virtual 函式指定符

2021-09-08 00:07:16 字數 3595 閱讀 2784

virtual 指定符指定非靜態成員函式為虛並支援動態繫結。它只能出現在非靜態成員函式首個宣告(即它宣告於類定義中時)的 decl-specifier-seq 中。

虛函式是在派生類中行為可被覆寫的成員函式。與非虛函式相反,覆寫的行為會受到保留,即使沒有關於該類實際型別的編譯時資訊。若使用到基類的指標或引用處理派生類,則對被覆寫虛函式的呼叫,將會呼叫定義於派生類的行為。若使用有限定名稱查詢(即若函式名出現在作用域解決運算子::的右側),則此行為被壓制。

執行此**

#include struct base 

};struct derived : base

};int main()

consteval虛函式不能覆寫非consteval虛函式或被它覆寫。

若某成員函式vf在類base中宣告為virtual,且某個直接或間接從base派生的類derived擁有下列幾點與之相同的成員函式宣告

要覆寫的base::vf不需要可見(可宣告為 private ,或用私有繼承繼承)。

class b  // 公開繼承

};struct d : public b ;

int main()

對於每個虛函式,存在最終覆寫者,它在虛函式呼叫進行時執行。基類base虛成員函式vf是最終覆寫者,除非派生類宣告或繼承(通過多重繼承)另一覆寫vf的函式。

struct a ;     // a::f 為 virtual

struct b : a ; // b::f 覆寫 a::f in b

struct c : virtual b ; // c::f 覆寫 a::f in c

struct d : virtual b {}; // d 不引入覆寫者, b::f 在 d 中為最終

struct e : c, d ;

int main()

若函式擁有多於乙個覆寫者,則程式為病式:

struct a ;

struct vb1 : virtual a ;

struct vb2 : virtual a ;

// struct error : vb1, vb2 ;

struct okay : vb1, vb2 ;

struct vb1a : virtual a {}; // 不宣告複寫者

struct da : vb1a, vb2 ;

擁有同名和相異引數列表的函式不覆寫同名的基類函式,但隱藏它:在非限定名稱查詢檢驗派生類的作用域時,查詢找到該宣告,且不檢驗基類。

struct b ;

struct d : b ;

struct d2 : d ;

int main()

若函式以指定符override宣告,但不覆寫虛函式,則程式為病式:

struct b ;

struct d : b ;

若函式以指定符final宣告,且另一函式試圖覆寫之,則程式為病式

struct b ;

struct d : b ;

(c++11 起)

非成員函式和靜態成員函式不能為虛。

函式模板不能為虛virtual。這只應用於自身是模板的函式——類模板的常規成員函式能宣告為虛。

虛函式(無論是宣告為 virtual 者還是覆寫者)不能有任何關聯制約

struct a ;
若覆寫的函式指定契約條件,則它必須指定與其所覆寫的函式相同的契約條件列表;不要求診斷對應的條件是否始終求值為相同值。否則,認為它擁有來自其所覆寫的函式之一的契約條件列表;在契約條件的出現點,繫結契約條件的名稱,並檢查語義制約。

struct a ;

struct b : a ;

struct c : a ;

若虛函式f的契約條件 odr 使用 *this ,則f作為直接成員所屬的類,必須是任何於其中覆寫f的類的無歧義且可訪問的基類。

struct a ;

struct b : a ;

struct c : a, b ;

若乙個函式覆寫多於乙個函式,則所有被覆寫函式必須擁有相同的契約條件列表;若對應的條件始終求值為相同值則不要求診斷。

struct a ;

int x = 42;

struct b

struct c : a, b ;

(c++20 起)

在編譯時替換虛函式的預設實參。

協變返回型別

若函式derived::f覆寫base::f,則其返回型別必須相同或為協變。若滿足所有下列要求,則二個型別為協變:

derived::f的返回型別中的類必須是derived自身,或必須是於derived::f宣告點的完整型別。

進行虛函式呼叫時,最終覆寫者的返回型別被隱式轉換成本該呼叫的被覆寫函式的返回型別:

class b {};

struct base ;

class d : private b ;

class a; // 前置宣告類是不完整型別

struct derived : public base ;

int main()

虛析構函式

雖然析構函式是不繼承的,若基類宣告器其析構函式為virtual,則派生的析構函式始終覆寫它。這使得可以通過指向基類的指標 delete 動態分配的多型型別物件

class base }; 

class derived : public base }; 

int main()

而且,若類為多型(宣告或繼承至少乙個虛函式),且其析構函式非虛,則刪除它是未定義行為,無關乎若不呼叫派生的析構函式是否導致資源洩漏。

一條有用的方針,是任何基類的析構函式必須為公開且虛,或受保護且非虛。

當直接或間接從建構函式或從析構函式呼叫虛函式(包含在類的非靜態成員函式的構造或析構期間,例如在初始化器列表中),且應用呼叫的物件是正在構造或析構中的物件,則所呼叫的函式是建構函式或析構函式的類中的最終覆寫者,而非進一步派生類中的覆寫者。 換言之,在構造和析構期間,進一步派生類不存在。

構建有多分支的複雜類時,在屬於乙個分支的建構函式內,多型被限制到該類與其基類:若它獲得到其子層級外的基類子物件的指標,且試圖進行虛函式呼叫(例如通過顯式成員訪問),則行為未定義:

struct v ;

struct a : virtual v ;

struct b : virtual v ;

struct d : a, b }; 

// b 的建構函式,從 d 的構造函式呼叫

b::b(v* v, a* a)

virtual 虛函式

virtual 虛函式 下面是對c 的虛函式這玩意兒的理解。一,什麼是虛函式 如果不知道虛函式為何物,但有急切的想知道,那你就應該從這裡開始 簡單地說,那些被virtual關鍵字修飾的成員函式,就是虛函式。虛函式的作用,用專業術語來解釋就是實現多型性 polymorphism 多型性是將介面與實現進...

虛函式(virtual)

上面提到動態多型主要通過虛函式機制實現,這裡介紹以下虛函式。和普通的函式宣告方式相同,只要在函式的返回值前加上virtual關鍵字,該函式就為虛函式,即virtual 函式型別 函式名 形式引數 虛函式的作用 允許通過基類的指標或引用來訪問基類和派生類的同名函式。include using name...

析構函式virtual與非virtual區別

析構函式virtual與非virtual區別 作為通常的原則,如果乙個類定義了虛函式,那麼它的析構函式就應當是virtual的。因為定義了虛函式則隱含著 這個類會被繼承,並且會通過基類的指標指向子類物件,從而得到多型性。這個類可能會被繼承,並且會通過基類的指標指向子類物件 因此基類的析構函式是否為虛...