有効なC ++項目33:オブジェクト指向の継承(避けるカバー継承名)

まず、隠れ変数の使用規則

  • 同じグローバルとローカル変数、ローカルスコープがある場合は、グローバルスコープの変数名は、ローカル変数の優先使用を隠されています
  • 例えば:
int x; //全局变量

void someFunc()
{
    double x; //局部变量
    std::cin >> x; //局部变量赋值
]

第二に、隠ぺいや書き換えの連続(カバー)

  • クラス/関数メンバで定義された変数グループは、派生クラスが、同じ名前を定義したとき、基底クラス/関数の変数は、派生クラスのメンバを非表示になります

ケース・プレゼンテーション

class Base
{
private:
    int x;
public:
    virtual void mf1() = 0;
    virtual void mf2();
    void mf3();
};

class Derived :public Base
{
public:
    virtual void mf1(); //重写(覆盖)
    void mf4(){
        fm2(); //调用基类中的fm2
    }
};
  • 上記のカテゴリの関係を次のように:

  • 次のようにFM4()関数呼び出しFM2()関数で、FM2()関数の検索順序に派生することです:
    • FM4()関数ではまず見て、そうでない場合は次のステップ
    • その後、派生クラスで、そうでない場合は次のステップ
    • そして、ベースクラスベースで見て(それが基本クラスBase呼び出す見つけるために)
    • ベースが見つからなかったと仮定すると、ベースがに位置している名前空間で見て、グローバル検索にはスコープが引き続き存在しない場合

第三に、すべての基本クラスの隠蔽

  • 基底クラスが過負荷一連の機能が含まれている場合に限り、派生クラスは、ベースクラスと同じ名前の関数を定義するように、派生クラスのベースクラスのすべてのオーバーロード機能であるすべての隠された(パラメータリストが矛盾している場合でも)
  • 理由のデザインルール:プログラムライブラリやアプリケーションフレームワーク内の新しい派生クラスを作成するときに、偶然遠くの基本クラスから継承された過負荷を防ぐために

ケース・プレゼンテーション

class Base
{
private:
    int x;
public:
    virtual void mf1() = 0;
    virtual void mf1(int);
    virtual void mf2();
    void mf3();
    void mf3(double);
};

class Derived :public Base
{
public:
    virtual void mf1(); //基类中的所有mf1()都被隐藏
    void mf3();         //基类中的所有fm3()都被隐藏
    void mf4();
};
  • 今すぐ下記のコードが呼び出しています:
Derived d;
int x;

d.mf1();  //正确
d.mf1(x); //错误,Base::fm1(int)被隐藏了

d.mf2();  //正确

d.mf3();  //正确
d.mf3(x); //错误,Base::mf3(double)被隐藏了

ステートメントを使用して、基本クラスのメンバ関数の使用を増やします

  • 時には非表示は違反する可能性がある、基底クラスと派生クラスの間の関係(基底クラス我々はいくつかの行為は、派生クラスでも使用することができますしたいので)。したがって、我々はできる宣言は、この隠されたキャンセル使用して式を使用して派生クラスで基本クラスのインポート機能の動作を
  • 注:派生クラス別のアクセスモードを使用した場合、アクセスモードに属する派生クラスに、その後ベースクラス、(パブリック、保護された、プライベート)、宣言を使用して
  • ケースプレゼンテーション:

class Base
{
private:
    int x;
public:
    virtual void mf1() = 0;
    virtual void mf1(int);
    virtual void mf2();
    void mf3();
    void mf3(double);
};

class Derived :public Base
{
public:
    using Base::mf1; //Base所有版本的mf1函数在派生类作用域都可见
    using Base::mf3; //Base所有版本的mf3函数在派生类作用域都可见

    virtual void mf1(); //重写mf1()函数
    void mf3();         //隐藏了mf1(),但是mf3(double)没有隐藏
    void mf4();
};
  • 今すぐ下記のコードが呼び出しています:
Derived d;
int x;

d.mf1();  //正确,调用Derived::mf1()
d.mf1(x); //正确,调用Base::mf1(int)

d.mf2();  //正确,调用Derived::mf2()

d.mf3();  //正确,调用Derived::mf3()
d.mf3(x); //正确,调用Base::mf3(double)

使用ケア機能

  • 時には、派生クラスの基本クラスから継承されたプライベートな方法では、その後、ベースクラスのすべての内容は、すべての派生クラスには見えないです
  • プライベート、派生クラスは、ベースクラスまたは非表示/機能(上書き)メンバーを書き換えることができます例えば:
class Base
{
public:
    void mf1() {}
    void mf1(int) {}
};

class Derived :private Base
{
public:
    void mf1() {} //隐藏了基类的mf1()
};

int main()
{
    Derived d;
    int x;

    d.mf1();  //正确,使用Derived::mf1()
    d.mf1(x); //错误

    return 0;
}
  • この時点で、我々はまた、usingステートメントを使用することができ、基本クラスのすべてのヘビーデューティーバージョンには、派生クラスに表示されます。例えば:
class Base
{
public:
    void mf1() {}
    void mf1(int) {}
};

class Derived :private Base
{
public:
    using Base::mf1; //使Base中的所有mf1版本在派生类作用域中都可见
    void mf1() {}    //隐藏Base::mf1()
};

int main()
{
    Derived d;
    int x;

    d.mf1();  //正确,使用Derived::mf1()
    d.mf1(x); //正确,使用Base::mf1(int)

    return 0;
}
  • もちろん、いくつかのケースでは、我々は、基本クラスのすべてのオーバーロードされたバージョンはしたくない派生クラスで表示されている、あなたは気付け自分で機能を設計することができます例えば:
class Base
{
public:
    virtual void mf1() = 0;
    virtual void mf1(int);
};

class Derived :private Base
{
public:
    //这是一个转交函数
    virtual void mf1() {
        Base::mf1(); //调用基类的mf1()函数
    }
};

int main()
{
    Derived d;
    int x;

    d.mf1();  //正确,虽然调用的是Derived::mf1(),但是本质上调用的是Base::mf()
    d.mf1(x); //错误,Base::mf(double)被隐藏了

    return 0;
}

 

IVの概要

リリース1504元の記事 ウォンの賞賛1063 ビュー43万+

おすすめ

転載: blog.csdn.net/qq_41453285/article/details/104760199