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