2009-06-06 15 views
3

は、私はちょうどこのコードの次のブロックは、C++で完全に有効であるかどうかを知りたいと思った:これは有効なC++コードですか?

class A 
{ 
public: 
    virtual bool b() = 0; 
}; 

class B 
{ 
public: 
    virtual bool b() = 0; 
}; 

class C: public A, public B 
{ 
public: 
    virtual bool A::b() 
    { 
    return true; 
    } 

    virtual bool B::b() 
    { 
    return false; 
    } 
}; 

それがエラーなしでコンパイルVS2008を使用して、しかし、GCC(MinGWの)上で、それは私のようなエラーが発生します3.4.5:

cannot declare member function `A::b' within `C' 

仮想メソッドが実装されている行について。これは一般的に無効であると考えられていて、C++標準の禁止コード(VSではGCCのバグやサポートされていない魔法のおかげで動作します)に興味がありました。

答えて

17

いいえ、それは無効です。同じシグニチャを持つため、それらを別々に上書きすることはできません。

guru of the weekです。

+1

とは別に、非仮想のdtorは目立つ爆弾です。それは問題ではありませんでした。 :) – wilhelmtell

1

修飾名A :: Bは、それが原因同じ関数名を持つ親にコンパイルしてはならないクラスC.

1

のメンバーの名前として許可されていません。さらに、関数bを複数回オーバーロードすることは想定されていません。

あなたはこのために作成した仮想テーブルを参照する場合:

0(beginning of vtable) - A::b() -> B::b() 

クラスBがクラスAと同じ関数名を持っているので、あなたは、このようにあなたが今B :: Bを(持っている、それはそれを上書きし、参照してください)をオーバーライドする(まだ純粋なので)。これは多重継承のためです。コンパイラはどのようにして2つのものを区別できますか(同じシグネチャを持っています)?一般的には、これは失敗します。なぜなら、私が言ったように、コンパイラは意思決定をしないと考えているから、問題があると言います。

VSでコンパイルしましたが、実行してみましたか(実際に作成されたファイルに含まれていますか?)。時々、コンパイラは怠惰で、使用されていないクラスではエラーをポップしません。あなたはbメソッドを使用しようとする場合にのみ

+0

>コンパイラはどのように2つのシグニチャを区別できますか? しかし、これは、たとえば、複数の基底を持つクラスがあり、共通の親基底を持っている場合(仮想継承をしばしば使用する必要がある場合など)にも発生します。もちろん、コンパイラは(仮想継承を使用しない場合)共通メソッドへの呼び出しを区別できず、あいまいな呼び出しエラーをスローしますが、クラスインスタンスを必要な基本クラスに動的にキャストすることで簡単に解決できます。そして、はい、私はこれをVSでこの方法で使用しており、問題なく動作します。 – RedDragCZ

+0

@RedDragCZ:私が仮想継承を使用している限り、サブクラスを同じ基本クラスから継承させる場合のみです。 litbリンクを見ると、提案されている解決策は補助クラスと呼ばれるものを使用することです。 – tomzx

0

ちょうどFYI、VCがエラーを与えるよう:

C:\temp\test.cpp(33) : error C2668: 'C::b' : ambiguous call to overloaded function 
     C:\temp\test.cpp(23): could be 'bool C::b(void)' 
     C:\temp\test.cpp(18): or  'bool C::b(void)' 
     while trying to match the argument list '(void)' 

そして、それは価値がある何のために、コモのコンパイラは、同様に動作しますが、さらに混乱エラーメッセージで:

"C:\temp\test.cpp", line 33: error: no instance of overloaded function "C::b" 
      matches the argument list 
      object type is: C 
     bool z = c.b(); 
+0

はい、私は、b()メソッドはもちろん動作しないことを意味するものではなく、ヒープに割り当てられたCインスタンスをダウンキャストしてb() dynamic_cast (c_instance_on_heap) - > b() '(これは私自身のコードではAとBをインタフェースとして使用するため完全に適用できます)。 – RedDragCZ

+0

しかし、コンパイラは、メソッドが宣言されたときにメソッドにアクセスするまで待つのではなく、メソッドを宣言しようとしたときに文句を言うべきです。なぜコンパイラがこの動作を使用するのかわかりません。 –

関連する問題