C Primer第五版筆記 虛函式

2021-08-24 20:17:34 字數 1433 閱讀 8844

當我們使用基類的引用或指標呼叫乙個虛成員函式時會發生動態繫結,知道執行時才會知道到底呼叫了哪個版本的虛函式,因此所有的虛函式都必須有定義。

對虛函式的呼叫可能在執行時才被解析

物件導向程式設計的核心思想是多型性(polymorphism)。多型性這個詞源於希臘語,其含義是「多種形態」,引用或指標的靜態型別與動態型別不同這一事實是c++語言支援多型性的根本所在。

當使用基類的引用或指標呼叫基類中定義的乙個函式時,我們並不知道該函式真正作用的物件是什麼型別的(可能是基類的物件也可能是派生類的物件)。如果該函式是虛函式,則直到執行時才會確定是哪個版本,判斷的依據是引用或指標所繫結的物件的真實型別。

另一方面,非虛函式的呼叫在編譯時進行繫結。類似的,通過物件進行繫結的函式(虛函式或非虛函式)呼叫也在編譯時進行繫結,因為物件的型別是不會改變的。

派生類中的虛函式:

在派生類中覆蓋某個虛函式時,可以加上virtual關鍵字,但是沒有必要,因為乙個函式被宣告為虛函式後,所有派生類中的它都是虛函式,且它的形參型別與返回值型別(乙個例外是返回型別是類本身的指標或引用)都和基類中相同。

final和override說明符:

派生類如果定義了乙個和基類中的虛函式名字相同但是此引數列表不同的函式時,這依然是合法的行為,但是並不是我們希望的情況。在c++11新標準中可以使用override來說明基類中的虛函式,這麼做的好處是使得程式設計師的意圖更清晰的同時讓編譯器可以發現這一錯誤:當使用override標記了某個函式,但該函式並沒有覆蓋已存在的虛函式,編譯器將報錯。

struct a;

struct b : a ;

還能將某個函式指定為final,表示之後任何嘗試覆蓋該函式的行為都會引發錯誤:

struct a ;

struct b : a ;

虛函式與預設實參:

和其它函式一樣,虛函式也可以擁有預設實參,如果某此函式呼叫使用了預設實參,則該實參值由本次呼叫的靜態型別決定。也就是說當使用基類的引用或指標呼叫函式時會使用基類中定義的的預設實參,即使實際上執行的是派生類中的函式版本也是如此,因此虛函式如果使用預設實參,則基類和派生類中定義的預設實參最好是一致的。

迴避虛函式的機制:

有時希望呼叫虛函式不根據動態繫結,而是自己指定版本,比如在派生類的虛函式中想要呼叫基類的虛函式版本,可以通過作用域運算子來實現:

//f為虛函式

//強行呼叫obj類的虛函式版本,不管p所指向的物件的型別到底是什麼

auto ret = p->obj::f();

還是之前的例子,如果沒有作用域運算子,那麼在派生類的虛函式中還會呼叫自身的虛函式,就可能導致無限遞迴呼叫下去。

C Primer第五版筆記 關聯容器

一 型別 關聯容器支援高效的關鍵字查詢和訪問,標準庫中兩個主要的關聯容器是map和set。map中的元素是鍵值對關鍵字表示索引。set中每個元素只包含乙個關鍵字,set支援高效的關鍵字查詢。關聯容器根據三個特性可以分為8種 1 set還是map 2 關鍵字是否可以重複,允許重複的容器名字中都包含單詞...

C Primer第五版筆記 動態陣列

allocator類 為了讓new分配乙個物件陣列,需要在型別名後跟方括號,括號中是分配物件的數目,該數目必須是整型,但不必是常量 new t 分配的記憶體並不是得到乙個陣列,而是得到乙個陣列元素型別的指標,因此不能對動態陣列呼叫begin和end 與普通陣列不同的是,普通陣列不能定義長度為0的陣列...

C Primer第五版筆記 拷貝控制

拷貝賦值函式 析構函式 三 五法則 default和阻止拷貝 乙個類通過定義五種特殊的成員函式來控制其拷貝 賦值 移動以及銷毀操作 拷貝建構函式 拷貝賦值運算子 移動建構函式 移動賦值運算子和析構函式。這些操作都是拷貝控制操作。當實現自己的類的時候要想好在做這些操作時的規則,因為編譯器通常會自動生成...