2011-06-10 55 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; 
} 

除非有关具体成员函数都有它自己的,独立的模板参数,成员函数不是一个模板,可以是虚拟的,不管它是否是从类模板产生的。