c++中同时用virtual和template
今天面试,被问到了这个问题。所以特意写个博文总结下。
首先明确,静多态指编译器多态,一般通过模板的方式来实现,比如SFINAF机制。
动多态一般使用虚表机制来实现。
先看场景一:
//
// Created by blacksungrass on 2022/3/8.
//
#include <iostream>
using namespace std;
template <typename T>
struct B{
T b;
B():b(2){}
virtual void print(){
cout<<b<<endl;
}
};
template <typename T>
struct A:public B<T>{
T a;
A():a(1){}
void print() override{
cout<<a<<endl;
}
};
int main(){
auto p = new A<double>();
p->print();
return 0;
}
以上代码是可以正确运行的
再看场景二:
//
// Created by blacksungrass on 2022/3/8.
//
#include <iostream>
using namespace std;
struct B{
template<typename T>
virtual void print(){
cout<<"i am B"<<endl;
}
};
struct A:public B{
template<typename T>
virtual void print() override{
cout<<"i am A"<<endl;
}
};
int main(){
B* p = new A();
p->print<>();
return 0;
}
这个编译的话就会报错:error C2898: “void B::print(void)”: 成员函数模板不能是虚拟的
现在知道了,会报错。但更深一层,这个报错,是语言规定嘛?还是现有的编译器不支持?还是原理上就无法支持?
参考:https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#t83-do-not-declare-a-member-function-template-virtual
可以看到cpp语言上应该是不支持这个操作的。理由是”如果支持的话,只有到链接时才能生成虚函数表。“。