虚拟模板解决方法

时间:2011-06-10 12:24:41

标签: c++ oop templates inheritance virtual

我有一个模板容器类,我从名为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.
{
    // ...
}

2 个答案:

答案 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;
}

除非相关的特定成员函数具有独立的模板参数,否则成员函数不是模板,可以是虚拟的,无论它是否是从类模板生成的。