如何专门化在基类中定义为纯函数的模板化函数?
struct A {
virtual void func(int a) = 0;
//virtual void func(int a) {} // replace above line with this and it works
};
struct B : public A {
template<typename T> void func(T t) {
cout <<"hello"<<endl;
}
};
template<> void B::func<int>(int a) { cout <<"hello 2"<<endl; }
int main() {
B b;
b.func(2);
}
错误:
错误:变量类型'B'是抽象类 B b; ^注意:“ B”中未实现的纯虚方法“ func” 虚拟虚空func(int a)= 0;
答案 0 :(得分:5)
虚拟功能只能由非模板功能覆盖。在这种情况下,
然后Derived类中的此函数也是虚拟的(在声明中是否使用了关键字virtual),并覆盖了Base :: vf(在声明中是否使用了override这个词)。
请注意,功能模板不能为virtual functions;
不能将功能模板声明为虚拟模板。
根据标准,[temp.mem]/4
成员函数模板的专业化不能覆盖 基类的虚函数。 [示例:
class B { virtual void f(int); }; class D : public B { template <class T> void f(T); // does not override B::f(int) void f(int i) { f<>(i); } // overriding function that calls the template instantiation };
-示例]
关于您的问题,
如果将函数设为“不纯”,为什么会起作用?
消失了,但仍然无法正常工作。派生类中的函数模板不会覆盖基类的虚拟函数。您可以使用dynamic dispatch进行检查:
如果使用指针或对基类的引用来处理派生类,则对重写的虚函数的调用将调用派生类中定义的行为。
请注意,您应该使用指针或引用来进行动态调度,例如
B b;
A* pa = &b;
pa->func(2);
您还可以应用override specifier来帮助您确认覆盖。
答案 1 :(得分:1)
//virtual void func(int a) {}
//用此替换上面的行,并且有效
替换上面的行,代码将无法编译。
或者,更好的方法是有效的,但是却没有您期望的那样。
问题在于virtual
函数和template
函数不能很好地融合。
因此,您不能创建直接覆盖虚拟函数的模板函数:如果将func()
定义为空虚拟函数
virtual void func(int a) = 0;
在您没有定义有效的A
virtual
函数之前,基础func()
类以及所有派生类将变得无法实例化。
定义
virtual void func(int a) {}
A
基类以及所有派生类不再是不可实例化的,因为您不再需要重新定义虚拟函数。
但是template
func()
版本与虚函数无关。
当您在b.func(2)
中调用main()
时,将被称为template
,而不是继承自virtual
的{{1}} func()
。这是因为A
template
“隐藏”了func()
继承的func()
版本。
您可以在virtual
定义的主体中添加virtual
中的func()
B
版本的“取消隐藏”
B
通过这种方式,在using A::func;
中调用b.func(2);
,将调用main()
继承的virtual
版本,并A
的模板特化,因此{{ 1}}指令,不再执行。
现在...如果我理解正确,那么您需要一个func()
std::cout <<"hello 2" << std::endl;
函数,以便在template
的情况下加入虚拟专业化。
我看到的唯一方法是在func()
中定义T == int
virtual
override
并从B
专长中调用它
void func (int a) override // override, so necessarily virtual
{ std::cout <<"hello 2" << std::endl; }
以下是完整的编译示例
template
答案 2 :(得分:0)
这可能不是重点,但在使用模板进行设计时可以使用一个非常好的助记符:
虚拟函数-动态多态性(在运行时通过vtable解决)
模板专业化-静态多态性(在编译时通过类型信息解决)
不要试图彼此解决。
在您的情况下,您尝试通过模板专门化为虚拟方法提供主体(解决运行时多态性)。