2011-06-10 53 views
1

我有一個模板容器類,我從MyContainer派生。 MyContainer定義了像Get()Set()等方法來訪問各個元素。我想做一個位字類實現爲MyContainer<char>,其中每個char元素擁有CHAR_BIT位數。但是,爲了允許用戶在單個位而不是整個字節上操作,我必須使Get()Set()爲虛擬,這是非法的。有什麼替代品?虛擬模板變通辦法

我正在考慮在派生類中定義GetBit()SetBit(),但這會違反Liskov替換原則。 (認爲​​一個SortMyContainer()功能的。)

編輯:這裏是一個簡化的例子:

template <typename Datatype> 
struct MyContainer 
{ 
    virtual Datatype Get(); 
}; 

template <typename Datatype> // Error: Templates may not be virtual. 
virtual Datatype MyContainer<Datatype>::Get() // EDIT: The problem was on this line. The "virtual" keyword should only appear with the function declaration. 
{ 
    // ... 
} 
+0

我可以向你傳授NVI模式或模板方法嗎?見http://www.gotw.ca/publications/mill18.htm。 STL通常是遵循這個原則來實施的。 – 2011-06-10 13:13:22

回答

4

它不是非法的,只有模板虛擬成員函數。

// valid 
template<typename T> class MyContainer { 
    virtual void set(const T &) = 0; 
} 

// not valid 
class MyContainer { 
    template <typename T> virtual void set (const T &) = 0; 
} 

如果我弄錯了,請考慮放置代碼示例。您的示例代碼添加後

編輯:

template <typename Datatype> 
virtual // <-- nope, not here 
Datatype MyContainer<Datatype>::Get() 
{ 
    // ... 
} 

virtual只是類體內聲明的一部分。這應該是有效的:

template <typename Datatype> 
Datatype MyContainer<Datatype>::Get() 
{ 
    // ... 
} 

但是,請注意定義必須在模板實例化點處可見。因此,也可以將它放在頭文件中(或者放入一個額外的頭文件中,然後將其包含在您的真頭文件中),或者將其保留在類體中。

(請人提export編輯模板現在,你我都知道了他們很多,但他們並不完全是初學者的話題,並與一個標準不建議使用)

+0

但是,成員函數是模板;他們在返回值和參數中使用類的模板參數。 – Maxpm 2011-06-10 12:32:25

+0

小心舉個例子嗎? ;) – 2011-06-10 12:32:59

+0

@Maxpm:這是無關緊要的。如果他們自己沒有模板參數,那麼他們不是模板。 – Puppy 2011-06-10 12:34:40

3

你顯得無所適從構成一個模板。類模板可能具有虛函數,實際上,這些模板參數可能出現在這些函數的簽名中。

template<typename T> class an_interface { 
    virtual T Get() = 0; 
}; 
class a_class : public an_interface<int> { 
}; 

這是完全有效的。什麼是不完全有效的是

class an_interface { 
    template<typename T> virtual T Get() = 0; 
} 

除非有關具體成員函數都有它自己的,獨立的模板參數,成員函數不是一個模板,可以是虛擬的,不管它是否是從類模板產生的。