|
|
noexcept
.Nowadays it is assumed that the destructor never throws even if there is no such indication. |
Because a catch block can catch it as a base class instead of the most derived class, and it needs to be able to deallocate it properly. Remember: exceptions are caught by reference - catching them by value is a mistake. |
If a virtual function has an exception specification, all declarations, including the definition, of any function that overrides that virtual function in any derived class shall only allow exceptions that are allowed by the exception specification of the base class virtual function, unless the overriding function is defined as deleted. - IS |
A declaration of a destructor that does not have an exception-specification has the same exception specification as if had been implicitly declared - IS |
|
|
clang version 3.6.0 (tags/RELEASE_360/final 235480) main.cpp:9:5: error: exception specification of overriding function is more lax than base version ~C() {} ; // *** error *** : looser exception specifier ^ main.cpp:1:20: note: overridden virtual function is here struct A { virtual ~A() throw() {} }; ^ 1 error generated. g++ (GCC) 5.2.0 main.cpp:9:5: error: looser throw specifier for 'virtual C::~C() throw (int)' ~C() {} ; // *** error *** : looser exception specifier ^ main.cpp:1:20: error: overriding 'virtual A::~A() throw ()' struct A { virtual ~A() throw() {} }; |
|
|
A declaration of a destructor that does not have an exception-specification has the same exception specification as if had been implicitly declared |
An implicitly declared special member function (Clause 12) shall have an exception-specification. If f is an implicitly declared default constructor, copy constructor, move constructor, destructor, copy assignment operator, or move assignment operator, its implicit exception-specification specifies the type-id T if and only if T is allowed by the exception-specification of a function directly invoked by f’s implicit definition; f shall allow all exceptions if any function it directly invokes allows all exceptions, and f shall allow no exceptions if every function it directly invokes allows no exceptions.[ Example: struct A { A(); A(const A&) throw(); A(A&&) throw(); ~A() throw(X); }; struct B { B() throw(); B(const B&) throw(); B(B&&) throw(Y); ~B() throw(Y); }; struct D : public A, public B { // Implicit declaration of D::D(); // Implicit declaration of D::D(const D&) throw(); // Implicit declaration of D::D(D&&) throw(Y); // Implicit declaration of D::~D() throw(X, Y); }; Furthermore, if A::˜A() or B::˜B() were virtual, D::˜D() would not be as restrictive as that of A::˜A, and the program would be ill-formed since a function that overrides a virtual function from a base class shall have an exception-specification at least as restrictive as that in the base class. —end example ] |
Quark wrote: |
---|
I doubt that C++11 forbids a destructor to throw since C++03 allows it. That change would be incompatible. |
|
|
warning C4290: C++ exception specification ignored except to indicate a function is not __declspec(nothrow) |
warning C4290: C++ exception specification ignored except to indicate a function is not __declspec(nothrow) |
error C2694: 'C::~C(void) throw(int)': overriding virtual function has less restrictive exception specification than base class virtual member function 'A::~A(void) throw()' |