8

重複の可能性:
親クラスに抽象クラス メンバーを
実装する C++ では、基底クラスが派生クラスの継承されたインターフェイスを実装できないのはなぜですか?

これらのオブジェクトを考慮する:

struct A
{
    virtual void foo() = 0;
};

struct B
{
    void foo() { /* neat implementation */ }
};

なぜ -- コンパイラの観点から -- 次のオブジェクトが抽象的と見なされるのか疑問に思います。

struct C : B, A
{
    using B::foo; // I tried my best to make the compiler happy
};

コンパイラは私にこれをさせません:

A* a = new C;

Visual Studio 2010 は次のように述べています。

'C' : 次のメンバのために抽象クラスをインスタンス化できません: 'void A::foo(void)' : 抽象です : 'A::foo' の宣言を参照してください

g++ 4.6.3 は次のように述べています。

次の仮想関数は 'C' 内で純粋であるため、抽象型 'C' のオブジェクトを割り当てることができません: virtual void A::foo()

これはC#で許可されていると思いますが、関連するメカニズムはわかりません-興味があるだけです。

4

4 に答える 4

7

残念ながら、これはあなたが望むことを完全には行いません。

usingディレクティブは、使用されるスコープにいくつかの名前を持ち込むことです。virtualメソッドはオーバーライドする必要があり、名前を持ち込むだけではオーバーライドとは見なされません。

実際のところ、C++ は委譲を直接サポートしていません。名前を明示的にスコープに入れるには、このわずかなひねりがあります。

于 2012-05-10T12:25:14.210 に答える
4

struct Bたまたま呼び出されfoo、引数を取らない関数を実装しています。その関数は明らかに とはまったく関係がありませんA::foo。したがって、がとのstruct C両方から派生する場合、継承されたことになります。AB

  • の実装を提供する責任A::foo
  • B::fooと同じ名前とシグネチャを持つが、A::fooまったく関係のないメソッド

問題は明らかだと思います。AC# と同等のものとして使用しようとしていますがinterface、その概念を C++ で表現する方法はありません。

ディレクティブは、 のスコープに持ち込むだけなので、ここusingでは役に立ちません。つまり、後者が class 内で検出されたときに、名前を解決する候補として考慮する必要があることをコンパイラに伝えます。残念ながら、これは純粋仮想メソッドを実装する責任とは関係ありません。B::fooCB::foofooC

于 2012-05-10T12:24:53.523 に答える
2

これを解決するには、C 内で独自に実装しfoo()、B 関数を明示的に呼び出す必要があります。つまり、C 内で A::foo を B::foo に効果的に転送します。

struct C : B, A
{
  virtual void foo() {
    // Override A::foo by forwarding to B::foo:
    B::foo();
  }
};

A::foo() と B::foo() の間に固有の関係はありません。C 内で明示的に確立する必要があります。

于 2012-05-10T12:30:14.877 に答える
1

これはC#で許可されていると思います

C++ は C# ではありません。

virtual void foo()void foo()は 2 つの異なる方法です。

virtual A::fooA と B の両方から派生すると、 と 非仮想 の2 つのメソッドにアクセスできますB::foo。そしてvirtual A::foo抽象的です。したがって、コンパイラエラー。

于 2012-05-10T12:34:08.700 に答える