In C++ you may declare function with exception specification like this:
int foo() const throw(Exception);
I found those two links:
But several things end up unanswered...
Question 1: why to add exception specification? Will it bring any performance increase? What will be different for compiler? Because it seems just like an information for programmer to me.
Question 2: what will happend (what should happen) if I throw something that isn't in specification? For example:
int foo() throw(int) {
throw char; // Totally unrelated classes, not types in real
}
Question 3: function/method shouldn't throw anything. I found at least two (three, alternative syntax for different compilers) ways to specify no exception throwing:
int foo() throw();
int foo() __attribute(nothrow)__
for gccint foo() nothrow
for visual C++Which one is "correct"? Is there any difference? Which one should I use?
Question 4: "standart exceptions", bad_alloc
,bad_cast
,bad_exception
,bad_typeid
and ios_base::failure
.
Ok bad_alloc
is self explaining and I know how (and more importantly when) to use it (add to exception specification), but what about the others? None of them does really ring a bell... Which "code pieces" are they associated with? Like bad_alloc
is associated with new char[500000]
.
Question 5: If I have exception classes hierarchy, like this:
class ExceptionFileType {
virtual const char * getError() const = 0;
};
class ExceptionFileTypeMissing : public ExceptionFileType {
virtual const char *getError() cosnt {
return "Missing file";
}
}
Should I use:
int foo() throw(ExceptionFileType);
Or:
int foo() throw(ExceptionFileTypeMissing,ExceptionFileTypeNotWritable,ExceptionFileTypeNotReadable,...)
Note: answers with references would be great. I'm looking for good practice tips.
The simple "good practice" tip is: don't use exception specifications.
Essentially the only exception to that is the possibility of an empty exception specification: throw()
. That's sufficiently useful that in C++11 it's been given its own keyword (noexcept
). It's generally agreed that any non-empty exception specification is a lousy idea though.
Exception specifications (other than noexcept
) are officially deprecated -- and unlike many deprecated features, removing this would affect little enough source code that I think there's a good chance it really will eventually be removed (certainly no guarantee, but a pretty fair chance anyway).
As for what happens when/if you do throw an exception of a type not allowed by the exception specification: std::unexpected()
gets invoked. By default, that invokes terminate()
. You can use std::set_unexpected
to set your own handler -- but about all you can reasonably do is add some logging before you terminate()
. Your unexpected handler is not allowed to return.
Question 1
Don't bother. They were a bad idea, and were deprecated in the latest version of the language. They give no benefit to the compiler, since they are checked at runtime; if anything, they might hurt performance in some cases.
Question 2
A function called std::unexpected
will be called. By default, this calls std::terminate
; by default, that terminates the program. Both of these behaviours can be changed, using std::set_unexpected
and std::set_terminate
to install your own handler, if you really want to.
Question 3
throw()
was the standard way to do it; the others are non-portable compiler extensions. In C++11, you might use noexcept
, which gives a compile-time check that nothing can throw, rather than a run-time check that nothing does throw.
Question 4
bad_cast
is thrown when a dynamic_cast
of a reference fails.bad_exception
is thrown in some weird circumstances when an exception specification is violated.bad_typeid
is thrown if evaluating the argument to typeid
involves dereferencing a null pointerios_base::failure
is thrown by the input/output library (<iostream>
etc.) when some operations failQuestion 5
If you want to allow the entire heirarchy to be thrown, then just specify the base class. But you shouldn't be using exception specifiers at all.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With