3

これがこの件に関する最初の質問ではないことはわかっていますが、私が読んだ他の関連するすべての質問 (および回答) は、少し的外れでした。コードを取る

#include <iostream>

using namespace std ;

class Base {
public:
    void methodA() { cout << "Base.methodA()" << endl ;}
};

class Derived : public Base {
public:
    void methodA(int i) { cout << "Derived.methodA(int i)" << endl ;}
};

int  main()
{
  Derived obj;
  obj.methodA();
}

このコードを最近のバージョンの g++ でコンパイルすると、エラーが発生します

no matching function for call to 'Derived::methodA()'

答えを見つけるために Stackoverflow に出くわしたのは、このエラーのためです。しかし、どの回答も私を納得させるものではありませんでした。2 つのメソッドのシグネチャは、それらを区別する際にあいまいさを示しません。コンパイラは、基本クラスのメソッドを取得できるはずです。コメントアウトするだけ

class Derived : public Base {
//public:
//    void methodA(int i) { cout << "Derived.methodA(int i)" << endl ;}
};

コードは期待どおりに機能します。つまり、基本クラスで同じ名前のメンバー関数を非表示にするのはメンバー関数名だけであり、関数名がマングルされていない場合のように、署名は考慮されません (この場合、マングルはあいまいさを解決する必要があります)。同様の質問で、これは C++ の精神 (およびオブジェクト指向、私が付け加えます) に反するものであると他の人が書いており、私は彼に完全に同意します。これは関数のオーバーロードの制限であり、私には明確な理由が見当たりません。

どうやら質問はクローズされているようです。そのため、回答を読んだ後、自分の最初の質問を編集する以外に返信を追加することはできません。古い C++ コンパイラでは、最初の質問のコードが問題なくコンパイル (および実行) されることを確信しています (ただし、それを証明する立場にはありません)。私の要点は、その言語設計の背後にある理論的根拠が本当にわからないということです(返信で呼ばれているように)。この場合、コンパイラは適切なアクションを実行するためにすべての情報を利用できます。これは私が期待することです。それ以外の場合は、言語設計の選択により、メンバー関数のシグネチャを考慮しないように選択されているように見えますが、これはかなり奇妙に聞こえます。先ほどの「プログラマーインタビュー」の記事を読んで、

4

3 に答える 3

9

これが言語の設計方法です。内側のスコープの名前は、外側のスコープの名前を隠します。ここで、派生クラスは内部スコープとして機能し、基本クラスは外部スコープとして機能します。

関数が同じスコープ内にある場合、関数がオーバーロードと見なされるという事実は問題ではありません。非表示は、個々の関数ではなく、名前に対して機能します。

派生クラスに名前を明示的に追加することで、デフォルトをオーバーライドできます。

class Derived : public Base {
public:
    using Base::methodA;   // Now it is visible!

    void methodA(int i) { cout << "Derived.methodA(int i)" << endl ;}
};
于 2015-10-05T10:41:17.590 に答える
2

これは、基底クラスで同名のメンバー関数を隠すのはメンバー関数名だけであり、署名は考慮されないことを意味します

正しい。それが言語が設計された方法です。私はその言語設計機能もあまり好きではありません。しかし、それは十分に文書化されており、選択の余地はありません。

于 2015-10-05T10:32:50.827 に答える
0

もうお分かりだと思います。それはName Hidingと呼ばれ、これが言語の作成方法です。しかし、最終的には C++ を使用するときにこれらの規則にかなり慣れるので、不便だとは思いません。ベース メソッドと同じ名前の非仮想メソッドを定義すると、派生クラスのベース クラス メソッドが非表示になるため、次のエラーが発生します。

obj.methodA();

派生クラスで基本クラスのメソッドが隠されないようにするには、次のようにします。

obj.Base::methodA();

詳細情報: http://www.programmerinterview.com/index.php/c-cplusplus/c-name-hiding/

于 2015-10-05T10:40:31.087 に答える