c++——派生類和基類轉換(類型兼容性原則)

基類也叫父類,派生類也叫子類。

類之間的繼承關係
繼承關係是類之間的父子關係。 繼承關係的特點如下:
A、 子類擁有父類的所有屬性和行爲
B、 子類也是一種特殊的父類
C、 子類對象可以當父類對象使用
D、 子類中可以添加父類沒有的屬性和方法
E、 子類對象可以直接初始化父類對象
F子類對象可以直接賦值給父類對象
G、 繼承是面向對象編程中代碼複用的重要手段

H、父類指針可以直接指向子類對象
 I、父類引用可以直接引用子類對象

 

C++編程中, 軟件可重用性(software reusability)是通過繼承(inheritance)
制來實現的。 類的繼承, 是新的類從已有類得到已有的特性。 從已有類產生新類
的過程就是類的派生。原有的類稱爲基類或父類, 產生的新類稱爲派生類或子類。
繼承是一種封裝模型之間關係的抽象, 是不同封裝模型的層次分類。

如果一個派生類同時有多個基類, 稱爲多重繼承; 如果派生類只有一個基類,稱爲單繼承。

使用 class 關鍵字定義派生類時, 默認繼承方式爲 private
使用 struct 關鍵字定義派生類時, 默認繼承方式爲 public
C++工程項目中, 通常只使用 public 繼承方式。

派生類中的成員包含兩大部分, 一類是從基類繼承過來的, 一類是自己增加
的成員。 從基類繼承的成員表現其共性, 而新增的成員體現其個性。
派生類中由基類繼承而來的成員的初始化工作還是由基類的構造函數完成,
然後派生類中新增的成員在派生類的構造函數中初始化。 派生類沒有繼承基類的
構造函數和析構函數。

派生類經常(但不總是)覆蓋它繼承的虛函數。如果派生類沒有覆蓋其基類中的某個虛函數,則該虛函數的行爲類似於其他的普通成員,派生類會直接繼承其在基類中的版本。

c++11允許派生類顯式地註明它使用某個成員函數覆蓋了它繼承的虛函數。具體做法是在形參列表後面、或者在const成員函數的const關鍵字後面、或者在引用成員函數的引用限定符後面添加一個關鍵字override。

派生類也必須使用基類的構造函數來初始化它的基類部分。(除非基類沒有顯式定義構造函數,這樣在派生類的構造函數中可以不顯式調用基類的構造函數)

我們可以把公共派生類當做基類使用,派生類可以賦值給基類,基類的引用或者指針可以綁定到派生類上(反之不行)。

遵循基類的接口:

儘管在語法上來說我們可以在派生類構造函數體內給它的共有或者受保護的基類成員賦值,但是最好不要這麼做。和使用基類的其他場合一樣,派生類應該遵循基類的接口,並通過調用基類的構造函數來初始化那些從基類中繼承而來的成員。

如果基類定義了一個靜態成員,則在整個繼承體系中只存在該成員的唯一定義。不論基類中派生出來多少個派生類,對於每個靜態成員都只存在唯一的實例。靜態成員也要遵循通用的訪問控制規則,public,private,protected。

如果我們想要將某個類用作基類,則該類必須是已經定義了的而不能僅僅聲明。這意味着,一個類不能派生它本身。

 

有時候我們會定義這樣一種類,我們不希望其他類繼承它,或者不想考慮它是否適合作爲一個基類,爲了實現這一目的,c++11提供了一種防止繼承發生的方法,即在類名後跟一個關鍵字final。我們還能把某個函數指定爲final,則之後任何嘗試覆蓋該函數的操作都將引發錯誤。

eg:

class A final { ....};//A不能作爲基類

當我們用一個派生類對象爲一個基類對象初始化或者賦值時,只有該派生類對象中的基類部分會被拷貝、移動或賦值,它的派生部分會被忽略掉。

如果表達式既不是指針也不是引用,那麼它的動態類型永遠與靜態類型一致,如果是指針或者引用,將產生動態綁定,動態類型直到運行時纔可知,而靜態類型在編譯時就總是已知的。