虛擬函式、抽象類、override和final
初識虛擬函式
用virtual關鍵字說明的函式;
虛擬函式是實現執行時多型性基礎;
C++中的虛擬函式是動態繫結的函式;
虛擬函式必須是非靜態的成員函式,虛擬函式經過派生之後,就可以實現執行過程中的多型;
一般成員函式可以是虛擬函式;
建構函式不能是虛擬函式;
解構函式可以是虛擬函式;
一般虛擬函式成員
虛擬函式的宣告: virtual 函式型別 函式名(形參表);
虛擬函式宣告只能出現在類定義中的函式原型宣告中,而不能在成員函式實現的時候。
在派生類中可以對基類中的成員函式進行覆蓋。
虛擬函式一般不宣告為行內函數,因為對虛擬函式的呼叫需要動態繫結,而對行內函數的處理是靜態的。
virtual 關鍵字
1)派生類可以不顯式地用virtual宣告虛擬函式,這時系統就會用以下規則來判斷派生類的一個函式成員是不是虛擬函式:
該函式是否與基類的虛擬函式有相同的名稱、引數個數及對應引數型別;
該函式是否與基類的虛擬函式有相同的返回值或者滿足型別相容規則的指標、引用型的返回值;
2)如果從名稱、引數及返回值三個方面檢查之後,派生類的函式滿足上述條件,就會自動確定為虛擬函式。這時,派生類的虛擬函式便覆蓋了基類的虛擬函式。
3)派生類中的虛擬函式還會隱藏基類中同名函式的所有其它過載形式。
4)一般習慣於在派生類的函式中也使用virtual關鍵字,以增加程式的可讀性。
純虛擬函式
1)純虛擬函式是一個在基類中宣告的虛擬函式,它在該基類中沒有定義具體的操作內容,要求各派生類根據實際需要定義自己的版本,純虛擬函式的宣告格式(虛擬函式後面加上=0)為: virtual 函式型別 函式名(引數表) = 0;
2)帶有純虛擬函式的類稱為抽象類。
抽象類
帶有純虛擬函式的類稱為抽象類: class 類名 { virtual 型別 函式名(引數表)=0; //其他成員…… }
注意:抽象類只能作為基類來使用。不能定義抽象類的物件。
抽象類作用
1)抽象類為抽象和設計的目的而宣告
2)將有關的資料和行為組織在一個繼承層次結構中,保證派生類具有要求的行為。
3)對於暫時無法實現的函式,可以宣告為純虛擬函式,留給派生類去實現。
override
多型行為的基礎:基類宣告虛擬函式,繼承類宣告一個函式覆蓋該虛擬函式
覆蓋要求: 函式簽名(signatture)完全一致
函式簽名包括: 函式名 引數列表 const
下列程式就僅僅因為疏忽漏寫了const,導致多型行為沒有如期進行
顯式函式覆蓋
- C++11 引入顯式函式覆蓋,在編譯期而非執行期捕獲此類錯誤。 - 在虛擬函式顯式過載中運用,編譯器會檢查基類是否存在一虛擬函式,與派生類中帶有宣告override的虛擬函式,有相同的函式簽名(signature);若不存在,則會回報錯誤。
final
C++11提供的final,用來避免類被繼承,或是基類的函式被改寫
例: struct Base1 final { };
struct Derived1 : Base1 { }; // 編譯錯誤:Base1為final,不允許被繼承
struct Base2 { virtual void f() final; };
struct Derived2 : Base2 { void f(); // 編譯錯誤:Base2::f 為final,不允許被覆蓋 };