繼承與多型

2021-09-28 19:41:01 字數 2908 閱讀 1753

(1):**的重用:派生類只需要定義自己特有的成員,共享的成員都由繼承而來,減少**的冗餘度。

(2):在基類中給派生類提供統一的虛函式介面,方便使派生類進行重寫操作,實現多型呼叫。

以下是當派生類繼承了基類的成員變數與成員方法,其的訪問限定

繼承方式

基類的訪問限定

派生類的訪問限定

外部訪問限定

public

public

public

yespublic

protected

protected

nopublic

private

無法訪問

noprotected

protected

protected

noprotected

protected

protected

nopublic

private

無法訪問

noprivate

private

private

noprivate

private

private

nopublic

private

無法訪問

no用class繼承,預設是private,而用struct繼承,預設是共有的

所以private只有當前類或這友元函式可以訪問,而protected在派生類中也可以訪問

派生類中的繼承的成員(無論是私有和是公共繼承而來)必須呼叫基類的建構函式來初始化,簡單理解為,派生類負責派生類自己的成員初始化,基類負責基類的成員初始化。即自己負責自己的成員初始化。

在初始化的過程中,派生類先呼叫基類的構造,再呼叫自己的構造。即—基類構造-----派生類構造----派生類析構—基類析構。。。

基類和派生類可以有同名的函式,但不構成過載,因為作用域不同

過載:在同一作用域,函式名相同,引數列表不同,才可以構成函式過載

**隱藏:**基類和派生類中的同名成員,只要成員名字相同,用派生類物件呼叫該成員名字時,就發生了隱藏(隱藏了基類的同名成員),派生類始終會優先訪問自己的成員變數或者方法,如果找不到就會在基類中訪問,如果要使用基類中的方法,需要新增作用域。。

例如:基類:void showdata(){} void showdata(int a)(){}

派生類:void showdata(){}

如果派生類的物件呼叫showdata(10),將會出錯。但是 派生類物件.基類::showdata(10) 這樣是正確的。

**覆蓋:**指的是基類和派生類中的同名成員函式,不僅函式名字相同、返回值相同、引數列表也相同,而且基類的該函式是virtual虛函式,那麼派生類的同名方法自動被處理成虛函式,它們之間的關係是覆蓋關係。

1.如果乙個類有虛函式,那麼編譯器在編譯階段,會給當前型別生成一張虛函式表,虛函式表裡面放的是虛函式的位址vfptr,還有rtti指標資訊;這張虛函式表在**執行階段,被載入到.rodata段,也就是說唯讀不能寫,這張虛函式表就是vftable。

2.當有派生類繼承了有虛函式的基類時,派生類同時繼承了基類的vfptr,即指向同乙個vftbale。

當存在同名覆蓋函式時,派生類會在執行期進行重寫,即在vftable中把繼承來的乙個同名虛函式位址替換為自己的同名函式位址

3.乙個類出現多個虛函式,物件記憶體只增長4個位元組

4.基類與派生類的vfptr,在派生類構造的時候,首先會構造繼承來的成員,此時vfptr儲存的是基類的虛函式表位址,在呼叫構造派生類的建構函式時,vfptr的儲存位址變換為派生類自己的虛函式表。

靜態繫結指編譯時期函式的呼叫就是確定的;動態繫結指函式的呼叫要到執行時期才能確定

1.什麼情況會發生動態繫結:

通過指標與引用來呼叫虛函式

2.動態繫結時多型的基礎

3.基類與派生類的轉換:

不管是物件還是指標,只支援派生類到基類的轉換,因為派生類的大小會大於基類

4.動態繫結

動態繫結必須依賴於物件,如果物件不存在或者未構造好,則不存在動態繫結,因為執行階段才有的虛函式表

而靜態繫結在物件未構造好時也可以發生呼叫。

1.建構函式可以實現為虛函式嗎?

不可以!如果物件沒有例項化,就無法找到物件記憶體空間中儲存的vfptr,也就無法找到vftable,也就無法進行構造。

2.析構函式可以實現為虛函式嗎?

可以,而且有些情況必須實現為虛函式。

3.什麼時候析構必須為虛函式?

當用基類指標指向new出來派生類的時候,delete只會呼叫基類的析構,派生類無法釋放。設定為虛析構函式後,指標指向哪個派生類,就會呼叫哪個派生類的析構函式,派生類再呼叫基類的析構函式。

1.當乙個物件指標指向nullptr,呼叫成員方法會發生什麼?

1.當呼叫非虛函式(不使用物件成員變數)時,是可以成功

2.當呼叫非虛函式(使用物件成員變數)時,失敗

3.呼叫虛函式,失敗

類的成員函式並不與具體物件繫結,所有的物件共用同乙份成員函式體。

當程式被編譯後,成員函式的位址即已確定,這份共有的成員函式體之所以能夠把不同物件的資料區分開來,靠的是隱式傳遞給成員函式的this指標,成員函式中對成員變數的訪問都是轉化成"this->資料成員"的方式。

因此,從這一角度說,成員函式與普通函式一樣,只是多了乙個隱式引數,即指向物件的this指標。

**總結:**成員函式不與任何乙個物件繫結,所有物件共享,所以為空的物件呼叫成員方法時可以的,但是當使用成員變數時,要使用this->,此時為空,出錯,虛函式就更不用說了,this->vfptr是訪問失敗的。

muduo裡eventloop中在封裝epoll與poll時,定義了乙個抽象類poller,實現了多型

繼承與多型

繼承 繼承是c 語言支援 重用及多型的重要機制。通過繼承,可以繼承可以在現有類的基礎上派生出新類,新類將共享現有類的成員,並且還可以新增新的成員。c 語言中,重用主要表現為可以使用現成的類 如.net框架類庫中的類 來定義新類,主要方法有組合和繼承兩種 繼承是物件導向程式設計支援 重用的另乙個重要機...

繼承與多型

虛函式只要在基類裡定義,所以繼承類都不用重新定義為虛函式,自動成為虛函式。虛函式必須有實現,普通成員函式在沒有呼叫時可以沒有實現 定義 class animal 只需要在基類定義函式為虛,子類中不需要新增virtual.smile函式在沒有呼叫時可以不實現。當有函式為虛函式時,析構函式應定義為vir...

繼承與多型

繼承需要符合的關係 is a,父類更通用 子類更具體 子類繼承父類的所有屬性和方法 不包括父類構造方法 super可以呼叫父類的方法和構造方法 子類可以重寫父類的方法 使用多型之後,當需要增加新的子類型別時,無需更改總部類,程式的可擴充套件性及可維護性增強 簡單來說,多型是具有表現多種形態的能力的特...