1

次のコードを検討してください

class X{
public:
    virtual void foo(X x){  }
    virtual void foo(int index){ }

};

class Y : public X{
public:

    void foo(int index){ }
};


int main(){
    Y y;
    y.foo(X()); //Error, see below
}

クラスXが仮想fooメソッドをオーバーロードしました。1つのバージョンはを取り、Xもう1つのバージョンはを取りますint。これで、クラスはメソッドYを継承しXてオーバーライドしますfoo(int)。メソッドfoo(X)はオーバーライドされません。同じままである必要があります。

Yただし、メソッドで型のオブジェクトを作成してmainを呼び出すfoo(X)と、コンパイラは次のように文句を言います。

In function ‘int main()’:
error: no matching function for call to ‘Y::foo(X)’
note: candidate is:
note: virtual void Y::foo(int)
note:   no known conversion for argument 1 from ‘X’ to ‘int’

したがって、唯一の候補はオーバーライドされたfoo(int)メソッドです。他の方法は単に消えたようです。オーバーライドするバージョンを削除すると、つまり、Yとして宣言するとpublic Y : public X{};、すべてが正常に機能します。なぜこれが起こるのですか?

4

2 に答える 2

5

派生クラスが基本クラスのメンバーと同じ名前のメンバーを定義する場合、派生クラス名は基本クラス名を非表示にします。

あなたの場合、関数Y::foo はを非表示 X::fooにします。あなたはそれを次のように範囲に入れる必要がありますY

class Y : public X{
public:

    using X::foo;  //it brings X::foo into the scope of Y

    void foo(int index){ }
};
于 2012-09-18T13:49:00.107 に答える
1

オーバーロードは、同じスコープで定義された名前に適用されます。したがって、fooinクラスは、異なるスコープで定義されているため、クラス内のsをYオーバーロードしません。これは非公式に「名前の非表示」として知られています。基本クラス名を派生クラスにプルするには、usingディレクティブを追加します。fooX

using X::foo;
于 2012-09-18T14:28:22.153 に答える