繼承和組合 多型性和虛函式

2021-07-11 16:18:43 字數 1627 閱讀 2810

繼承和組合:

重用已存在類的**有兩種方式:1,組合,即在新類中建立已存在類的物件;2,繼承,即建立乙個新類作為乙個已存在類的型別。

在派生類中可以重新定義基類中的成員函式,派生類的物件呼叫該函式時呼叫的是重新定義的成員函式,而呼叫基類的成員函式只能使用作用域顯示的標明基類名。

建構函式和析構函式的呼叫順序:建構函式是從類層次的最根處開始,在每一層,首先會呼叫基類建構函式,然後呼叫成員物件建構函式,最後呼叫的才是自己的建構函式的執行體(還有一點需要注意:成員物件的初始化次序完全不受建構函式的初始化表示式中的次序影響,該次序是由成員物件在類中宣告的次序決定的),而析構函式的呼叫順序和建構函式的呼叫順序完全相反。

建構函式和析構函式不能被繼承,operator=也不能被繼承,因為它完成類似於建構函式的活動。每乙個派生類都必須有自己的建構函式和析構函式。如果在派生類中重新定義了成員函式,所有在基類中的其他過載函式都會被隱藏。

乙個類物件可以作為它自己的類或者它的基類的物件來使用,即向上型別轉換。

多型性和虛函式:

多型性提供了介面與具體實現之間的隔離,從而將"what"和"how"分離開來,多型性改善了**的組織性和可讀性,同時使穿件的程式具有可擴充套件性。

把函式體和函式呼叫相聯絡稱為**:1,早**(靜態**):**在程式執行前(由編譯器和鏈結器)完成;2,晚**(動態**):**發生在程式執行時,需要確定並**物件的型別,從未呼叫合適的成員函式。對於特定的函式,為實現動態**,需要在基類中使用virtual關鍵字宣告這個函式為虛函式,而呼叫所有匹配基類宣告行為的派生類函式都將自動使用虛函式,動態**只對虛函式起作用。

編譯器為每個包含虛函式的類建立唯一的乙個表(稱為vtable)編譯器在該表中放置特定類的虛函式的位址;在每個包含虛函式的類中,編譯器都會放置乙個指標,稱為vpointer,指向這個物件的vtable,vpointer指標都在物件的相同位置(常常在物件的開頭)。當通過基類指標做虛函式呼叫時(多型呼叫),編譯器靜態的插入能取得這個vpointer並在vtable表中查詢函式位址的**,這樣就能呼叫正確的函式並引起動態**的發生。

不懂虛函式就等於不懂得物件導向程式設計。

建構函式不能為虛函式,但是析構函式能夠且常常必須是虛函式。

純虛函式:

有時候希望基類僅僅作為其派生類的乙個介面,而不希望使用者實際地建立乙個基類的物件,我們可以在基類中加入至少乙個純虛函式來使基類成為抽象類。純虛函式使用關鍵字virtual,並且在其後面加上=0,如:virtual  void f() =0;,編譯器會阻止為抽象類生成物件,並在vtable中為函式保留乙個位置,但這個特定位置中不存放位址,即vtable是不完全的。當繼承乙個抽象類時必須實現所有的純虛函式,否則繼承出的類也將是乙個抽象類。

如果對乙個物件進行向上型別轉換,而不使用位址和引用,這個物件將被「切片」,直到剩下來的是最適合於目的的子物件,因為按值傳遞時,基物件的拷貝建構函式將被呼叫,建構函式初始化vpointer指向基類的vtable,並且只拷貝這個物件的基類部分,而不像使用指標或者引用那樣簡單地改變位址的內容。

編譯器必須保證我們能夠多型的通過基類呼叫函式,所以不允許我們改變重新定義過的虛函式的返回值。但存在特例:如果返回乙個指向基類的指標或引用,則幹函式的從新定義版本將會從基類返回的內容中返回乙個指向派生類的指標或引用。

多型性和虛繼承

多型性 字面意思是多種形狀,即 乙個介面,多種方法 c 的多型性是由虛函式來實現的,虛函式允許派生類重新定義成員函式,派生類重新定義基類的方法稱為遮蔽。只有重寫虛函式才算是體現了函式的多型性。過載沒有體現多型性,因為過載是根據同名函式的不同引數型別選擇使用哪個函式的。include using na...

多型性和虛函式

11.27 多型指的是同樣的資訊被不同型別的物件接收導致不同的行為,包括 靜態多型性和動態多型性。靜態多型性包括 函式過載和運算子過載 動態多型主要 由虛函式實現。虛函式宣告 virsual 型別說明符 函式名 參數列 純虛函式 virtual 函式型別 函式名 參數列 0 在派生類中定義 抽象類 ...

多型性和虛函式

多型性是物件導向程式設計的乙個重要特徵。c 支援多型性,在 c 程式設計中能夠實現多型性。1 乙個典型的例子 先建立乙個 point 點 類,包含資料成員x,y 座標點 以他為基類,派生出乙個 circle 圓 類,增減資料成員 r 半徑 再以 circle 類為直接基類,派生出乙個 cylinde...