2013-08-24 3 views
10

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

Сообщает ли компилятор сообщение об ошибке? И если да, то почему это не в вопросе? –

+0

@DavidHeffernan, thanx, fixed – cpp

+1

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

ответ

8

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

Это правильно, так как общественное деструктор станд :: исключением также определяет throw()

~A() throw(){}; 

от стандарта (N3225) 12.4.4:

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

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

~A(){}; 

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

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

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

+4

Это не говорит всю историю. Сгенерированный компилятором деструктор будет иметь спецификацию «nothrow», если все функции, которые он вызывает напрямую, не допускают исключений (деструкторы нестатических элементов данных и деструкторы базовых классов). Пример не скомпилирован, потому что деструктор элемента 'std :: string' не помечен' throw() '. Попробуйте заменить его на 'const char *' и увидите разницу. – jrok

+1

Оба [gcc 4.8.1] (http://coliru.stacked-crooked.com/view?id=0717ca903ccad574b2dea253a7ad316c-f674c1a6d04c632b71a62362c0ccfc51) и [clang 3.4] (http://coliru.stacked-crooked.com/view?id = 0717ca903ccad574b2dea253a7ad316c-9f343bb235880f7057c63e887501d7f0) скомпилируйте код OP просто отлично. То есть, в C++ 11. Я не знаю, было ли это изменено после C++ 03. – jrok

+0

@jrok Спасибо за полезный комментарий, я обновил свой ответ – hetepeperfan

Смежные вопросы