C++中的類繼承之單繼承&多繼承&菱形繼承


 C++中的類繼承之單繼承&多繼承&菱形繼承

 

單繼承是一般的單一繼承,一個子類只 有一個直接父類時稱這個繼承關系為單繼承。這種關系比較簡單是一對一的關系:

多繼承是指 一個子類有兩個或以上直接父類時稱這個繼承關系為多繼承。這種繼承方式使一個子類可以繼承多個父類的特性。多繼承可以看作是單繼承的擴展。派生類具有多個基類,派生類與每個基類之間的關系仍可看作是一個單繼承。多繼承下派生類的構造函數與單繼承下派生類構造函數相似,它必須同時負責該派生類所有基類構造函數的調用。同時,派生類的參數個數必須包含完成所有基類初始化所需的參數個數。在子類的內存中它們是按照聲明定義的順序存放的,下面的截圖將清晰看到。
但是多繼承存在一個問題,要想研究這個問題,我們先從單繼承講起。來看內存空間:

class Base
{
public:
Base() {
cout << "B()" << endl;
}
int b1;
};
class Derive : public Base
{
public:
Derive() {
cout << "D()" << endl;
}
int d1; 
};
int main()
{
Test();
getchar();
return 0;
}

多繼承的內存空間:

class Base
{
public:
Base() {
cout << "B()" << endl;
}
int b1;
};
class C
{
public:
C() {
cout << "C()" << endl;
}
int c;
};
class Derive : public Base, public C
{
public:
Derive() {
cout << "D()" << endl;
}
int d1; 
};

菱形繼承內存中數據分布:

class A
{
public:
A() {
cout << "A()" << endl;
}
int a;
};
class Base:public A
{
public:
Base() {
cout << "B()" << endl;
}
int b1;
};
class C: public A
{
public:
C() {
cout << "C()" << endl;
}
int c;
};
class Derive : public Base, public C
{
public:
Derive() {
cout << "D()" << endl;
}
int d1; 
};
在A類中初始化int a=4則可清楚的看到菱形繼承中內存分布所以子類Derive中有兩份A類中的數據成員,這造成了訪問二義性和數據冗余的問題這就是我前面說的多繼承存在的問題。可以這樣訪問

1 tmp.C::a=4;
2 tmp.Base::a=5;

什么是對象模型

有兩個概念可以解釋C++對象模型:

1、語言中直接支持面向對象程序設計的部分。
2、對於各種支持的底層實現機制。

還有另外一個方法解決這個問題,我們要用到一種新的繼承方法:虛繼承--解決菱形繼承的二義性和數據冗余的問題。看下面這段代碼:

復制代碼
 1 class Base
 2 {
 3 public:
 4     Base() {
 5         cout << "B()" << endl;
 6     }
 7     int b1;
 8 };
 9 class Derive : virtual public Base
10 {
11 public:
12     Derive() {
13         cout << "D()" << endl;
14     }
15     int d1; 
16 };
17 void Test()
18 {
19     Derive tmp;
20     tmp.d1 = 1;
21     tmp.b1 = 2;
23 }
24 int main()
25 {
26     Test();
27     getchar();
28     return 0;
29 }
復制代碼

虛擬繼承的關鍵字---virtual

復制代碼
 1 class A
 2 {
 3 public:
 4     A() {
 5         cout << "A()" << endl;
 6     }
 7     int a ;
 8 };
 9 class Base : virtual public A
10 {
11 public:
12     Base() {
13         cout << "B()" << endl;
14     }
15     int b1;
16 };
17 class C:virtual public A
18 { 
19 public:
20     C() {
21         cout << "C()" << endl;
22     }
23     int c;
24 };
25 class Derive : virtual public Base, virtual public C
26 {
27 public:
28     Derive() {
29         cout << "D()" << endl;
30     }
31     int d1; 
32 };
33 void Test()
34 {
35     Derive tmp;
36     tmp.d1 = 1;
37     tmp.b1 = 2;
38     tmp.c = 3;
39     tmp.a = 4;
40 }
41 int main()
42 {
43     Test();
44     getchar();
45     return 0;
46 }
復制代碼

菱形虛擬繼承的對象模型解決二義性問題在vs環境下用的是偏移量,而不是圖中的直接指針指向這里只是為了更直觀的展示。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM