第15章 物件導向程式設計 3

2021-09-30 09:26:03 字數 1706 閱讀 2876

15.2.4 virtual與其他成員函式

c++中的函式呼叫預設不使用動態繫結。要出動動態繫結,必須滿足兩個條件:第一,只有指定為虛函式的成員函式才能進行動態繫結,成員函式預設為非虛函式,非虛函式不進行動態繫結;第二,必須通過基類型別的引用或指標進行函式呼叫。

1. 從派生類到基類的轉換

因為每個派生類物件都包括基類部分,所以可將基類型別的引用繫結到派生類物件的基類部分,也可以用指向基類的指標指向派生類物件。

item_base *item1=new bulk_item();

item_base &item2=*item1;

因為可以使用基類型別的指標或引用來引用派生型別物件,所以,使用基類型別的引用或指標時,不知道指標或引用所繫結的物件的型別:基類型別的引用或指標可以引用基類型別的物件,也可以引用派生型別物件。無論實際物件具有哪種型別,編譯器都將它當作基類型別物件。將派生類物件當作基類物件是安全的,因為每個派生類物件都擁有基類子物件。而且,派生類繼承基類的操作,即,任何可以在基類物件上執行的操作也可以通過派生類物件使用。

基類型別引用和指標的關鍵點在於靜態型別(static type,在編譯時可知的引用型別或指標型別)和動態型別(dynamic type,指標或引用所繫結的物件的型別,這是在執行時可知的)可能不同。

2. 可以執行時確定virtual函式的呼叫

item_base *item1=new bulk_item();

cout通過引用或指標呼叫虛函式時,編譯器將生成**,在執行時確定呼叫哪個函式,被呼叫的是與動態型別相對應的函式。

引用和指標的靜態型別與動態型別可以不同,這是c++用以支援多型性的基石。

通過基類引用或指標呼叫基類中定義的函式時,我們並不知道執行函式的物件的確切型別,執行函式的物件可能是基類型別的,也可能是派生型別的。

如果呼叫非虛函式,則無論實際物件是什麼型別,都執行基類型別所定義的函式。如果呼叫虛函式,則直到執行時才能確定呼叫哪個函式,執行時的虛函式是引用所繫結的或指標所指向的物件所屬型別定義的版本。

另一方面,物件是非多型的——物件型別已知且不變。物件的動態型別總是與靜態型別相同,這一點與引用或指標相反。執行的函式(虛函式或非虛函式)是由物件的型別定義的。

3. 編譯時確定非virtual呼叫

cout即使bulk_item定義了自己的book函式版本,這個呼叫也會呼叫基類中的版本。

非虛函式總是在編譯時根據呼叫該函式的物件、引用或指標的型別而確定。

4. 覆蓋虛函式機制

在某些情況下,希望覆蓋虛函式機制並強調函式呼叫使用虛函式的特定版本,這時可以使用作用域操作符。

cout派生類虛函式呼叫基類版本時,必須顯式使用作用域操作符。如果派生類函式忽略了這樣做,則函式呼叫會在執行時確定並且將是乙個自身呼叫,從而導致無窮遞迴。

5. 虛函式與預設實參

像其他任何函式一樣,虛函式也可以有預設實參。通常,如果有用在給定呼叫中的預設實參值,該值將在編譯時確定。如果乙個呼叫省略了具有預設值的實參,則所有的值由呼叫該函式的型別定義,與物件的動態型別無關。通過基類的引用或指標呼叫虛函式時,預設實參為在基類虛函式宣告中指定的值,如果通過派生類的指標或引用呼叫虛函式,則預設實參是在派生類的版本中宣告的值。

在同一虛函式的基類版本和派生類版本中使用不同的預設實參幾乎一定會引起麻煩。如果通過基類的引用或指標呼叫虛函式,但實際執行的是派生類中定義的版本,這是就可能會出現問題。在這種情況下,為虛函式的基類版本定義的預設實參將傳遞給派生類定義的版本,而派生類版本是用不同的預設實參定義的。

第15章 物件導向程式設計

派生類中的虛函式可以返回基類函式所返回型別的派生類的引用或指標。只有指定為虛函式的成員函式才能進行動態繫結。派生類可以進一步限制但不能放鬆對所繼承的成員的訪問。使用private或protected派生的類不繼承基類的介面,稱為實現繼承。使用class保留字定義的派生類預設具有private繼承,而...

第 15章 物件導向程式設計(一)

以quote基類和bulk quote派生類為例,記錄標頭檔案和cpp檔案的構成。目錄 基類和派生類的標頭檔案及cpp檔案結構 quote.h quote.cpp bulk quote.h bulk quote.cpp main.cpp ifndef quote h define quote h i...

第15章 物件導向程式設計 4

15.2.5 公有 私有和受保護的繼承 對類所繼承的成員的訪問由基類中的成員訪問級別和派生類派生列表中使用的訪問標號共同控制。每個類控制它所定義的成員的訪問。派生類可以進一步限制但不能放鬆對所繼承的成員的訪問。派生類不能訪問基類的private成員,也不能使自己的使用者能夠訪問那些成員。如果基類成員...