【问题标题】:Overriding template methods覆盖模板方法
【发布时间】:2015-02-14 20:05:50
【问题描述】:

我正在尝试覆盖模板方法。 这是一个最小的例子:

#include <iostream>

class Base
{
public:
    template <typename T>
    void print(T var)
    {
        std::cout << "This is a generic place holder!\n";
    }
};

class A: public Base
{
public:
    template <typename T>
    void print(T var)
    {
        std::cout << "This is A printing " << var << "\n";
    }
};

class B: public Base
{
public:
    template <typename T>
    void print(T var)
    {
        std::cout << "This is B printing " << var << "\n";
    }
};


int main()
{
    Base * base[2];
    base[1] = new A;
    base[2] = new B;

    base[1]->print(5);
    base[2]->print(5);

    delete base[1];
    delete base[2];
    return 0;
}

两种情况下的输出都是This is a generic place holder! 如何实现调用派生类的方法?

如果方法不是模板,我可以定义它virtual,它会按预期工作(已经尝试过),但它需要是模板。那我做错了什么?

【问题讨论】:

标签: c++ templates inheritance


【解决方案1】:

两个调用调用Base::print 的原因与print 是模板方法这一事实无关,而与它是非虚拟的事实有关。不管print 是什么,A::printB::print 都不会被考虑。

现在,通过Base* 实际调用A::print 的典型解决方案是简单地将print 设为virtual 方法。但是,这是不行的,因为print 是一个模板,您不能按规则拥有模板虚拟方法。

解决此问题的一种方法是类型擦除。您可以使用Boost.TypeErasure 执行以下操作:

typedef any<mpl::vector<
    copy_constructible<>,
    typeid_<>,
    ostreamable<>
> > any_streamable;

struct Base {
    virtual void print(any_streamable var) // not a template!
    {
        std::cout << "This is a generic place holder!\n";
    }        
};

struct A : Base {
    void print(any_streamable var) {
        std::cout << "This is A printing " << var << "\n";
    }
};

对于像流式传输这样简单的事情,您也可以自己编写而不需要库。

【讨论】:

    【解决方案2】:

    首先,成员函数模板不能是虚拟的,派生类中的成员函数模板不能覆盖基类中的虚拟成员函数。

    由于你的代码,指针的类型是Base*,所以在模板成员函数实例化中,Base中的函数被实例化,这就是函数被调用的原因。

    如果使用 A* 和 B*,子项中的函数将被实例化并调用。

    【讨论】:

    • 所以无法覆盖模板函数?
    • 是的,但这正是重点:只有一种类型的数组。基类在这里充当接口。所以想法是有一个基类数组来保存派生类元素。如前所述,当方法不是模板时,这可以正常工作。
    • 嗯,不是重点...假设我有一个变体向量,我想将工厂生产的一组异构值模板化。我需要一个基类的模板,并专门针对派生类中的每个变体用例? ...就我而言,这 IS 是重点;知识被推迟到它被知道的那一刻。例如,或者当该用例不受支持时抛出。
    【解决方案3】:

    虽然非特化模板方法是虚拟的没有意义(例如,vtable 会是什么样子?),但值得指出的是,模板方法的特化没有理由不能是虚拟的,并且允许它的显着好处。我将此作为N3405 中的最后一部分提交给了C++ 委员会。委员会尚未考虑这一点,但我还有更旧的论文正在考虑中,所以仍有希望:)

    【讨论】:

      猜你喜欢
      • 2011-07-24
      • 2012-09-15
      • 1970-01-01
      • 1970-01-01
      • 2012-11-28
      • 1970-01-01
      • 1970-01-01
      • 2014-08-30
      • 1970-01-01
      相关资源
      最近更新 更多