1. C++繼承與java不同,java遵循單繼承,但java的接口為其不足做了很好的彌補了。 C++則是靈活的多,為多繼承。即一個C++類可以同時繼承N個類的屬性。
2. 對於繼承方式 :
有三種: public ,private,protect,對於public繼承的類,其公有成員依然是公有成員,私有成員依舊是私有成員。
對於protect,private 則有限制 ,就好比一個水管,公有水管是最大號的,對於水的流量沒有限制。保護水管,是中等的號的,對於大號水管的流量使其變成中等流量,對於中等以下的不限制。私有水管,則是最小號的,對於大於私有水管限制的統統的改為私有水管的標准。 其中私有繼承,其實就是一種絕育的措施。就是以后的繼承就沒有太大意義。
3.對於繼承關於構造和析構順序原里的歸納:
看代碼:
1 #include<iostream> 2 using namespace std ; 3 4 class Base1 { 5 6 public : 7 Base1() { 8 cout << "Default Base1" << endl; 9 } 10 Base1(int i) { 11 cout << "Base1"<<i<< endl; 12 } 13 ~Base1() { 14 cout << "Base1 析構" << endl; 15 } 16 }; 17 18 class Base2 { 19 20 public : 21 Base2() { 22 cout << "Default Base2" << endl; 23 } 24 ~Base2() { 25 cout << "Base2 析構" << endl; 26 } 27 Base2(int i) { 28 cout << "Base2" << i << endl; 29 } 30 }; 31 class Base3 { 32 33 public : 34 Base3() { 35 cout << "Default Base3" << endl; 36 } 37 ~Base3() { 38 cout << "Base3 析構" << endl; 39 } 40 Base3(int i) { 41 cout << "Base3" << i << endl; 42 } 43 44 }; 45 46 47 class Derived : public Base1, public Base2, public Base3 //(1)先 在這兒開始構造從左到右 48 //析構則是從右到左 49 { 50 51 public : 52 Derived() { 53 cout << "Default Derived" << endl; 54 } 55 ~Derived() { 56 cout << "Derived 析構" << endl; 57 } 58 Derived( int a , int b , int c , int d ) 59 :men2(b),Base1(a),Base3(c), Base2(d),men1(b) { 60 cout << "Derived" << endl; 61 }; 62 63 private : 64 //構造從左到右 65 Base3 men3; 66 Base2 men2; 67 Base1 men1; 68 69 //析構則是從底部開始往上析構,先 Base 1,2,3 70 }; 71 72 int main(void ) { 73 74 Derived obj(1,2,3,4); 75 return 0; 76 77 }
結果:
Base11
Base24
Base33
Default Base3
Base22
Base12
Derived
Derived 析構
Base1 析構
Base2 析構
Base3 析構
Base3 析構
Base2 析構
Base1 析構
請按任意鍵繼續. . .
4. 以上是對於單繼承的描述,如果是多繼承,那么常規的話,我們很容易清楚器執行順序,但是如果是虛繼承,其執行順序又會如何 ?
1. 現在我們來看這樣一個圖:它的運行結果又是如何.......
1 #include<iostream> 2 using namespace std; 3 4 class Boss { 5 6 public : 7 Boss() { 8 cout << "this is Boss's constructor !" << endl; 9 }; 10 Boss(int i) { 11 cout << "this is Boss's constructor !" \ 12 << " moneny=" << i << endl; 13 } 14 15 void show() { 16 cout<<"寶劍磨礪,斬魂妖,時光磨砂,魔刃出"<<endl; 17 } 18 virtual ~ Boss() { 19 cout << "this is Boss's xigou function !" << endl; 20 }; //虛析構函數 21 }; 22 23 //店小二 24 class xiao_er :virtual public Boss 25 { 26 public: 27 xiao_er() { 28 cout << "this is xiao_er's constructor !"<<endl; 29 } 30 xiao_er(int i) : Boss(i){ 31 cout << "this is xiao_er's constructor !" \ 32 << " moneny=" << i << endl; 33 } 34 virtual ~xiao_er() { 35 cout << "this is xiao_er's xigou function !" << endl; 36 } 37 void show() { 38 cout << "我是店小二,客官 !" << endl; 39 } 40 }; 41 42 //王二小 43 class er_xiao : virtual public Boss \ 44 , virtual public xiao_er /*其實這里這個可以省去,但是這兒是為了寫代碼而寫代碼*/ 45 { 46 public : 47 er_xiao() { 48 cout << "this is er_xiao's constructor !" << endl; 49 } 50 er_xiao(int i) : \ 51 Boss(i) , xiao_er(i+1) 52 { 53 cout << "this is er_xiao's constructor !" \ 54 << " moneny=" << i << endl; 55 } 56 virtual ~ er_xiao() { 57 cout << "this is er_xiao's xigou function !"<<endl; 58 } 59 void show() { 60 cout << "我是王二小,為壞人帶路的王二小 !" << endl; 61 } 62 }; 63 64 //天朝VIP員工 65 class VIP_em : virtual public Boss 66 { 67 68 public: 69 VIP_em(){ 70 cout << "this is VIP_em's constructor !" << endl; 71 } 72 73 VIP_em(int i) : \ 74 Boss(i) 75 { 76 cout << "this is VIP_em's constructor !" \ 77 << " moneny=" << i << endl; 78 } 79 virtual ~VIP_em() { 80 cout << "this is VIP_em's xigou function !" << endl; 81 } 82 void show() { 83 cout << "我是VIP , 我有特權! "<<endl; 84 } 85 }; 86 87 //熊孩子 88 class stupid_kid : virtual public VIP_em \ 89 , virtual public xiao_er , \ 90 virtual public er_xiao 91 { 92 public: 93 stupid_kid() { 94 cout << "this is stupid_kid's constructor !" << endl; 95 } 96 97 stupid_kid(int i) : \ 98 VIP_em(i) , xiao_er(12) , er_xiao(13),xe(i) 99 { 100 cout << "this is stupid_kid's constructor !" \ 101 <<" moneny="<<i<<endl; 102 } 103 ~stupid_kid() { 104 cout << "this is stupid_kid's xigou function !"<<endl; 105 } 106 107 void show() { 108 cout << "我是熊孩子,蜀黍,蜀黍,抱抱!" << endl; 109 } 110 private : 111 VIP_em vi; 112 xiao_er xe; 113 er_xiao ex; 114 }; 115 116 int main(){ 117 118 stupid_kid st(100); 119 //父類的函數被覆蓋了 120 st.show(); 121 //如何調用父類,強制是一種。 122 ((Boss)st).show(); 123 124 //stupid_kid *pt = &st; 125 //stupid_kid &sb = st; 126 // pt->show(); 127 //((Boss)sb).show(); 128 return 0; 129 }
結果為:
this is Boss's constructor !
this is VIP_em's constructor ! moneny=100
this is xiao_er's constructor ! moneny=12
this is er_xiao's constructor ! moneny=13
-------------這部分為熊孩子的繼承部分構造函數
下面是私有變量的構造函數
this is Boss's constructor !
this is VIP_em's constructor !
------私有變量 Vip_em調用無參數的構造函數
this is Boss's constructor ! moneny=100
this is xiao_er's constructor ! moneny=100
------私有變量 xiao_er調用有參數的構造函數
this is Boss's constructor !
this is xiao_er's constructor !
------私有變量 xiao_er調用無參數的構造函數
this is er_xiao's constructor !
this is stupid_kid's constructor ! moneny=100
我是熊孩子,蜀黍,蜀黍,抱抱!
寶劍磨礪,斬魂妖,時光磨砂,魔刃出
this is Boss's xigou function !
this is stupid_kid's xigou function !
this is er_xiao's xigou function !
this is xiao_er's xigou function !
this is Boss's xigou function !
this is xiao_er's xigou function !
this is Boss's xigou function !
this is VIP_em's xigou function !
this is Boss's xigou function !
this is er_xiao's xigou function !
this is xiao_er's xigou function !
this is VIP_em's xigou function !
this is Boss's xigou function !
請按任意鍵繼續. . .
6、 從上述代碼可以不難看出, 虛內繼承,避免了二義性,僅僅壓縮了公有的你虛類繼承類。
如果要弄清楚虛擬繼承,就得先知道virtual table (vtbl) ----我們說的虛函數表
在內存那塊, 會留 下一塊連續的內存塊,用作vtble存儲JMP地址,而vtble里頭存的便是virtual function(虛函數)地址,
每次繼承時,基類都會產生一個vptr指針,指向派生類的地質,當 vptr指針指着同一個地址時,就不重復構造。 其他的,構造函數和析構函數,基於第一個代碼列子。 根據自己對源碼的理解和測試的總結,如有錯誤,還請多多指正。