今天面试,被问到了这个问题。所以特意写个博文总结下。

首先明确,静多态指编译器多态,一般通过模板的方式来实现,比如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语言上应该是不支持这个操作的。理由是”如果支持的话,只有到链接时才能生成虚函数表。“。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注