2011-01-12 4 views
6
struct level0 
{ 
    virtual void foo() = 0; 
}; 

struct level1 : level0 
{ 
    virtual void foo() { cout <<" level1 " << endl; } 
}; 

struct level2 : level1 
{ 
    virtual void foo() { cout <<" level2 " << endl; } 
}; 

struct level3 : level2 
{ 
    using level1::foo; 
}; 

int main() 
{ 
    level1* l1 = new level3; 
    l1->foo(); 
    level3 l3; 
    l3.foo(); 
    return 0; 
} 

上記のコード使用してgccが継承された仮想関数を使用する宣言は非表示にする必要がありますか?

level2 
level1 

を与えるが、ICCに正しいか、それが標準で定義されていない1

level2 
level2 

いますか?

編集:これは確かにバグがあることを証明 は、だから、直接使用したのと同じオブジェクトが異なる結果を生成し、同じ型のポインタ経由で使用する場合は、異なる結果を生成し、次の主な機能

int main() 
{ 
    level3 l3; 
    l3.foo();    // This prints level1 

    level3* pl3 = &l3; 
    pl3->foo();    // This prints level2 

    level3& rl3 = l3; 
    rl3.foo();    // This prints level1 

    level3& rpl3 = *pl3; 
    rpl3.foo();    // This prints level2 

    return 0; 
} 

を考えます!!!もちろん、レベル1レベル1を取得する

+0

私はGCCが正しいと思いますが、わかりません。 –

+0

おかしい、私は昨日これを調べていた。 – aschepler

+0

TDM MinGW g ++ 4.4.1の動作を確認しました。これはg ++のバグです。報告してください。 Cheers&hth。 –

答えて

5

標準セクション10.3p2の例では、宣言を使用してでなく、仮想関数をオーバーライドすることが明らかになりました。

これはknown g++ bugです。

あなたが気づいたように、ダイナミックタイプがわかっている場合ではなく、参照またはポインタを介してメンバー関数を呼び出すと、バグは発生しません。

+0

+1はバグレポートへの参照です。 –

+1

標準的な見積もりの​​場合+1、2004年に報告されたバグ、2006年の最終更新 - >誰も本当に気にしないでしょう:) –

0

の方法は、次のようになります。

struct level3 : level2 
{ 
    virtual void foo() { level1::foo(); } 
}; 

あなたの「使用する」ディレクティブを使用すると、レベル3を持っており、それにFOOを呼び出す場合、それはLEVEL1を呼び出す必要があることをコンパイラに通知しているようですv-tableに上書きしていません。

gccは矛盾のために間違っていますが、iccについてはわかりません。なぜなら、標準が示すものがわからないからです。

1

using level1::foo;は、level1::fooを指すlevel3クラスにfoo関数を導入しています。

メンバー宣言として使用される使用宣言では、ネストされた名前指定子は、定義されているクラスの基本クラスを指定します。このようなusing宣言は、メンバー名検索によって見つかった宣言のセットを導入します。

level1::fooが仮想であるので、私はそれを呼び出すことによって、あなたはICCは右でなければなりませんので、level2::fooを呼ぶべきだと思います。

私はそれほど確かではありません。

関連する問題