面向對象編程的主要目的之一是:提供可重用的代碼。尤其是項目很龐大的時候,重用測試過的代碼比重新編碼代碼要好得多。
?????? C 提供了更高層次的重用性。其中之一就是繼承這個概念。
?????? 一些廠商提供了類庫。類庫由類聲明和實現(xiàn)構成。類庫通常是由源代碼組成的,這意味著可以對其進行修改,以滿足需求。但是也可以用類繼承的方式,來擴展和修改類。這比修改代碼的方法更好。正如繼承一筆財產(chǎn)要比自己白手起家更容易。
?????? 繼承的基本實現(xiàn)非常簡單,但是要對繼承進行管理,使之在所有情況下都能正常使用,則需要做一些調整。所以繼承有簡單的一面,也有復雜的一面。
從一個類派生出另一個類時,原始類稱為基類,繼承類稱為派生類。
?
基類的私有部分將稱為派生類的一部分,但只能通過基類的公有和保護方法訪問。
基類的公有成員將稱為派生類的公有成員。
?
派生類對象存儲了基類的數(shù)據(jù)成員(派生類繼承了基類的實現(xiàn));
派生類對象可以使用基類的方法(派生類繼承了基類的接口);
派生類需要添加自己的構造函數(shù);
派生類可以根據(jù)自身需要添加額外的數(shù)據(jù)成員和成員函數(shù);
?????? 派生類不能訪問基類的私有成員,而必須通過基類方法進行訪問。
因此派生類構造函數(shù)必須使用基類構造函數(shù);
?????? 創(chuàng)建派生類對象時,程序首先創(chuàng)建基類對象。從概念上講,這意味著基類對象應當在程序進入派生類構造函數(shù)之前被創(chuàng)建。->C 使用成員初始化列表來完成這種工作。
?
RatedPlayer::RatedPlayer(unsigned int r, const string & fn, const string & ln, bool ht):TableTennisPlayer(fn,ln,ht)
{
?????? rating = r;
}
?
如果省略了基類構造函數(shù)的話:
RatedPlayer::RatedPlayer(unsigned int r, const string & fn, const string & ln, bool ht)
{
?????? rating = r;
}
首先還是創(chuàng)建基類對象,如果不調用基類構造函數(shù),程序將使用默認的基類構造函數(shù)。
因此上述代碼與下面等效:
RatedPlayer::RatedPlayer(unsigned int r, const string & fn, const string & ln, bool ht):TableTennisPlayer()
{
?????? rating = r;
}
除非要使用默認構造函數(shù),否則應該顯式調用正確的基類構造函數(shù)。
?
還有一種構造函數(shù)代碼:
RatedPlayer::RatedPlayer(unsigned int r, const TableTennisPlayer & tp):TableTennisPlayer(tp)
{
?????? rating = r;
}
這里也是將TableTennisPlayer的信息傳遞給了TableTennisPlayer構造函數(shù)。
這種方式將調用基類的復制構造函數(shù),如果基類沒有定義復制構造函數(shù),但又要使用它,則編譯器將自動生成一個。
?
甚至還可以對派生類成員使用成員初始化列表語法:
RatedPlayer::RatedPlayer(unsigned int r, const TableTennisPlayer & tp):TableTennisPlayer(tp),rating(r)
{
}
?
派生類構造函數(shù)的要點總結:
首先創(chuàng)建基類對象;
派生類構造函數(shù)應通過成員初始化列表(TableTennisPlayer(tp))將基類信息傳遞給基類構造函數(shù);
派生類構造函數(shù)應初始化派生類新增的數(shù)據(jù)成員(rating = r)。
如果沒有提供顯示構造函數(shù),將使用隱式構造函數(shù)。
理解派生類對象創(chuàng)建過程的對象創(chuàng)建順序:先創(chuàng)建基類對象,在創(chuàng)建派生類對象;
釋放對象的順序與創(chuàng)建對象的順序相反:首先執(zhí)行派生類的析構函數(shù),然后自動調用基類的析構函數(shù)。
?
成員初始化列表:(TableTennisPlayer(tp))
派生類構造函數(shù)可以使用初始化器列表機制將值傳遞給基類構造函數(shù)。
derived :: derived(type1 x, type2 y) : base(x,y)
{
?????? ...
}
Derived是派生類,base是基類。X和Y是基類構造函數(shù)使用的變量。
如果派生類構造函數(shù)接收到參數(shù)10和12,這種機制將把10和12傳遞給定義為接受這些類型的參數(shù)的基類構造函數(shù)。類只能將值傳遞回相鄰的基類。虛基類除外,虛基類可以使用相同的機制將信息傳遞給相鄰的基類,以此類推。如果沒有在成員初始化列表中提供基類構造函數(shù),程序將使用默認的積累構造函數(shù)。成員初始化列表只能用于構造函數(shù)。
?
使用派生類,程序必須要能夠訪問基類聲明??梢园褍蓚€類的聲明放在同一個頭文件中,也可以放在不同的頭文件中。
?
?????? 派生類可以使用基類的方法,條件是方法不是私有的。
?
?????? 基類指針可以再不進行顯式類型轉換的情況下指向派生類對象。
?????? 基類引用可以再不進行顯式類型轉換的情況下引用派生類對象。
?????? 但是基類指針和引用只能調用基類的方法。
?????? C 中要求引用和指針類型與賦予的類型匹配,但這一規(guī)則對繼承來說是例外。這例外是單向的,也就是說不能將基類對象和地址賦給派生類引用和指針。
?????? 但是這種關系是單向的,不能將基類對象和地址賦給派生類引用和指針。
?
?????? 這樣要求是有道理的:如果允許基類引用隱式地調用派生類方法,則可以使用基類引用為派生類對象調用基類的方法。因為派生類繼承了基類的方法,所以這樣做不會有問題。
?????? 如果可以將基類對象賦給派生類引用,將發(fā)生什么情況?派生類引用能夠為基類對象調用派生類方法,這是沒有意義的。例如TableTennisPlayer沒有rating成員。
?????? 基類引用和指針可以指向派生類對象,將出現(xiàn)一些很有意思的現(xiàn)象:
?來源:http://www.icode9.com/content-1-121001.html