【问题标题】:Virtual Template Workarounds虚拟模板变通办法
【发布时间】:2011-09-12 11:23:45
【问题描述】:

我有一个名为MyContainer 的模板容器类。 MyContainer 定义了诸如Get()Set() 等方法来访问单个元素。我想将一个位域类实现为MyContainer<char>,其中每个char 元素包含CHAR_BIT 位数。但是,为了允许用户对单个位而不是整个字节进行操作,我必须将 Get()Set() 设为虚拟,这是非法的。有哪些替代方案?

我想在派生类中定义GetBit()SetBit(),但这会违反里氏替换原则。 (想想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.
{
    // ...
}

【问题讨论】:

标签: c++ oop templates inheritance virtual


【解决方案1】:

不违法,只有模板虚成员函数才是。

// 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()
{
    // ...
}

但是,请注意定义必须在模板实例化时可见。所以要么把它也放在头文件中(或者放在一个额外的头文件中,然后将它包含到你的真实头文件中),或者把它放在类体中。

(现在请不要提及exported 模板,你和我都非常了解它们,但它们并不是一个初学者主题,并且在下一个标准中已弃用)

【讨论】:

  • 虽然成员函数是模板;他们在返回值和参数中使用类的模板参数。
  • @Maxpm:这无关紧要。如果它们本身没有模板参数,那么它们就不是模板。
  • @phresnel @DeadMG 我在 OP 中添加了一个简化示例。
  • @Maxpm:如果您的编译器拒绝该代码,那么它是错误。哦,除了你不应该把virtual放在那里。
  • @DeadMG:有时,编译器是错误的,尤其是非常过时的编译器。 @Maxpm:正如 DeadMG 指出的那样,在定义成员函数时,必须省略 virtual。它只是类体内声明的一部分。
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 2021-06-16
    • 2016-09-28
    • 2011-12-19
    • 1970-01-01
    • 2014-10-25
    • 2011-11-28
    • 1970-01-01
    • 2015-12-21
    相关资源
    最近更新 更多