C++虚继承下派生类虚方法定义规则的正确理解咨询
对C++虚继承与纯虚函数规则的正确理解
你看到的维基百科中加粗的两条规则表述是完全错误的,属于对C++核心规则的误解,纯虚函数的实现要求和是否使用虚继承没有任何绑定关系。
C++抽象类与纯虚函数的真实规则
C++标准中对纯虚函数、抽象类的约束只有核心一条:
- 只要一个类中存在未被实现的纯虚函数(无论是自身声明的,还是从基类继承的),这个类就是抽象类
- 抽象类唯一的使用限制是不能被直接实例化,除此之外没有额外约束:任何派生类(无论继承时是否加
virtual关键字)都可以选择不实现继承来的纯虚函数,只要你不尝试创建这个类的实例,代码就完全合法。未实现的纯虚函数会继续向下传递,直到某个派生类实现了所有纯虚函数,这个派生类才成为可以实例化的具体类。
为什么维基的示例会造成误导
维基示例里的注释写“因为B、C虚继承A,所以不需要实现纯虚方法”是完全的因果错配:
示例中的B、C类不管用不用虚继承,只要不实现pure_virtual_test,就都是抽象类,本身就不能被实例化。代码里真正实例化的是D类——D实现了A的纯虚方法,所以D是可以正常实例化的具体类,它的派生类E不需要重复实现已经被D实现的纯虚方法,这和B、C是否虚继承A没有任何关系。
你自己写的非虚继承验证代码能正常编译运行,恰恰证明了这一点:你的代码里B类非虚继承A,也没有实现纯虚函数,但你从来没有尝试实例化B,只实例化了实现了纯虚函数的D、E类,完全符合C++标准,没有任何问题。
补充说明
虚继承的唯一作用是解决菱形继承场景下公共基类子对象重复拷贝的问题,它只会影响派生类的构造逻辑(虚继承的公共基类需要由最底层的派生类负责构造),完全不参与纯虚函数实现、抽象类判定的相关逻辑。维基那段表述把两个完全不相关的C++特性强行绑定,属于典型的事实错误。
// 非虚继承下中间类不实现纯虚函数的合法示例 #include <string> #include <iostream> class A { protected: std::string _msg; public: A(std::string x): _msg(x) {} void test(){ std::cout<<"hello from A: "<<_msg <<"\n"; } virtual void pure_virtual_test() = 0; }; // 非虚继承A,不实现纯虚函数,B是抽象类,不可实例化 class B: public A { public: B(std::string x):A("b"){} }; // D实现了纯虚函数,是具体类,可以实例化 class D: public B { public: D(std::string x):B("d_b"){} void pure_virtual_test() override { std::cout<<"pure virtual hello from: "<<_msg <<"\n"; } }; // E继承自已经实现了纯虚函数的D,不需要重复实现 class E: public D { public: E(std::string x):D("e_d"){} }; int main(int argc, char ** argv){ D d("d"); d.test(); d.pure_virtual_test(); E e("e"); e.test(); e.pure_virtual_test(); }
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

