C++学習ノート--継承中の同名変数と同名関数

3317 ワード

同じ名前のメンバー
子クラスで親と同じ名前の変数を定義できますか?もしよろしければどうやって区別すればいいですか?
やってみてもいいですか.
class Parent
{
public:
    int mi;
};

class Child : public Parent
{
public:
    int mi;
};
コンパイラがコンパイルできることを発見しました.
親と子では、同じ名前の変数を定義できます.サブクラスオブジェクトcが定義されている場合、c.mi=100.ステートメント
親のメンバー変数が変更されますか、または子のメンバー変数が変更されますか.
答えは、子クラスのメンバー変数の値を変更することです.子クラスのメンバーは、親クラスのメンバーを非表示にします.非表示にするだけです.親クラスの同名のメンバーは子クラスに存在します.ただし、呼び出し方法では、c.Parent::mi=20などの役割ドメイン識別子を使用する必要があります.これを同名カバーと言います.
親と子にコンストラクション関数を追加します.
    Parent()
    {
        cout << "Parent() : " << "&mi = " << &mi << endl;
    }
    Child()
    {
        cout << "Child() : " << "&mi = " << &mi << endl;
    }
どういう意味ですか.サブクラスと親クラスの同名変数を区別するために異なる呼び出し方法を使用するのを見て、それぞれの同名変数のアドレスを印刷することで区別します.
mainで次のプログラムを呼び出します.
    Child c;
    
    c.mi = 100;    
    
    c.Parent::mi = 1000;
    
    cout << "&c.mi = " << &c.mi << endl;
    cout << "c.mi = " << c.mi << endl;
    
    cout << "&c.Parent::mi = " << &c.Parent::mi << endl;
    cout << "c.Parent::mi = " << c.Parent::mi << endl;
mainでは、サブクラスオブジェクトのデフォルト呼び出し変数miと、役割ドメイン分解子によってクラスオブジェクトのmi変数を呼び出す2つの呼び出し方式が使用されています.
プログラム実行プロセスは、まずコンストラクション関数を呼び出してサブクラスオブジェクトを作成し、親コンストラクション関数を呼び出してからサブクラスコンストラクション関数を呼び出し、mi変数に2つの方法で値を割り当て、最後に2つの呼び出し方法のメンバー変数値とアドレスを印刷します.まず、出力結果を見てみましょう.
Parent():&mi=0 x 68 fee 8 Child():&mi=0 x 68 feec&c.mi=0 x 68 feec c.mi=100&c.Parent::mi=0 x 68 fee 8 c.Parent::mi=1000見えますか、デフォルトの呼び出し方式で印刷された値は100で、そのアドレスはサブクラス構築関数で印刷されたメンバー変数アドレスと同じで、役割ドメイン分解子を使用した呼び出しmi変数値は1000です.アドレスは、親コンストラクション関数で印刷されたメンバー変数アドレスと同じです.デフォルトの呼び出しで動作するのは、役割ドメイン識別子を使用しない限り、親クラスの同じ名前のメンバー変数を上書きする子クラスの同じ名前のメンバー変数であることを示します.
同じ名前のメンバー変数が存在することを許可する理由1つの変数は独自の役割ドメインでしか使用できないことを知っています.したがって、同じ名前の変数を許可する本質は、実際には同じ役割ドメイン内ではありません.
同名関数
同じ名前の関数といえば、関数のリロードの本質は複数の異なる関数であり、関数名とパラメータリストは一意の識別であり、同じ役割ドメインでしか発生しません.
サブクラスで定義された関数が親クラスの同名の関数を再ロードできるかどうかを考えます.
2つのクラス、親クラス、および子クラスを作成し、親クラスで関数を再ロードします.
class Parent
{
public:
    int mi;

    void add(int v)
    {
        mi += v;
    }

    void add(int a, int b)
    {
        mi += (a + b);
    }
};

class Child : public Parent
{
public:
    int mi;
    
};
Childオブジェクトcを作成し、
c.add(1)を呼び出す.およびc.add(2,3);コンパイルできますか?もちろんいいです.継承関係である以上、ChildクラスはParentクラスのすべてのコードを継承しているので、呼び出しは親クラスのメンバー関数ですが、加算も親クラスのメンバー変数miで、親クラスのメンバー関数は後でmiという変数が現れることを知ることはできません.
次に、サブクラスでaddを再ロードします.
    void add(int x, int y, int z)
    {
        mi += (x + y + z);
    }
では、c.add(4,5,6)を元のベースで呼び出します.試し:
当ててもいいですか.
答えはコンパイルエラーです.Child::add(int)とChild::add(int,int)の2つの関数が一致しません.サブクラスの同じ名前の関数も親クラスの同じ名前の関数を上書きするため、親クラスの同じ名前のメンバー関数を呼び出すことができません.したがって、これは関数リロードとは呼ばれません.関数リロードは同じ役割ドメインでのみ発生し、関数の同名オーバーライドと呼ばれます.もちろん、親クラスの同名関数は、役割ドメイン分解子によって呼び出されます.
まとめ;
子クラスでは、親クラスと同じ名前のメンバー変数を定義できます.
子クラスのメンバーは、親クラスの同じ名前のメンバー変数を非表示にします.
子クラスの関数は、親クラスの同じ名前の関数を非表示にします.
役割ドメインが異なるため、子クラスは親クラスのメンバー関数を再ロードできません.
親クラスの同名メンバー関数にアクセスするには、役割ドメイン分解子を使用します.
子クラスでは、親クラスとまったく同じメンバー関数を定義できます.