Overriding template methods
我正在尝试重写模板方法。下面是一个最小的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | #include <iostream> class Base { public: template <typename T> void print(T var) { std::cout <<"This is a generic place holder! "; } }; class A: public Base { public: template <typename T> void print(T var) { std::cout <<"This is A printing" << var <<" "; } }; class B: public Base { public: template <typename T> void print(T var) { std::cout <<"This is B printing" << var <<" "; } }; 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; } |
两种情况下的输出都是
如果该方法不是模板,我可以将其定义为
这两个调用都调用
现在,通过
解决这个问题的一种方法是类型擦除。您可以使用boost.typeerasure执行以下操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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! "; } }; struct A : Base { void print(any_streamable var) { std::cout <<"This is A printing" << var <<" "; } }; |
对于简单的事情,比如流媒体,你也可以不需要图书馆就自己写。
虽然非特定化模板方法是虚拟的(例如,vtable会是什么样子?)值得指出的是,模板方法的专门化不可能是虚拟的,这对于允许它是非常有益的。我把它提交给C++委员会作为N3405中的最后一节。到目前为止,委员会还没有考虑到这一点,但我还有更老的文件要考虑,所以还是有希望的:)
首先,成员函数模板不能是虚拟的,派生类中的成员函数模板不能重写基类中的虚拟成员函数。
作为代码,指针的类型是base*,因此在模板成员函数实例化中,会实例化base中的函数,这就是为什么调用函数是base的原因。
如果使用a*和b*,子级中的函数将被实例化并调用。