Исключение деструктора исключения std:

Следующая программа не компилируется в g++ 4.4, если line 8 прокомментирован. Зачем? Кажется, что когда я переопределяю конструктор 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()’

Ответ 1

Это потому, что для деструктора требуется спецификатор throw(). Если вы не укажете его в своем классе, компилятор записывает собственный дескриптор по умолчанию для вашего класса, а деструктор по умолчанию не указывает, что вы не бросаете исключения.

Это правильно, так как публичный деструктор std:: exception также указывает throw()

~A() throw(){};

из стандарта (N3225) 12.4.4:

Если класс не имеет объявленного пользователем деструктора, деструктор неявно объявляется как > дефолт (8.4). Неявно- объявленный деструктор является встроенным публичным членом своего класса.

Поэтому, если вы сами не объявляете деструктор, компилятор создает следующий деструктор. Если все деструкторы членов исключения, где nothrow квалифицированы, компилятор, вероятно, будет генерировать деструктор с указанным throw().

~A(){};

И технически можно было бы исключить из этого деструктора исключение, но это был бы очень плохой стиль программирования, поэтому исключение из std::exception гарантирует, что вы не бросаете никаких исключений в деструктор производного класса std::exception.

Изменить Новые компиляторы предоставят деструктор, который имеет спецификатор noexcept, если указан деструктор std::string noexcept. И другие компиляторы также сгенерируют деструктор noexcept, если все деструкторы-члены не генерируют исключений (не являются допустимыми). Это предусмотрено стандартом С++ 11 в главе 15.4. [Except.spec]

14 Неявно объявленная специальная функция-член (пункт 12) должна иметь спецификацию исключения. Если f неявно объявленный конструктор по умолчанию, конструктор копирования, перемещение конструктора, деструктор, назначение копии оператора или оператора переадресации, его неявное исключение-спецификация задает тип-идентификатор T тогда и только тогда если T разрешено исключением-спецификацией функции, непосредственно вызываемой fs неявным определением; f разрешить все исключения, если какая-либо функция, которую он вызывает напрямую, допускает все исключения, а f не допускает исключений если каждая вызываемая им функция не допускает никаких исключений. [...]