8
class A
{
    public:
    virtual ~A()
    {
    }
};

class B : virtual public A
{
    public:
    ~B() throw()
    {}
};

class C : public B
{
};

int main(int argc, char * argv [])
{
return 0;
}

そのコードは次のエラーを出します:

error: looser throw specifier for ‘virtual C::~C()’
error:   overriding ‘virtual B::~B() throw ()’

私のdebianテストでは(gcc(Debian 4.6.0-10)4.6.1 20110526(プレリリース))、以前のgccバージョン(私のdebianシステムでは4.5)ではエラーなしでコンパイルされます。

例外仕様は仮想デストラクタのオーバーライドにどのように影響しますか? その答えによると、コンパイラは基本クラスのthrow宣言に一致するデフォルトのコンストラクタを作成することになっています。明らかに、これは新しいgccで起こることではありません。変更点、正しいコンパイラの動作、および派生クラス(コンパイラフラグなど)に空のデストラクタを手動で追加する以外に、問題の簡単な解決策はありますか。

4

2 に答える 2

3

実際のコードでは、仮想として宣言されていると思います~A()か? ~B()(エラー メッセージは仮想デストラクタについて不平を言っていますが、記述されているコードでは仮想デストラクタはありません。)

仮想継承が問題の引き金になっていると思います。C の (暗黙的に定義された) デストラクタは、最初に を呼び出し~B()てから、C が最も派生したクラスであるため、 を呼び出す必要があります~A()。(12.4/6)

に対して生成された例外仕様は、例外仕様を持たない~C()ものを直接呼び出すため、例外を伝播できるようにする必要があります。~A()(15.4/13)

throw()そして、それがあなたのエラーを引き起こします -仕様 (B のデストラクタ) で仮想関数をスローする可能性のあるバージョンでオーバーライドすることはできません。(15.4/3)

解決策はthrow()、A のデストラクタを配置することです。(それができないなら、なぜBでやってるの?)

また、仮想継承がなければエラーは発生しません。C のデストラクタは B のデストラクタのみを呼び出すためです。(B のデストラクタは依然として A のデストラクタを呼び出します。A のデストラクタがスローした場合、あなたはまっすぐにterminate().

于 2011-07-19T21:19:42.727 に答える
0

GCC 4.X は、以前のバージョンよりも厳密であるため、暗黙的に宣言しない場合があります。はっきり言ってみてください。

クラスBに明示的に何もスローしないデストラクタがある場合(つまり.

class B: public A
{
public:
virtual ~B() throw { }
}

大丈夫です。

とにかく、前回チェックしたとき、d'tors から例外をスローするのは非常に悪い習慣でした。

それがあなたの助けになることを願っています!

于 2011-06-30T18:26:51.583 に答える