第九章 C++繼承和多態
共有繼承中,繼承類在初始化時,需要調用基類構造函數來初始化基類成員變量,特別是私有成員變量。
私有繼承的基類成員成爲派生類的私有成員,所以不能直接使用。若果兩個類之間是私有繼承關係,那麼編譯器一般不會把派生類對象轉換爲基類對象。
例子1:
私有繼承和組合的相同點和不同點,如何選擇?
使用組合表示(has a)(即有一個)的關係。如果在組合中需要使用對象的某些方法,則完全可以用私有繼承來代替。
私有繼承是派生類獲得基類的一份備份,同時還可以訪問基類的公共以及保護接口以及重寫基類的虛擬函數,它意味着“isimplementInTermsof”(即以……實現),他是組合語法的一種變形,即聚合或者有一個。
hasa關係既可以用私有繼承表示,也可以用單一組合表示:
私有繼承和組合的相同點:
1、他們都有一個需要包含的類在裏面。
2、他們在外部都不能與被包含類進行指針轉換;
3、他們都有被包含類的方法。
私有繼承和組合的區別:
1、如果想讓每個類包含多個被包含類,那隻能用組合;
2、私有繼承可能引入不必要的多重繼承;
3、私有繼承允許繼承類的成員將繼承類轉換成被繼承類,但是在外部不可以。
4、私有繼承允許訪問基類的保護成員
5、私有繼承允許繼承類重寫被繼承類的虛函數
選用原則是儘量使用組合,萬不得已使用私有繼承。
多態性:
多態、封裝和繼承是面向對象的三大特徵,多態的含義是,同一操作,作用於不同對象,產生不同的結果。
有兩種類型的多態性:
1、編譯時的多態性,是通過重載來實現的。對於非虛函數,系統在編譯時,根據傳入數據類型和返回類型的不同,調用不同的函數
2、運行時的多態性,是通過虛函數來實現的,只有在運行時才決定實現何種操作。
class person
{
public:
virtual void print()
{
cout<<"person"<<endl;
};
};
class China:public person
{
public:
virtual void print()
{
cout<<"China"<<endl;
}
};
class American:public person
{
public:
virtual void print()
{
cout<<"American"<<endl;
}
};
void Print(person &p)
{
p.print();
}
void main()
{
person p;
China c;
American a;
Print(p);
Print(c);
Print(a);
}
多重繼承和虛擬繼承:
(1)任何虛擬基類的構造函數都按照他們被繼承的順序構造。
(2)任何非虛擬基類的構造函數按照他們被構造的順序構造。
(3)任何成員對象的構造函數按照他們的聲明順序調用。
9.5 純虛函數和抽象基類
純虛函數就是基類之定義了函數體,沒有實現過程,如果基類包含一個或多個純虛函數,那麼他就是抽象基類,不能被實例化。
引入純虛函數和抽象基類的原因:
1、爲了方便多態性。
2、基類本省並不適合生成對象。
虛函數與純虛函數的區別:
1、類內聲明虛函數的作用是爲了讓這個函數在他的子類中被覆蓋,這樣編譯器就可以使用後期綁定來實現多態。純虛函數只是定義一個接口,要留到子類中去實現。
2、虛函數在子類中可以不重載,但是純虛函數必須在子類中實現。通常很多函數加上virtual修辭,雖然犧牲了性能,但是增加了面向對象的多態性,可以阻止父類中的這個函數在子類中被修改。
3、虛函數的類用於“實作”繼承,也就是說繼承了接口的同時,也繼承了父類的實現,也可以有自己的實現。而純虛函數只是“界面繼承”關注的是接口的一致性,實現由子類完成。
4、帶純虛函數的類叫做抽象類,這種類不能直接產生對象,只能被繼承,重寫其純虛函數後纔可以使用,也叫虛基類。
COM:即組件對象模型,定義了一種二進制標準,使得任何語言都能存取它所寫的模塊。
特點:
1、組件與開發語言沒有關係。
2、通過接口有效保證了組件的複用性。
3、組件運行效率高,便於使用和管理。
第九章結束