继承作为面向对象编程的一种基本特征,其使用频率非常高。而继承包含了虚拟继承和普通继承,在可见性上分为public、protected、private。可见性继承比较简单,而虚拟继承对学习c++的难度较大。

  首先,虚拟继承与普通继承的区别有:

  假设derived 继承自base类,那么derived与base是一种“is a”的关系,即derived类是base类,而反之错误;

  假设derived 虚继承自base类,那么derivd与base是一种“has a”的关系,即derived类有一个指向base类的vptr。(貌似有些牵强!某些编译器确实如此)

  因此虚继承可以认为不是一种继承关系,而可以认为是一种组合的关系。正是因为这样的区别,下面我们针对虚拟继承来具体分析。虚拟继承中遇到广泛的是菱形结构。下面从菱形虚继承结构说起吧:

class stream
{
public:
    stream(){cout<<"stream::stream()!"<<endl;}
};

class iistream:virtual stream
{
public:
    iistream(){cout<<"istream::istream()!"<<endl;}
};

class oostream:virtual stream
{
public:
    oostream(){cout<<"ostream::ostream()!"<<endl;}
};

class iiostream:public iistream,public oostream
{
public:
    iiostream(){cout<<"iiostream::iiostream()!"<<endl;}
};

int main(int argc, const char * argv[])
{
    iiostream oo;
};

  程序运行的输出结果为:

  stream::stream()!
  istream::istream()!
  ostream::ostream()!
  iiostream::iiostream()!

  输出这样的结果是毫无悬念的!本来虚拟继承的目的是当多重继承出现重复的基类时,其只保存一份基类。减少内存开销。其继承结构为:

  stream
  /              
  istream   ostream
                   /
  iiostream

  这样子的菱形结构,使公共基类只产生一个拷贝。

  从基类 stream 派生新类时,使用 virtual 将类stream说明为虚基类,这时派生类istream、ostream包含一个指向虚基类的vptr,而不会产生实际的stream空间。所以终iiostream也含有一个指向虚基类的vptr,调用stream中的成员方法时,通过vptr去调用,不会产生二义性。