『Effective C+』学習ノート——条項36

1000 ワード

六、継承とオブジェクト向け設計
条項36、継承されたnon-virtual関数を再定義しない
Rule 36. Never redefine an inherited non-virtual function.
ベースクラスにpublic関数がある場合、派生クラスポインタを作成してベースクラスオブジェクトにこの関数を呼び出し、ベースクラスポインタを作成してこのオブジェクトにこの関数を呼び出すと、結果は同じですか?違う!派生クラスでは、ベースクラスの関数を再定義すると、ベースクラスの対応する関数がマスクされ、派生クラスを通じて関数が呼び出されるため、ベースクラスのバージョンではなく、派生クラスのバージョンになります.
class B {
public:
    void mf();
    ...
};
class D : public B  {
public:
    void mf();    //      B mf  (     33)
    ...
};

D x;
B* pB = &x;
D* pD = &x;
pB->mf();    //    B::mf
pD->mf();    //    D::mf

このような現象の原因は,non−virtual関数,例えばB::mfおよびD::mfが静的バインドであるためである.しかし、virtual関数はダイナミックバインドなので、この問題は発生しません.
前の条項32においても、public継承はis−a関係を意味すると述べている.条項34においても、class内でnon−virtual関数がclassのために不変性を確立する理由について説明する.この例では、次のように表現されています.
  • は、各DオブジェクトがBオブジェクトであるため、Bオブジェクトのすべてのことに適用され、Dオブジェクトにも適用される.
  • Bクラスの派生クラスは、mfがBのnon-virtual関数であるため、mfのインタフェースと実装を継承するに違いない.

  • したがって、上述したように、継承されたnon−virtual関数は、いかなる場合においても再定義すべきではない.