虚拟模板解决方案

Virtual Template Workarounds

本文关键字:解决方案 虚拟      更新时间:2023-10-16

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

这不是非法的,只有模板虚拟成员函数是非法的。

// 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模板,你和我都很了解它们,但它们还不是一个初学者的话题,在下一个标准中不推荐使用)

您似乎对模板的组成感到困惑。类模板可能具有虚拟函数,事实上,这些模板参数可能出现在这些函数的签名中。

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

除非有问题的特定成员函数有自己的、独立的模板参数,否则该成员函数不是模板,并且可能是虚拟的,无论它是否从类模板生成。