9

検討:

#include <iostream>

using namespace std;

struct A {
  virtual void f() { cout << "A::f" << endl; }
  virtual void f() const { cout << "A::f const" << endl; }
};

struct B : public A {};

struct C : public A {
   virtual void f() { cout << "C::f" << endl; }
};


int main()
{
   const B b;
   b.f();   // prints "A::f const"

   const C c;
   c.f();
   // Compile-time error: passing ‘const C’ as ‘this’ argument of
   //   ‘virtual void C::f()’ discards qualifiers
}

(私はGCCを使用しています。)

したがって、f()のconstバージョンはCに隠されているようです。これは私には非常に理にかなっていますが、標準で義務付けられていますか?

4

4 に答える 4

6

私は(もう一度)この素晴らしい記事をリンクします:

まず、[コンパイラ]は直接のスコープ(この場合はクラスCのスコープ)を調べ、fという名前の関数のリストを作成します(アクセス可能かどうか、または適切な数の関数を取得するかどうかに関係なく)パラメーター)。そうでない場合にのみ、次の囲んでいるスコープに「外側」に進みます[...]

そうです、のconstバージョンfは非表示になっていますが、これは完全に正常なことです。シモーネが指摘したように、usingステートメントを使用A::fしてCスコープを取り込むことができます。

于 2010-11-11T09:30:37.757 に答える
3

はい、そうです。あなたは書くことができます:

struct C : public A {
   virtual void f() { cout << "C::f" << endl; }
   using A::f;       
};

コードをコンパイルするには:

int main()
{
   const B b;
   b.f();   // prints "A::f const"

   const C c;
   c.f();   // prints "A::f const"
}

詳細については、2010 C ++ドラフトドキュメント(ここにあります)の第10.2章(3-4)を参照してください。

于 2010-11-11T09:21:22.917 に答える
3

基本メンバーを隠すのは仮想性や恒常性(またはその欠如)ではなく、派生メソッドは同じ名前の基本メソッドを隠します。これは、壊れやすい基本クラスの問題を改善するために行われました。

関連性のない部分が削除された状態で、コードが以下のように(おそらく何年も)機能していたと想像してください。

struct Base {
};

struct Derived : Base {
  void f(double);
}

void g(Derived &d) {
  d.f(42);
}

次に、Baseを変更して、まったく異なることを行うメソッドを含める必要がありますが、何らかの理由で、「f」という名前を付けます。

struct Base {
  void f(int);
};

このルールがないと、派生呼び出しfのすべての使用を手動で評価する必要があります。また、Baseが他の人に提供されたライブラリにある場合は、他の使用にアクセスできない可能性があります。ユーザー定義の(暗黙の)変換に直面すると、さらに悪化します。

代わりに、派生クラスに、using宣言を使用してBaseから指定された名前をインポートすることを明示的に指定するように要求することが決定されました。このルールは驚くべきものであり、今日の言語に正味のメリットがあるかどうかはわかりませんが、彼らは私に尋ねませんでした。当時、私はおそらく2音節の単語でしか答えることができなかったでしょう。:)

于 2010-11-11T09:37:43.350 に答える
2

入れるusing B::f;

struct C : public A { 
   using A::f;
   virtual void f() { cout << "C::f" << endl; } 
}; 

C ++標準2003。13.2p.1:

同じ名前の2つの関数宣言は、それらが同じスコープ内にあり、同等のパラメーター宣言(13.1)を持っている場合、同じ関数を参照します。派生クラスの関数メンバーは、基本クラスの同じ名前の関数メンバーと同じスコープにありません。

したがってC::f、すべてを非表示にしますA::f

于 2010-11-11T09:20:42.930 に答える