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:每個 D 對象都是 B 對象。若 D 重定義 mf,產生矛盾:
D 真需不同實現,則 D 不應 is-a B(不應公有繼承)。D 必須 is-a B,則 mf 不應為不變量(應聲明為 virtual)。D 真 is-a B 且 mf 為不變量,則 D 無需重定義。無論哪種情況,重定義繼承的非虛函數都違背設計邏輯。
《多態基類中將析構函數聲明為虛擬》是本條款的特例:基類析構函數若非虛,派生類重定義它即違反本條款,導致通過基類指針刪除派生對象時行為未定義。