重写模板方法
Overriding template methods
我正在尝试覆盖模板方法。下面是一个最小示例:
#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
定义它,它将按预期工作(已经尝试过(,但它需要是一个模板。那么我做错了什么?
两个调用调用Base::print
的原因与print
是一个模板方法这一事实无关,而与它是非虚拟的事实有关。不管是什么print
,A::print
和B::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";
}
};
对于像流式传输这样简单的事情,您也可以自己编写,而无需库。
First 成员函数模板不能是虚拟的
,派生类中的成员函数模板不能重写基类中的虚拟成员函数。
作为您的代码,指针的类型为 Base*,因此在模板成员函数实例化中,Base 中的函数被实例化,这就是调用函数 is base 的原因。
如果使用 A* 和 B*,则将实例化并调用子项中的函数。
虽然非专用模板方法是虚拟的(例如,vtable会是什么样子?(,但值得指出的是,模板方法的专业化没有理由不是虚拟的,并且允许它有很大的好处。我将其作为 N3405 的最后一部分提交给C++委员会。委员会尚未考虑这一点,但我有更老的论文要考虑,所以仍然有希望:)
相关文章:
- 方法重写线程C++中的概念
- 将成员函数指针作为参数传递给模板方法
- 模板方法访问正向声明的类仅在没有此指针的情况下无法编译
- C++11:模板方法的模板函数调用无法编译?
- 如何从ECS中的模板方法获取组件?
- 使用 SFINAE 设计模板方法
- 一个模板方法,用于同时接受常量和非常量参数
- C++模板方法中的循环依赖关系
- 在 C++ 中使用模板方法重写类方法
- 类中的模板方法
- 基于枚举参数调用专用模板方法
- 模板中的模板方法 - 实例声明和类方法声明签名不同
- 可变参数模板方法
- 使用模板方法为标头提供空 cpp 时出现问题
- SFINAE 方法在 clang 中完全禁用基类的模板方法
- 将函数和成员函数传递给模板方法
- 从非模板类调用专用模板方法
- MSVC使用constexpr-if从可变模板方法中的基本模板参数中吞下const
- 用模板方法重写虚拟方法
- 重写模板方法