effective C++ 條款 36:絕不重新定義繼承而來的non-virtual函數

來源:互聯網
上載者:User

class B {
public:
    void mf();
    ...
};
class D : public B {...};

D x;

如果一下行為:

B* pB = &x;

pB->mf();

異於以下行為:

D* pD = &x;

pD->mf();

你可能相當驚訝。兩者的行為確實應該相同,但是如果mf是個non-virtual函數而D定義有自己的mf版本:

class D : public B {
public:
    void mf();
    ...
};
pB->mf();//調用B::mf
pD->mf();//調用D::mf

造成這一行為的原因是,non-virtual函數都是靜態繫結的。由於pB被聲明為一個pointer-to-B,通過pB調用的non-virtual函數永遠是B所定義的版本,即使pB指向一個類型為“B派生之Class”的對象。

virtual函數是動態綁定的,如果mf是個virtual函數,不論通過pB還是通過pD調用mf,都會導致調用D::mf,因為pB和pD真正指的都是D的對象。

reference也會展現和指標一樣難以理解的這中精神分裂的不一致行為。

public繼承意味著is-a關係。

如果有non-virtual函數mf,B的derived class一定會繼承mf的介面和實現。

現在,如果D重新定義mf,你的設計就出現矛盾。如果D真有必要實現出與B不同的mf,並且如果每一個B對象--不管多麼特化--真的必須使用B所提供的mf實現碼,那麼“每個D都是一個B”就不為真。既然如此,D就不應該以public形式繼承B。

另一方面,如果D真的必須以public方式繼承B,並且D真有需要實現出與B不同的mf,那麼mf就無法為B反應出“不變性淩駕特異性”的性質。既然這樣mf應該聲明為virtual函數。

最後,如果D真的是個B,並且如果mf真的為B反應出“不變性淩駕特異性”的性質,那麼D便不需要重新定義mf,而且也不應該嘗試這樣做。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.