web-dev-qa-db-ja.com

C ++の継承と関数のオーバーライド

C++では、基本クラスのメンバー関数は、同じ名前の派生クラス関数によってオーバーライドされますか?プロトタイプ(パラメーターの数、タイプ、および定数)が異なっていても?多くのウェブサイトが、関数プロトタイプはそれが起こるために同じでなければならないと言っているので、これはばかげた質問だと思います。しかし、なぜ以下のコードがコンパイルされないのですか?非常に単純な継承のケースだと思います。

#include <iostream>
using std::cout;
using std::endl;

class A {};
class B {};

class X
{
public:
    void spray(A&)
    {
        cout << "Class A" << endl;
    }
};

class Y : public X
{
public:
    void spray(B&)
    {
        cout << "Class B" << endl;
    }
};

int main()
{
    A a;
    B b;
    Y y;

    y.spray(a);
    y.spray(b);

    return 0;
}

GCCスロー

error: no matching function for call to `Y::spray(A&)'
note: candidates are: void Y::spray(B&)
21
legends2k

これを説明するために使用される用語は、「オーバーライド」ではなく「非表示」です。派生クラスのメンバーは、デフォルトで、同じ署名を持つかどうかに関係なく、同じ名前の基本クラスのメンバーにアクセスできなくなります。基本クラスのメンバーにアクセスする場合は、using宣言を使用してそれらを派生クラスにプルできます。この場合、class Yに以下を追加します。

using X::spray;
28
Mike Seymour

それはいわゆる「非表示」です:Y::spray非表示X::spray。 usingディレクティブを追加します。

class Y : public X
{
public:
   using X::spray;
   // ...
};
10

クラスはスコープであり、クラススコープはその親にネストされています。他のネストされたスコープ(名前空間、ブロック)とまったく同じ動作をします。

名前ルックアップが名前の定義を検索すると、現在の名前空間が検索され、次にエングロビン名前空間が検索され、1つの定義が見つかるまで続きます。その後、検索が停止します(これは、引数に依存する名前のルックアップによって発生する複雑さを考慮していません。これは、引数の1つの名前空間で定義された関数の使用を許可するルールの一部です)。

5
AProgrammer