非コンスト仮想メソッドをオーバーライドすると、const過負荷が隠されていますか?

StackOverflow https://stackoverflow.com/questions/4152799

質問

検討:

#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に隠されているようです。これは私にとって非常に理にかなっていますが、標準によって義務付けられていますか?

役に立ちましたか?

解決

これを(もう一度)リンクします 記事 :

まず、[コンパイラ]は即時の範囲(この場合はクラスCの範囲を調べ、Fが見つけることができるすべての関数のリストを作成します(アクセス可能かどうかに関係なく、または適切な数の数を取るかどうかに関係なくパラメーター)。 それが行われない場合にのみ、次の囲まれたスコープに「外向き」を続けます [...]

そうです、 const のバージョン f 隠されており、それは完全に正常です。 Simoneが指摘したように、あなたは using もたらす声明 A::fC 範囲。

他のヒント

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

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)。

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

あなたのコードが以下のように(おそらく何年も)機能していたと想像してください。

struct Base {
};

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

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

次に、ベースを変更して、まったく違うことを行う方法を含める必要がありますが、何らかの理由で、「F」という名前を付けたいと思います。

struct Base {
  void f(int);
};

このルールがなければ、 毎日 派生した呼び出しFの使用は手動で評価する必要があります。そして、ベースが他の人に与えられたライブラリにある場合、他の用途にもアクセスできない場合があります。ユーザー定義(暗黙の)変換に直面して悪化します。

代わりに、宣言を使用してベースから与えられた名前をインポートすることを明示的に述べるために、派生クラスを要求することが決定されました。このルールは驚くかもしれませんし、今日の言語に対する純利益であるかどうかはわかりませんが、彼らは私に尋ねませんでした - 当時、私はおそらく2音節の言葉でしか答えられなかったでしょう。 :)

入れる using B::f;

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

C ++Standard2003。13.2P.1:

同じ名前の2つの関数宣言は、同じ範囲にあり、同等のパラメーター宣言(13.1)がある場合、同じ関数を指します。派生クラスの関数メンバー ではありません 基本クラスの同じ名前の関数メンバーと同じ範囲で。

したがって C::f すべてを隠します A::f.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top