標籤:
一、父類與子類父類與子類的相互轉換
1、衍生類別的對象可以賦給基類,反之不行
2、基類的指標可以指向衍生類別,反之不行
3、基類的引用可以初始化為衍生類別的對象,反之不行
4、衍生類別指標必須強制轉換為基類指標後才可以指向基類
5、基類指標轉換為衍生類別指標容易導致崩潰性錯誤
6、虛基類的引用或派生不能轉換為衍生類別
class father{
//
};
class son : public father{
//
};
int main(){ father f; son s; f = s;//正確 s = f;//錯誤 father *pf = new son;//正確 son *ps = new father;//錯誤 father &rf = s;//正確 father &rs = f;//錯誤 return 0;} 繼承關係對基類成員的影響
| |
公有成員 |
保護成員 |
私人成員 |
| 公有繼承 |
公有 |
保護 |
不可訪問 |
| 保護繼承 |
保護 |
保護 |
不可訪問 |
| 私人繼承 |
私人 |
私人 |
不可訪問 |
| 成員函數 |
1 |
1 |
1 |
| 對象 |
1 |
0 |
0 |
| 子類 |
1 |
1 |
0 |
1:可以訪問 0:不可訪問
當所有成員都變成不可訪問時,再往下派生就沒有意義了
二、子類的構造與析構1、構造衍生類別對象時,先執行基類的建構函式,再執行子類的建構函式,析構反之
class father{public: father(){cout<<"father construct"<<endl;} ~father(){cout<<"father delete"<<endl;}};class son : public father{public: son(){cout<<"son construct"<<endl;} ~son(){cout<<"son delete"<<endl;}};int main(){ son s; return 0;}
輸出:
father constructson constructson deletefather delete
2.如果是多重繼承,基類的構造順序按給定的順序,析構反之
class father{public: father(){cout<<"father construct"<<endl;} ~father(){cout<<"father delete"<<endl;}};class mother{public: mother(){cout<<"mother construct"<<endl;} ~mother(){cout<<"mother delete"<<endl;}};class son : public father, public mother{public: son(){cout<<"son construct"<<endl;} ~son(){cout<<"son delete"<<endl;}};int main(){ son s; return 0;}
輸出:
father constructmother constructson constructson deletemother deletefather delete
3.利用基類的建構函式構造子類,效率更高
class father{ int x;public: father(int a):x(a){cout<<"father construct:"<<x<<endl;}};class son : public father{ int y;public: son(int a, int b):father(a), y(b){cout<<"son construct:"<<y<<endl;}};int main(){ son s(1, 2); return 0;}
輸出:
father construct:1son construct:2
三、多重繼承
1.多重繼續的二義性,根本原因是
假如A有Test(),則B和C都有Test(),於是D產生了二義性
class A{public: void Test(){cout<<"A"<<endl;}};class B{public: void Test(){cout<<"B"<<endl;}};class C : public A, public B{};int main(){ C c; c.Test(); //錯誤 c.A::Test(); //正確,輸出:A c.B::Test(); //正確,輸出:B return 0;}
2.編譯器通常都是從離自己最近的分類樹向上搜尋的
子類的Test()覆蓋了基類的Test(),並不代表基類的Test()消失,只是不能直接存取
class A{public: void Test(){cout<<"A"<<endl;}};class B{public: void Test(){cout<<"B"<<endl;}};class C : public A, public B{ void Test(){cout<<"C"<<endl;}};int main(){ C c; c.Test(); //正確,輸出:C c.A::Test(); //正確,輸出:A c.B::Test(); //正確,輸出:B return 0;}
3.對於單一繼承,子類能否訪問父類的父類,只與繼承的方式有關
對於多重繼承,子類不能直接存取父類的父類。
4.用virtual來避免二義性。
class B : virtual public A.
四、繼承與包含
1.一個類的成員變數列表中包含另一個類的對象,叫做包含(包容)。
2.包含與私人繼承的區別:
包含:
1)使程式看上去更清晰易懂
2)不存在繼承帶來的問題
3)可以包括另一個類的多個對象
私人繼承:
1)可以訪問基類的保護成員
2)可以重定義虛函數,實現多態
c++ --> 父類與子類間的繼承關係