10

line 8次のプログラムは、がコメントされている場合、g++ 4.4 でコンパイルされません。なんで?コンストラクタをオーバーライドするときはstd::exception、デストラクタもオーバーライドする必要があるようです。これの理由は何ですか?

#include<iostream>
#include<exception>
using namespace std;

class A : public exception {
public:
    A(string msg) : _msg(msg) {}
    //~A() throw(){};                     // line 8
    const char* what() const throw() { return _msg.c_str();}    
private:
    string _msg;
};

int main()
{
}

コンパイルエラーは次のとおりです。

error: looser throw specifier for ‘virtual A::~A()’
4

1 に答える 1

8

これは、デストラクタが throw() 指定子を必要とするためです。クラスで指定しない場合、コンパイラはクラスの独自のデフォルトのデストラクタを作成し、デフォルトのデストラクタは例外をスローしないことを指定しません。

std::exception の public デストラクタも指定しているため、これは正しいです。throw()

~A() throw(){};

標準 (N3225) 12.4.4 から:

クラスにユーザー宣言のデストラクタがない場合、デストラクタは暗黙的に >defaulted (8.4) として宣言されます。暗黙的に宣言されたデストラクタは、そのクラスのインライン パブリック メンバです。

したがって、デストラクタを自分で宣言しないと、コンパイラは次のデストラクタを作成します。すべての例外メンバー デストラクタがnothrow修飾されている場合、コンパイラはおそらく指定されたデストラクタを生成しthrow()ます。

~A(){};

技術的には、このデストラクタから例外をスローすることもできますが、それは非常に悪いプログラミング スタイルです。したがって、派生クラスstd::exceptionのデストラクタで例外をスローしないことを保証する例外から派生します。std::exception

Editnoexcept新しいコンパイラは、std::string のデストラクタが指定されている場合、指定子 を持つデストラクタを提供しnoexceptます。noexceptまた、すべてのメンバーのデストラクタが例外をスローしない (noexcept 修飾されている) 場合、他のコンパイラもデストラクタを生成します。これは、15.4 章の C++11 標準によって義務付けられています。【スペック以外】

14 暗黙的に宣言された特別なメンバー関数 (第 12 節) には、例外指定が必要です。f が暗黙的に宣言されたデフォルト コンストラクター、コピー コンストラクター、ムーブ コンストラクター、デストラクタ、コピー代入演算子、またはムーブ代入演算子である場合、その暗黙的な例外仕様は、例外仕様によって T が許可されている場合にのみ、型 ID T を指定します。 f の暗黙の定義によって直接呼び出される関数。f が直接呼び出す関数がすべての例外を許可する場合、f はすべての例外を許可し、f が直接呼び出すすべての関数が例外を許可しない場合、f は例外を許可しません。[...]

于 2013-08-24T09:05:10.977 に答える