C++ Primer 5th笔记(chap 15 OOP)虚函数
生活随笔
收集整理的這篇文章主要介紹了
C++ Primer 5th笔记(chap 15 OOP)虚函数
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1. 定義
基類希望其派生類進行覆蓋的函數(虛函數)。
- 基類通過在成員函數前面加上 virtual 函數使得該函數執行動態綁定。
- 任何構造函數之外的非靜態函數都可以是虛函數。
- 關鍵字 virtual 只能出現在類內部聲明語句之前,不能用于類外部的函數定義。
- 如果基類把一個函數寫成虛函數,則該函數在派生類中隱式地也是虛函數。
1.1 虛函數的調用可能在運行時才被解析
1.2 注意:
- 基類的析構函數通常都應該定義成虛函數。
- 一旦某個函數被聲明成虛函數,則在所有的派生類中它都是虛函數
1.3 看一個派生類的函數是否覆蓋基類的虛函數
- 若沒有,則該函數的行為類似于其他成員,派生類會直接繼承其在基類中的版本,認為兩個函數相互獨立
- 若有,則它的形參類型必須被它覆蓋的基類函數完全一致;返回類型也必須相同。該規則存在一個例外:類的虛函數返回類型是本身的指針或引用。
2. final 和 override 說明符
2.1 override
C++ 11 新標準使用 override 關鍵字來覆蓋基類的虛函數
struct B {virtual void f1(int) const;virtual void f2();void f3(); };struct D1 : B {void f1(int) const override; // ok: f1 matches f1 in the basevoid f2(int) override; // error: B has no f2(int) functionvoid f3() override; // error: f3 not virtualvoid f4() override; // error: B doesn't have a function named f4 }- 如果基類并沒有覆蓋已存在的虛函數,或者參數不對應則都會產生編譯錯誤。
2.2 final
函數也可以通過添加final關鍵字來禁止覆蓋操作。
struct D2 : B {// inherits f2() and f3() from B and overrides f1(int)void f1(int) const final; // subsequent classes can't override f1(int) }; struct D3 : D2 { void f1(int) const ; // error };2.3 final 和 override 關鍵字應該出現在形參列表(包括任何const或引用修飾符)以及尾置返回類型之后。
3. 默認實參
虛函數也可以有默認實參,每次函數調用的默認實參值由本次調用的靜態類型決定。
如果通過基類的指針或引用調用函數,則使用基類中定義的默認實參,即使實際運行的是派生類中的函數版本也是如此。
eg.
struct A{ void f1(int a, int b = 0) const {std::cout << "a f1" << endl;}};struct B : A{void f1(int a, int b = 2) const {std::cout << "b f1" << endl;}};A a;B b;a.f1(1);b.f1(1);A* pa = &b; pa->f1(1);輸出:
a f1 b f1 a f1- 如果虛函數使用默認實參,則基類和派生類中定義的默認實參值最好一致。
4. 回避虛函數的機制
可以使用作用域符限制虛函數的動態綁定,而是強迫其執行虛函數的某個特定版本
//強行調用基類中定義的函數版本而不管baseP的動態類型到底是什么 double undiscounted=baseP->Quote::net_price(42);- 通常情況下,只有成員函數(或者友元)中的代碼才需要使用作用域運算符來回避虛函數的機制。
- 通常是一個派生類的虛函數調用它覆蓋的基類的虛函數版本時。
注意:如果一個派生類虛函數需要調用它的基類版本,但是沒有使用作用域運算符,則在運行時該調用將被解析為對派生類版本自身的調用,從而導致無限遞歸。
【引用】
[1] 代碼oopTest.h
總結
以上是生活随笔為你收集整理的C++ Primer 5th笔记(chap 15 OOP)虚函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++ Primer 5th笔记(cha
- 下一篇: C++ Primer 5th笔记(cha