首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 箴言:絕不重定義繼承的非虛擬函數

     編輯:關於C++

現象:靜態綁定導致行為雙面性

class B { public: void mf(); };
class D : public B { public: void mf(); }; // 隱藏 B::mf
D x;
B* pB = &x; pB->mf(); // 調用 B::mf
D* pD = &x; pD->mf(); // 調用 D::mf

非虛函數靜態綁定:調用版本取決於指針/引用的聲明類型,而非對象實際類型。虛函數則為動態綁定,總調用最派生版本。

理論依據:public inheritance = is-a + 非虛函數 = 不變量

  • public inheritance 意味著 is-a:每個 D 對象都是 B 對象。
  • 基類中的非虛函數定義了超越特化的不變量:所有派生類必須繼承其接口和實現。

若 D 重定義 mf,產生矛盾:

  1. 若 D 真需不同實現,則 D 不應 is-a B(不應公有繼承)。
  2. 若 D 必須 is-a B,則 mf 不應為不變量(應聲明為 virtual)。
  3. 若 D 真 is-a B 且 mf 為不變量,則 D 無需重定義。

無論哪種情況,重定義繼承的非虛函數都違背設計邏輯。

關聯:析構函數必須為虛

《多態基類中將析構函數聲明為虛擬》是本條款的特例:基類析構函數若非虛,派生類重定義它即違反本條款,導致通過基類指針刪除派生對象時行為未定義。

記住要點

  • 絕不重定義繼承的非虛擬函數。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved