繼承派生(只考慮public繼承)以及多型

2021-10-07 05:19:33 字數 2813 閱讀 4530

一、繼承和派生

classb:

public a

;

b繼承自a, b是a的派生。派生類擁有基類的全部成員函式和成員變數,但基類的private成員,派生類無法訪問(因此可以將派生類定義成基類的友元類,友元關係不具有傳遞性和繼承性),基類的protected成員:派生類的成員函式可以訪問當前物件的基類的保護成員。保護成員就是為了繼承而生的,其它訪問限制與private一樣。

關於建構函式問題見寫在建構函式一章

繼承與成員物件的區別:

無論是b繼承a,還是在b中定義乙個a類的物件,都可以實現在b類物件的記憶體裡,放乙個a類的物件(二者幾乎可以達到一樣的功能,但無法通過成員物件訪問a的保護成員,因為protected為繼承而生)。

但它們的應用場景,在邏輯上完全不同。

b繼承a的正確場景是:b類物件從邏輯上也是a類物件。比如男人類可以繼承自人類,乙個男人也必然是乙個人(public繼承是這樣,其它兩種繼承不是這種邏輯)。

b中定義成員物件(a)的正確場景是:a是b的組成部分,比如圓由圓心(點)和半徑組成,在定義圓類時就可以定義乙個double型別的半徑,和點型別的成員變數圓心。點類就是a類。

基類與成員物件的區別不是從類內內容上來區分的,而是從邏輯大小上來區分的。

派生類覆蓋基類成員:

派生類中如果定義了和基類同名的成員變數、成員函式。那麼預設訪問的就是派生類自己定義的同名成員,覆蓋了基類的成員。此時要想訪問基類中的同名成員,就要通過 基類名::成員名;來訪問,但這種訪問方法也僅侷限在成員函式中訪問成員物件作用的物件的基類同名成員;無法訪問同類物件的基類的同名成員。

一般來說派生類中不定義基類的同名成員變數(如果非要用基類的私有變數,那就在基類中把它定義成保護成員變數啊)

派生類中經常要定義基類的同名成員函式,這是下面的多型問題。

public繼承的相容性:

1、派生類物件可以賦值給基類物件(只取重合那塊)

2、基類的引用可以被派生類物件初始化

3、基類的指標可以指向派生類的物件

二、多型和虛函式

前面提到,派生類中可以定義和基類成員函式同名的成員函式。這種方法可以大大擴充**的靈活性,因為派生類總有自己的特點,所以我們需要定義同名函式。

基類的指標可以指向派生類物件,那在往函式裡傳引數時,只要形參是基類指標(或引用),那所有派生類物件豈不是都能傳進函式裡去。這也太好了吧,本來要過載函式才能傳其它型別物件(派生類之間也是不同的型別),這樣寫乙個就行了。

細心一點就會發現,雖然基類指標可以指向派生類的物件,但只能通過該指標訪問派生類物件裡的基類那部分成員,無法訪問新定義的成員(同名也不行),這大大限制了上面說的那種好處。多型和虛函式就是為破解這個限制而設計的。

虛函式:

定義成員函式時,在函式宣告前加上關鍵字virtual,就定義了乙個虛函式。如果虛函式的函式體寫在外面,實現的時候就不要再寫virtual,基類中如果定義了虛函式,那麼在派生類中的同名同參的函式不寫virtual也是虛函式。如果在派生類中沒有繼續定義虛函式,那麼繼承來的那個虛函式也是派生類的虛函式。

虛函式不要定義成私有成員函式,因為影響在其它函式中呼叫宣告為公有的派生類的虛函式(會報錯)

多型:

通過基類指標呼叫基類和派生類中的同名虛函式時:

(1)若該指標指向乙個基類的物件,那麼被呼叫是 基類的虛函式;

(2)若該指標指向乙個派生類的物件,那麼被呼叫 的是派生類的虛函式。

這種機制就叫做「多型」。

多型的意義是,一方面可以減少函式過載(大家都用基類指標),另一方面是派生類自己的虛函式也是成員函式,可以訪問新設的成員變數,這就使基類指標可以通過虛函式訪問派生類中新增加的變數。

如果派生類中定義了乙個虛函式,而基類中並沒有對應的虛函式,那麼通過基類指標無法訪問這個虛函式。

虛析構函式:

如果基類指標指向派生類的物件,那麼在delete指標時,只會呼叫基類的析構函式,無法摧毀派生類物件。為此我們把基類和派生類的物件都定義成虛函式,那麼在delete指標時就可以先執行基類建構函式,再呼叫派生類的建構函式。

注意:如果乙個類準備作為基類,最好把它的析構函式寫成虛函式,成員變數定義成protected;

在普通成員函式中呼叫虛函式是多型,在建構函式和析構函式中呼叫虛函式,不是多型。編譯時即可確定,呼叫的函式是自己的類或基類中定義的函式,不會等到執行時才決定呼叫自己的還是派生類的函式。

多型的實現原理:

含有虛函式的類都有乙個虛函式表(應該是存放在全域性變數區),物件裡會有虛函式指標。用sizeof求記憶體時會因為虛函式指標而多四個位元組(sizeof(類名)也是多4個位元組,因此類裡多的也是虛函式表指標)

虛函式表指標存放在物件記憶體最前面,派生類的虛函式表指標可被基類指標訪問,因此當基類指標指向的是派生類的物件時,基類指標可以利用虛函式表指標找到屬於派生類的虛函式(按常理這是超過了基類指標的能力範圍),並執行。

純虛函式和抽象類

純虛函式就是沒有函式體的虛函式

virtual

void

print()

=0;//純虛函式

含有純虛函式的類叫抽象類。抽象類不能例項化物件,只有它的派生類實現了所有的純虛函式,派生類才能例項化物件。

C private繼承與public繼承

private 只能由1.該類中的函式 2.其友元函式訪問。不能被任何其他訪問,該類的物件也不能訪問。protected 可以被1.該類中的函式 2.子類的函式 3.其友元函式訪問。但不能被該類的物件訪問。public 可以被1.該類中的函式 2.子類的函式 3.其友元函式訪問,也可以由4.該類的物...

private繼承與public繼承

private 能夠訪問 1.該類中的函式 2.友元函式。不能訪問 1.public繼承的子類和private繼承子類 2.該類的物件。protected 能夠訪問 1.該類中的函式 2.public繼承的子類和private繼承子類 3.友元函式。不能訪問 1.該類的物件。public 能夠訪問 ...

C private繼承與public繼承

private 只能由1.該類中的函式 2.其友元函式訪問。不能被任何其他訪問,該類的物件也不能訪問。protected 可以被1.該類中的函式 2.子類的函式 3.其友元函式訪問。但不能被該類的物件訪問。public 可以被1.該類中的函式 2.子類的函式 3.其友元函式訪問,也可以由4.該類的物...