我有一个模板容器类,我从名为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 :(得分: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
ed模板,你和我对它们了解很多,但它们不是一个初学者话题,并且在下一个标准中被弃用了)
答案 1 :(得分: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;
}
除非相关的特定成员函数具有独立的模板参数,否则成员函数不是模板,可以是虚拟的,无论它是否是从类模板生成的。