C++虛繼承的概念
http://blog.csdn.net/wangxingbao4227/article/details/6772579
C++中虛擬繼承的概念
為了解決從不同途徑繼承來的同名的資料成員在記憶體中有不同的拷貝造成資料不一致問題,將共同基類設定為虛基類。這時從不同的路徑繼承過來的同名資料成員在記憶體中就只有一個拷貝,同一個函式名也只有一個對映。這樣不僅就解決了二義性問題,也節省了記憶體,避免了資料不一致的問題。
class 派生類名:virtual 繼承方式 基類名
virtual是關鍵字,宣告該基類為派生類的虛基類。
在多繼承情況下,虛基類關鍵字的作用範圍和繼承方式關鍵字相同,只對緊跟其後的基類起作用。
宣告瞭虛基類之後,虛基類在進一步派生過程中始終和派生類一起,維護同一個基類子物件的拷貝。
C++虛擬繼承
◇概念:
C++使用虛擬繼承(Virtual Inheritance),解決從不同途徑繼承來的同名的資料成員在記憶體中有不同的拷貝造成資料不一致問題,將共同基類設定為虛基類。這時從不同的路徑繼承過來的同名資料成員在記憶體中就只有一個拷貝,同一個函式名也只有一個對映。
◇解決問題:
解決了二義性問題,也節省了記憶體,避免了資料不一致的問題。
◇同義詞:
虛基類(把一個動詞當成一個名詞而已)
當在多條繼承路徑上有一個公共的基類,在這些路徑中的某幾條匯合處,這個公共的基類就會產生多個例項(或多個副本),若只想儲存這個基類的一個例項,可以將這個公共基類說明為虛基類。
◇語法:
class 派生類: virtual 基類1,virtual 基類2,...,virtual 基類n
{
...//派生類成員宣告
};
◇執行順序
首先執行虛基類的建構函式,多個虛基類的建構函式按照被繼承的順序構造;
執行基類的建構函式,多個基類的建構函式按照被繼承的順序構造;
執行成員物件的建構函式,多個成員物件的建構函式按照申明的順序構造;
執行派生類自己的建構函式;
析構以與構造相反的順序執行;
mark
從虛基類直接或間接派生的派生類中的建構函式的成員初始化列表中都要列出對虛基類建構函式的呼叫。但只有用於建立物件的最派生類的建構函式呼叫虛基類的建構函式,而該派生類的所有基類中列出的對虛基類的建構函式的呼叫在執行中被忽略,從而保證對虛基類子物件只初始化一次。
在一個成員初始化列表中同時出現對虛基類和非虛基類建構函式的呼叫時,虛基類的建構函式先於非虛基類的建構函式執行。
◇因果:
多重繼承->二義性->虛擬繼承解決
◇二義性:
1: //-----------------------------------------------------
2: //名稱:blog_virtual_inherit.cpp
3: //說明:C++虛擬繼承學習演示
4: //環境:VS2005
5: //blog:pppboy.blog.163.com
6: //----------------------------------------------------
7: #include "stdafx.h"
8: #include <iostream>
9: using namespace std;
10:
11: //Base
12: class Base
13: {
14: public:
15: Base(){cout << "Base called..."<< endl;}
16: void print(){cout << "Base print..." <<endl;}
17: private:
18: };
19:
20: //Sub
21: class Sub //定義一個類 Sub
22: {
23: public:
24: Sub(){cout << "Sub called..." << endl;}
25: void print(){cout << "Sub print..." << endl;}
26: private:
27: };
28:
29: //Child
30: class Child : public Base , public Sub //定義一個類Child 分別繼承自 Base ,Sub
31: {
32: public:
33: Child(){cout << "Child called..." << endl;}
34: private:
35: };
36:
37: int main(int argc, char* argv[])
38: {
39: Child c;
40:
41: //不能這樣使用,會產生二意性,VC下error C2385
42: //c.print();
43:
44: //只能這樣使用
45: c.Base::print();
46: c.Sub::print();
47:
48: system("pause");
49: return 0;
50: }
◇多重繼承:
1: //-----------------------------------------------------
2: //名稱:blog_virtual_inherit.cpp
3: //說明:C++虛擬繼承學習演示
4: //環境:VS2005
5: //blog:pppboy.blog.163.com
6: //----------------------------------------------------
7: #include "stdafx.h"
8: #include <iostream>
9: using namespace std;
10:
11: int gFlag = 0;
12:
13: class Base
14: {
15: public:
16: Base(){cout << "Base called : " << gFlag++ << endl;}
17: void print(){cout << "Base print" <<endl;}
18: };
19:
20: class Mid1 : public Base
21: {
22: public:
23: Mid1(){cout << "Mid1 called" << endl;}
24: private:
25: };
26:
27: class Mid2 : public Base
28: {
29: public:
30: Mid2(){cout << "Mid2 called" << endl;}
31: };
32:
33: class Child:public Mid1, public Mid2
34: {
35: public:
36: Child(){cout << "Child called" << endl;}
37: };
38:
39: int main(int argc, char* argv[])
40: {
41: Child d;
42:
43: //不能這樣使用,會產生二意性
//d.print();
45:
46: //只能這樣使用
47: d.Mid1::print();
48: d.Mid2::print();
49:
50: system("pause");
51: return 0;
52: }
53:
//output
Base called : 0
Mid1 called
Base called : 1
Mid2 called
Child called
Base print
Base print
◇虛擬繼承
在派生類繼承基類時,加上一個virtual關鍵詞則為虛擬繼承
1: //-----------------------------------------------------
2: //名稱:blog_virtual_inherit.cpp
3: //說明:C++虛擬繼承學習演示
4: //環境:VS2005
5: //blog:pppboy.blog.163.com
6: //----------------------------------------------------
7: #include "stdafx.h"
8: #include <iostream>
9: using namespace std;
10:
11: int gFlag = 0;
12:
13: class Base
14: {
15: public:
16: Base(){cout << "Base called : " << gFlag++ << endl;}
17: void print(){cout << "Base print" <<endl;}
18: };
19:
20: class Mid1 : virtual public Base
21: {
22: public:
23: Mid1(){cout << "Mid1 called" << endl;}
24: private:
25: };
26:
27: class Mid2 : virtual public Base
28: {
29: public:
30: Mid2(){cout << "Mid2 called" << endl;}
31: };
32:
33: class Child:public Mid1, public Mid2
34: {
35: public:
36: Child(){cout << "Child called" << endl;}
37: };
38:
39: int main(int argc, char* argv[])
40: {
41: Child d;
42:
43: //這裡可以這樣使用
44: d.print();
45:
46: //也可以這樣使用
47: d.Mid1::print();
48: d.Mid2::print();
49:
50: system("pause");
51: return 0;
52: }
53:
//output
1: Base called : 0
2: Mid1 called
3: Mid2 called
4: Child called
5: Base print
6: Base print
7: Base print
8: 請按任意鍵繼續. . .
◇通過輸出的比較
1.在多繼承情況下,虛基類關鍵字的作用範圍和繼承方式關鍵字相同,只對緊跟其後的基類起作用。
2.宣告瞭虛基類之後,虛基類在進一步派生過程中始終和派生類一起,維護同一個基類子物件的拷貝。
3.觀察類建構函式的構造順序,拷貝也只有一份。
◇與虛擬函式關係
虛擬繼承與虛擬函式有一定相似的地方,但他們之間是絕對沒有任何聯絡的。
再想一次:虛擬繼承,虛基類,虛擬函式。
相關文章
- c++ 虛繼承詳解C++繼承
- C++中的虛繼承的構造C++繼承
- 菱形繼承,虛繼承繼承
- 虛繼承繼承
- C++ 虛擬函式和虛繼承淺析C++函式繼承
- C++繼承二之虛擬函式C++繼承函式
- C++ 繼承、多型、虛擬函式C++繼承多型函式
- C++繼承一之公有繼承C++繼承
- C++中公有繼承、保護繼承、私有繼承的區別C++繼承
- C++繼承C++繼承
- C++知識點隨筆(五):虛繼承C++繼承
- C++ 虛繼承 物件記憶體佈局C++繼承物件記憶體
- C++虛繼承原理與類佈局分析C++繼承
- C++中的繼承C++繼承
- C++繼承詳解:共有(public)繼承,私有(private)繼承,保護(protected)繼承C++繼承
- C++單繼承、多繼承情況下的虛擬函式表分析C++繼承函式
- C++ | 類繼承C++繼承
- C++菱形繼承C++繼承
- 物件導向之_繼承概念物件繼承
- 多重繼承及虛繼承中物件記憶體的分佈繼承物件記憶體
- C++繼承體系C++繼承
- 虛擬繼承的意義 (轉)繼承
- c++中的繼承關係C++繼承
- C++多繼承的細節C++繼承
- C++繼承三之純虛擬函式pure virtual functionC++繼承函式Function
- 菱形繼承與虛基類繼承
- [C++]繼承和派生類C++繼承
- 說說C++多重繼承C++繼承
- c++ 記憶體 繼承C++記憶體繼承
- C++ 整理15_繼承C++繼承
- C++ protected繼承意義C++繼承
- C++的核心特性:繼承機制C++繼承
- C++繼承時的修飾符C++繼承
- odoo 繼承(owl繼承、web繼承、view繼承)Odoo繼承WebView
- C++高階教程之繼承得本質:單繼承(一)C++繼承
- C++學習筆記——C++ 繼承C++筆記繼承
- C++ 記憶體分佈之菱形繼承(無虛擬函式)C++記憶體繼承函式
- C++繼承:公有,私有,保護C++繼承