菱形继承
继承是面向对象中实现复用的一个机制,通过继承定义的一个类,可以共享公共的东西,而各自实现本质不同的东西。
在单继承下,这种由继承机制支持的、特殊形式的按值组合提供了最有效、最紧凑的对象表示。在多继承下,当一个基类在派生类中多次出现时就会出现问题。最主要的一个例子是 iostream
类的层次结构模型。如下图:
(图片来源:http://blog.csdn.net/lostspeed/article/details/50431402)
如上图所示:istream
和 ostream
都从抽象 ios
基类派生而来, 而 iostream
类又继承了 istream
和 ostream
两个类,这种情况下,每个 iostream
类的对象都包含两个 ios
类的子对象:在 istream
和 ostream
中子对象的实例,保存两个相同的副本,对内存来说是一种浪费,更严重的地方在于:两个实例所造成的二义性问题。
这是一种典型的菱形继承所造成的二义性问题。如下:
当在 Assistant
中访问成员 _name
时,到底该访问哪份实例。下面这份代码会出现编译时错误:
class Person{
public:
//...
private:
string _name;
};
class Student: public Person{
//Student继承了Person类
public:
//...
protected:
int _num;
};
class Teacher : public Person{ //Teacher也继承了Person类
public:
//...
protected:
int _id;
};