C++继承汇总(单继承、多继承、虚继承、菱形继承)
一、C++中的对象模型
1、 概念
语言中直接支持面向对象程序设计的部分;
对于各种支持的底层实现机制。(没看懂……)
2、 类中的成员分类
a) 成员函数
i. static function
ii. non static function
iii. virtual function
b) 数据成员
i. static member data
ii. non static member data
3、 C++对象模型
a) 类对象内存布局中的包括
i. non static member data
ii. vptr(虚函数表指针)
iii. vbptr(虚基类表指针)
b) 不包括
i. static member data(存储在静态存储区)
ii. 成员函数(存储在代码区)
c) virtual table
简称vtbl。存放着指针,这些指针指向该类每一个虚函数。虚表中的函数地址将按声明时的顺序排列。vtbl在类声明后就形成了,vptr是编译器生成的。
d) vptr的位置一般放在一个类对象的最前端。
e) 虚基类表
vbptr指向的表,用于存放虚继承中,虚基类存储相对于虚基类表指针的偏移量。
二、继承类型
1、普通继承(不包含虚函数)
a、单继承
class Base { public: Base (int a = 1):base(a){} void fun0(){cout << base << endl;} int base; }; class Derive:public Base { public: Derive (int a = 2):derive(a){} void fun1(){cout << base1 << endl;} int derive; };
b、多继承
class Base1 { public: Base1 (int a = 2):base1(a){} void fun1(){cout << base1 << endl;} int base1; }; class Base2 { public: Base2 (int a = 3):base2(a){} void fun2(){cout << base2 << endl;} int base2; }; class Derive: public Base1, public Base2 { public: Derive (int value = 4):derive (value){} void fun3(){cout << derive << endl;} int derive; };
c、菱形继承
class Base { public: Base (int a = 1):base(a){} void fun0(){cout << base << endl;} int base; }; class Base1:public Base { public: Base1 (int a = 2):base1(a){} void fun1(){cout << base1 << endl;} int base1; }; class Base2:public Base { public: Base2 (int a = 3):base2(a){} void fun2(){cout << base2 << endl;} int base2; }; class Derive: public Base1, public Base2 { public: Derive (int value = 4):derive (value){} void fun3(){cout << derive << endl;} int derive; };
注:菱形继承存在二义性问题,编译都不通过,只能通过指定特定基类的方式进行访问基类变量。
Derive d;
d.base =3; // 不正确
d.Base1::base = 3; // 正确
2、普通继承(包含虚函数)
a、单继承(包含虚函数)
class Base { public: Base (int a = 1):base(a){} virtual void fun0(){cout << base << endl;} int base; }; class Derive:public Base { public: Derive (int a = 2):derive(a){} virtual void fun0(){}; virtual void fun1(){cout << derive << endl;} int derive; };
注:派生类中新增的虚函数追加到虚函数表后面。
b、多继承(包含虚函数)
class Base1 { public: Base1 (int a = 2):base1(a){} virtual void fun1(){cout << base1 << endl;} int base1; }; class Base2 { public: Base2 (int a = 3):base2(a){} virtual void fun2(){cout << base2 << endl;} int base2; }; class Derive: public Base1, public Base2 { public: Derive (int value = 4):derive (value){} virtual void fun3(){cout << derive << endl;} int derive; };
注:派生类中新增的虚函数,追加到第一个基类的虚函数表的后面。
c、菱形继承(包含虚函数)
class Base { public: Base (int a = 1):base(a){} virtual void fun0(){cout << base << endl;} int base; }; class Base1:public Base { public: Base1 (int a = 2):base1(a){} virtual void fun1(){cout << base1 << endl;} int base1; }; class Base2:public Base { public: Base2 (int a = 3):base2(a){} virtual void fun2(){cout << base2 << endl;} int base2; }; class Derive: public Base1, public Base2 { public: Derive (int value = 4):derive (value){} virtual void fun3(){cout << derive << endl;} int derive; };
注:分析时,由上到下依次分析。存在二义性问题和内存冗余问题。
3、虚继承(不包含虚函数)
新增虚基类指针,指向虚基类表,虚基类表中首项存储虚基类指针的偏移量,接下来依次存储虚基类的偏移量(偏移量是相对于虚基类表指针的存储地址)。
a、单虚继承(不包含虚函数)
class Base { public: Base (int a = 1):base(a){} void fun0(){cout << base << endl;} int base; }; class Base1:virtual public Base { public: Base1 (int a = 2):base1(a){} void fun1(){cout << base1 << endl;} int base1; };
b、多虚继承(不包含虚函数)
class Base1 { public: Base1 (int a = 2):base1(a){} void fun1(){cout << base1 << endl;} int base1; }; class Base2 { public: Base2 (int a = 3):base2(a){} void fun2(){cout << base2 << endl;} int base2; }; class Derive:virtual public Base1, virtual public Base2 { public: Derive (int value = 4):derive (value){} void fun3(){cout << derive << endl;} int derive; };
c、菱形虚继承(不包含虚函数)
第一种形式:
class Base { public: Base (int a = 1):base(a){} void fun0(){cout << base << endl;} int base; }; class Base1:virtual Base { public: Base1 (int a = 2):base1(a){} void fun1(){cout << base1 << endl;} int base1; }; class Base2:virtual Base { public: Base2 (int a = 3):base2(a){} void fun2(){cout << base2 << endl;} int base2; }; class Derive:virtual public Base1, virtual public Base2 { public: Derive (int value = 4):derive (value){} void fun3(){cout << derive << endl;} int derive; };
注:分析派生类的内存分布时,也是由上到下分析。虚继承将基类置于内存末尾,但是置于末尾的顺序也有一定的次序。首先Base先放到末尾,然后Base1放到末尾,最后Base2放到末尾。
第二种形式:
class Base { public: Base (int a = 1):base(a){} void fun0(){cout << base << endl;} int base; }; class Base1:virtual public Base { public: Base1 (int a = 2):base1(a){} void fun1(){cout << base1 << endl;} int base1; }; class Base2:virtual public Base { public: Base2 (int a = 3):base2(a){} void fun2(){cout << base2 << endl;} int base2; }; class Derive: public Base1, public Base2 { public: Derive (int value = 4):derive (value){} void fun3(){cout << derive << endl;} int derive; };
注:分析的原则,从上到下,依次分析。
4、 虚继承(包含虚函数)
a、单虚继承(包含虚函数)
class Base { public: Base (int a = 1):base(a){} virtual void fun0(){cout << base << endl;} int base; }; class Base1:virtual Base { public: Base1 (int a = 2):base1(a){} virtual void fun1(){cout << base1 << endl;} int base1; };
与普通的包含虚函数的单继承相比,派生类拥有自己的虚函数表以及虚函数表指针,而不是与基类共用一个虚函数表。注意虚函数表指针和虚基类表指针的存储顺序。
b、多虚继承(包含虚函数)
class Base1 { public: Base1 (int a = 2):base1(a){} virtual void fun1(){cout << base1 << endl;} int base1; }; class Base2 { public: Base2 (int a = 3):base2(a){} virtual void fun2(){cout << base2 << endl;} int base2; }; class Derive:virtual public Base1, virtual public Base2 { public: Derive (int value = 4):derive (value){} virtual void fun3(){cout << derive << endl;} int derive; };
c、菱形虚继承(包含虚函数)
第一种形式:
class Base { public: Base (int a = 1):base(a){} virtual void fun0(){cout << base << endl;} int base; }; class Base1:virtual public Base { public: Base1 (int a = 2):base1(a){} virtual void fun1(){cout << base1 << endl;} int base1; }; class Base2:virtual public Base { public: Base2 (int a = 3):base2(a){} virtual void fun2(){cout << base2 << endl;} int base2; }; class Derive: public Base1, public Base2 { public: Derive (int value = 4):derive (value){} virtual void fun3(){cout << derive << endl;} int derive; };
第二种形式:
class Base { public: Base (int a = 1):base(a){} virtual void fun0(){cout << base << endl;} int base; }; class Base1:virtual public Base { public: Base1 (int a = 2):base1(a){} virtual void fun1(){cout << base1 << endl;} int base1; }; class Base2:virtual public Base { public: Base2 (int a = 3):base2(a){} virtual void fun2(){cout << base2 << endl;} int base2; }; class Derive: virtual public Base1,virtual public Base2 { public: Derive (int value = 4):derive (value){} virtual void fun3(){cout << derive << endl;} int derive; };
自行脑补C++类对象的内存结构……
注:上述虚函数中,如果派生类重写了基类的虚函数,则对应虚函数表中的虚函数应该修改成重新后的虚函数,即Base::fun()->Derive::fun()。
参考链接:
http://www.cnblogs.com/raichen/p/5744300.html