虚拟继承是C++语言中一个非常重要但是又比较生僻的存在,它的定义非常简单,但是对于理解C++的继承机制却是非常有用的。笔者最近学习过程中发现对C++的虚拟继承不是很明朗,故在这里对虚继承做个小结。
首先说下遇到的问题吧。代码如下(代码来自于何海涛《程序员面试精选100题第32题)。意图是要设计一个不能被继承的类,类似java中的final。但是又可以生成栈对象,可以像一般的C++类一样使用。
#include
using std::endl;
using std::cout;
template
{
friend T;
private:
MakeFinal()
{
cout<<"in MakeFinal"< } ~MakeFinal(){} }; class FinalClass: virtual public MakeFinal { public: FinalClass() { cout<<"in FinalClass"< } ~FinalClass(){} }; class Try: public FinalClass { public: Try() { cout<<"in Try"< } }; 这样的确使得FinalClass不能被继承了,原因在于类FinalClass是从类MakeFinal 1、为什么需要虚继承 由于C++支持多重继承,那么在这种情况下会出现重复的基类这种情况,也就是说可能出现将一个类两次作为基类的可能性。比如像下面的情况 #include 编译时的错误如下 虚继承的特点是,在任何派生类中的virtual基类总用同一个(共享)对象表示,正是如上图所示。
using std::cout;
using std::endl;
class Base
{
protected:
int value;
public:
Base()
{
cout<<"in Base"<
};
class DerivedA:protected Base
{
public:
DerivedA()
{
cout<<"in DerivedA"<
};
class DerivedB: protected Base
{
public:
DerivedB()
{
cout<<"in DerivedB"<
};
class MyClass:DerivedA,DerivedB
{
public:
MyClass()
{
cout<<"in MyClass"<
};
这中情况下会造成在MyClass中访问value时出现路径不明确的编译错误,要访问数据,就需要显示地加以限定。变成DerivedA::value或者DerivedB::value,以消除歧义性。并且,通常情况下,像Base这样的公共基类不应该表示为两个分离的对象,而要解决这种问题就可以用虚基类加以处理。如果使用虚继承,编译便正常了,类的结构示意图便如下。