What's the usual way to create & handle exceptions in c++?
class CannotRead : public runtime_exception { ... }
class CannotParse : public runtime_exception { ... }
...
throw CannotRead();
...
or
...
throw runtime_error("cannot read");
...
What's the idiomatic way to do this in C++?
Links to articles comparing both approaches would be appreciated.
Thanks
There's no cut and dry advice to give, but my personal rule of thumb is:
throw std::runtime_error (or one of its siblings, as appropriate)
until you find you need to distinguish at catch-time between your various exceptions, then start deepening the inheritance heirarchy.
Typically, as others have mentioned in comments, you derive from std::runtime_error and overload the what() virtual method. As an exercise to the reader, a constructor can also be written to capture the exception message. This website provided the following code (although I modified it slightly to reflect the std::runtime_error change).
#include <iostream>
#include <exception>
class MyException : public std::runtime_error
{
const char * what () const throw () {
return "C++ Exception";
}
};
int main()
{
try {
throw MyException();
} catch(MyException& e) {
std::cout << "MyException caught" << std::endl;
std::cout << e.what() << std::endl;
} catch(std::exception& e) {
}
return 0;
}
Related
During the member initialisation of a class with multiple members, it seems desirable to be able to catch an exception generated by any specific member initialiser, to wrap in additional context for rethrowing, but the syntax of a function-try-block doesn't appear to accomodate that.
#include <stdexcept>
#include <string>
#include <sstream>
using namespace std::literals::string_literals;
[[noreturn]]
int thrower() { throw std::runtime_error("unconditional throw"s); }
int nonThrower() { return 3; }
class C {
int x;
int y;
public:
C();
};
class XError : public std::runtime_error {
public:
XError(const std::string& what) : std::runtime_error((std::stringstream() << "xerror: "s << what).str()) {};
};
class YError : public std::runtime_error {
public:
YError(const std::string& what) : std::runtime_error((std::stringstream() << "yerror: "s << what).str()) {};
};
C::C() try:
x(nonThrower()),
y(thrower()) {}
catch(const std::exception& e) { /* ... */ }
In the above trivial example, on the final line, I would very much like to be able to throw XError() if the exception occurs in initialisation of .x, and YError() if the exception occurs in initialisation of .y.
Ideally I'd like to be able to do something like
// -std=c++3000
C::C():
try: x(nonThrower()) catch(const std::exception& e) { throw XError(e.what()); },
try: y(thrower()) catch(const std::exception& e) { throw YError(e.what()); } {}
But it seems my only option is to write separate functions per initialiser member which wrap the exceptions themselves, then use those in the member initialisers. Given how ghastly member initialiser syntax is, this will probably read better, but it's less compact and more non-linear, which is less than ideal. For completeness:
int makeX() {
try { return nonThrower(); }
catch(const std::exception& e) { throw XError(e.what()); }
}
int makeY() {
try { return thrower(); }
catch(const std::exception& e) { throw YError(e.what()); }
}
C::C():
x(makeX()),
y(makeY()) {}
Please excuse any antipatterns or mistakes in my C++. I am both very new to the language and not as smart as you might hope me to be.
Is it possible to have a function-try-block per member initialiser?
No, that is not possible.
Sidebar: it seems like you're overusing and/or overthinking exceptions. Most people don't write much exception-handling code, because most programs are fine with just terminating if an exception is thrown, in most places. Of course there are exceptions to this rule, but if you're new to C++ and you're getting hung up on this, you should probably revisit your approach and not make your program so reliant on fine-grained exception handling.
It's not possible, but if you want to go down the exception route you can write function wrappers:
template<typename Exn, typename T>
T catch_with(T (*fn)()) // or, std::function<T()> fn
{
try { return fn(); }
catch(const std::exception& e) { throw Exn(e.what()); }
}
C::C():
x(catch_with<XError>(nonThrower)),
y(catch_with<YError>(thrower) {}
Here's a curious one. I have a class A. It has an item of class B, which I want to initialize in the constructor of A using an initializer list, like so:
class A {
public:
A(const B& b): mB(b) { };
private:
B mB;
};
Is there a way to catch exceptions that might be thrown by mB's copy-constructor while still using the initializer list method? Or would I have to initialize mB within the constructor's braces in order to have a try/catch?
Have a read of http://weseetips.wordpress.com/tag/exception-from-constructor-initializer-list/)
Edit: After more digging, these are called "Function try blocks".
I confess I didn't know this either until I went looking. You learn something every day! I don't know if this is an indictment of how little I get to use C++ these days, my lack of C++ knowledge, or the often Byzantine features that litter the language. Ah well - I still like it :)
To ensure people don't have to jump to another site, the syntax of a function try block for constructors turns out to be:
C::C()
try : init1(), ..., initn()
{
// Constructor
}
catch(...)
{
// Handle exception
}
It's not particularly pretty:
A::A(const B& b) try : mB(b)
{
// constructor stuff
}
catch (/* exception type */)
{
// handle the exception
}
I know it has been awhile since this discussion started. But that try-and-catch construct mentioned by Adam is part of the C++ standard and is supported by Microsoft VC++ and GNU C++.
Here is the program that works. By the way the the catch generates automatically another exception to signal about the constructor failure.
#include <iostream>
#include <exception>
#include <string>
using namespace std;
class my_exception: public exception
{
string message;
public:
my_exception(const char* message1)
{
message = message1;
}
virtual const char* what() const throw()
{
cout << message << endl;
return message.c_str();
}
virtual ~my_exception() throw() {};
};
class E
{
public:
E(const char* message) { throw my_exception(message);}
};
class A
{
E p;
public:
A()
try :p("E failure")
{
cout << "A constructor" << endl;
}
catch (const exception& ex)
{
cout << "Inside A. Constructor failure: " << ex.what() << endl;
}
};
int main()
{
try
{
A z;
}
catch (const exception& ex)
{
cout << "In main. Constructor failure: " << ex.what() << endl;
}
return 0;
}
You could work with lazy initialization, though, that is hold a unique_ptr to Reader in MyClass and create it with new. That way, you do not even need the flag has_reader but you can just see if your unique_ptr is initial or not.
#include <iostream>
#include <memory>
using namespace std;
class MyOtherClass
{
public:
MyOtherClass()
{
throw std::runtime_error("not working");
}
};
class MyClass
{
public:
typedef std::unique_ptr<MyOtherClass> MyOtherClassPtr;
MyClass()
{
try
{
other = std::make_unique<MyOtherClass>();
}
catch(...)
{
cout << "initialization failed." << endl;
}
cout << "other is initialized: " << (other ? "yes" : "no");
}
private:
std::unique_ptr<MyOtherClass> other;
};
int main()
{
MyClass c;
return 0;
}
Of course, there are also solutions without using exceptions at all but I assumed that this is a prerequisite in your setting.
I don't see how you'd do that with initializer-list syntax, but I'm also a bit sceptical that you'll be able to do anything useful by catching the exception in your constructor. It depends on the design of the classes, obviously, but in what case are you going to fail to create "mB", and still have a useful "A" object?
You might as well let the exception percolate up, and handle it wherever the constructor for A is being called.
I have a silly question. I read this article about std::exception http://www.cplusplus.com/doc/tutorial/exceptions/
On catch (exception& e), it says:
We have placed a handler that catches exception objects by reference (notice the ampersand & after the type), therefore this catches also classes derived from exception, like our myex object of class myexception.
Does this mean that by using "&" you can also catch exception of the parent class? I thought & is predefined in std::exception because it's better to pass e (std::exception) as reference than object.
The reason for using & with exceptions is not so much polymorphism as avoiding slicing. If you were to not use &, C++ would attempt to copy the thrown exception into a newly created std::exception, potentially losing information in the process. Example:
#include <stdexcept>
#include <iostream>
class my_exception : public std::exception {
virtual const char *what() const throw() {
return "Hello, world!";
}
};
int main() {
try {
throw my_exception();
} catch (std::exception e) {
std::cout << e.what() << std::endl;
}
return 0;
}
This will print the default message for std::exception (in my case, St9exception) rather than Hello, world!, because the original exception object was lost by slicing. If we change that to an &:
#include <stdexcept>
#include <iostream>
class my_exception : public std::exception {
virtual const char *what() const throw() {
return "Hello, world!";
}
};
int main() {
try {
throw my_exception();
} catch (std::exception &e) {
std::cout << e.what() << std::endl;
}
return 0;
}
Now we do see Hello, world!.
Does this mean that by using "&" you can also catch exception of the parent class?
No, this doesn't increase the scope of where you will catch exceptions from (e.g. from the parent class of the class that contains the try/catch code).
It also doesn't increase the types of exceptions that can be caught, compared to catching by value (catch(std::exception e) without the & - you'll still catch each exception that either is std::exception or derives from it).
What it increases is the amount of data that you will actually get when you catch the exception.
If an exception is thrown that derives from std::exception, and you catch it by value, then you are throwing out any extra behavior in that exception class. It breaks polymorphism on the exception class, because of Slicing.
An example:
class MyException : public std::exception
{
public:
virtual const char* what() const
{
return "hello, from my exception!";
}
};
// ...
try
{
throw MyException();
}
catch(std::exception& e)
{
// This will print "hello, from my exception!"
std::cout << e.what() << "\n";
}
// ...
try
{
throw MyException();
}
catch(std::exception e)
{
// This will print "Unknown exception"
std::cout << e.what() << "\n";
}
No the & has absolutely no bearing on the polymorphic nature of exception handlers. Their wording is very poor, it does seem to indicate that the & is somehow responsible. This is not the case. You are correct, & just passes by reference which is a tad more efficient.
Also as a general rule, you should really try to avoid cplusplus.com.
Updated link: What's wrong with cplusplus.com
Using reference to exception here can reduce the temporary objects created, and it can also keep the polymorphism.
Is there a way to determine the exception type even know you caught the exception with a catch all?
Example:
try
{
SomeBigFunction();
}
catch(...)
{
//Determine exception type here
}
Short Answer: No.
Long Answer:
If you derive all your exceptions from a common base type (say std::exception) and catch this explicitly then you can use this to get type information from your exception.
But you should be using the feature of catch to catch as specific type of exception and then working from there.
The only real use for catch(...) is:
Catch: and throw away exception (stop exception escaping destructor).
Catch: Log an unknwon exception happend and re-throw.
Edited:
You can extract type information via dynamic_cast<>() or via typid()
Though as stated above this is not somthing I recomend. Use the case statements.
#include <stdexcept>
#include <iostream>
class X: public std::runtime_error // I use runtime_error a lot
{ // its derived from std::exception
public: // And has an implementation of what()
X(std::string const& msg):
runtime_error(msg)
{}
};
int main()
{
try
{
throw X("Test");
}
catch(std::exception const& e)
{
std::cout << "Message: " << e.what() << "\n";
/*
* Note this is platform/compiler specific
* Your milage may very
*/
std::cout << "Type: " << typeid(e).name() << "\n";
}
}
You can actully determine type inside a catch(...), but it is not very useful:
#include <iostream>
#include <exception>
class E1 : public std::exception {};
class E2 : public std::exception {};
int main() {
try {
throw E2();
}
catch( ... ) {
try {
throw;
}
catch( const E1 & e ) {
std::cout << "E1\n";
}
catch( const E2 & e ) {
std::cout << "E2\n";
}
}
}
There is no standard, portable way to do this. Here's a non-portable way to do it on GCC and clang
#include <iostream>
#include <cxxabi.h>
const char* currentExceptionTypeName()
{
int status;
return abi::__cxa_demangle(abi::__cxa_current_exception_type()->name(), 0, 0, &status);
}
int main()
{
try {
throw std::string();
} catch (...) {
std::cout<<"Type of caught exception is "<<currentExceptionTypeName()<<std::endl;
}
return 0;
}
Output:
Type of caught exception is std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >
provided that c++11 available,
bool throwing_func()
{
// something is wrong...
throw char('5');
// ...
return true;
}
void exception_handler(std::exception_ptr _Eptr)
{
try
{
if (_Eptr) {std::rethrow_exception(_Eptr);}
}
catch(int _Xi)
{
std::cout << "int\n";
}
catch(char _Xc)
{
std::cout << "char\n";
}
catch(const std::exception& _Xe)
{
std::cout << "std::exception " << _Xe.what() << "\n";
}
catch (...)
{// develop more catch cases above to avoid what follows
std::cout << "unhandled exception\n";
// grande problema
}
}
int main()
{
try
{
throwing_func();
}
catch(...)
{
//Determine exception type here
exception_handler(std::current_exception());
}
return 0;
}
If you need to handle exceptions differently based on what they are, you should be catching specific exceptions. If there are groups of exceptions that all need to be handled identically, deriving them from a common base class and catching the base class would be the way to go. Leverage the power and paradigms of the language, don't fight against them!
No.
Doing so would at the very least require you to be able to access the current exception. I do not believe there is a standard way of doing this.
Once you had the exception instance, you would have to use a type inspection algorithm. C++ doesn't have inherent support for this. At best you would have to have a big if/elseif statement with dynamic_cast's to check the type.
This question was asked some time ago and I'm offering this answer as a companion to the accepted answer from 9 years ago. I'd have to concur with that respondent that that answer, "... is not very useful." Further, it opens the door to an exception which was once handled being unhandled. To illustrate, let me build upon the respondent's answer
#include <iostream>
#include <exception>
class E1 : public std::exception {};
class E2 : public std::exception {};
class E3 : public std::exception {};
int main() {
try {
throw E3();
}
catch( ... ) {
try {
// OOOPS!!! E3 is now unhandled!!!!!!
throw;
}
catch( const E1 & e ) {
std::cout << "E1\n";
}
catch( const E2 & e ) {
std::cout << "E2\n";
}
}
}
An alternative to this approach would be the following:
#include <iostream>
#include <exception>
class E1 : public std::exception {};
class E2 : public std::exception {};
class E3 : public std::exception {};
int main() {
try {
throw E3();
}
catch( const E1 & e ) {
std::cout << "E1\n";
}
catch( const E2 & e ) {
std::cout << "E2\n";
}
catch( ... ) {
std::cout << "Catch-all...";
}
}
This second approach seems to be tantamount to the first and has the advantage of specifically handling E1 and E2 and then catching everything else. This is offered only as an alternative.
Please note that, according to C++ draft of 2011-02-28, paragraph 15.3, bullet item 5, "If present, a ... handler shall be the last handler for its try block."
I've tried various ways; this works for me:
Begin by subclassing runtime_error :
/*----------------------------------------------------------------------*/
/* subclass runtime_error for safe exceptions in try/throw/catch */
#include <stdexcept>
/* a little preprocessor magic here -- makes a subclass of runtime_error*/
#define NEWERROR( NE ) class NE : public runtime_error { \
public: NE ( string const& error ) : runtime_error(error) {} }
NEWERROR( FileError );
NEWERROR( NetworkError );
NEWERROR( StringError );
NEWERROR( CofeeError );
/*----------------------------------------------------------------------*/
Then you may create some instances of your exceptions.
/*----------------------------------------------------------------------*/
/* some example pre-defined exceptions */
FileError ReadOnly ( "ReadOnly" );
FileError FileNotFound ( "FileNotFound" );
NetworkError TimeOutExceeded ( "TimeOutExceeded" );
NetworkError HostNotFound ( "HostNotFound" );
CoffeeError OutOfCoffee ( "OutOfCoffee" );
/*----------------------------------------------------------------------*/
Explicitly notify the compiler that your function may throw an exception
or the program will probably terminate at the point thrown, and data could be lost or corrupted
if resources are in use at the time.
"Make sure you can and do catch anything that you can throw."
(I use the generic runtime_error because throwing and catching it covers all of
my exceptions plus the systems' ones as well.)
/*----------------------------------------------------------------------*/
/* example function that may throw an exception */
#include <fstream>
ifstream& getFileStream (string fname) throw (runtime_error)
{
if ( fname == "" )
throw StringError( "<getFileStream> fname:empty string" );
// processing stops here if thrown
try
{
ifstream Inputfstream;
ifstream& ifsref = Inputfstream;
// ifstream has its own <legacy> exception
// mechanisms and procedures
ifsref.exceptions ( ifstream::failbit | ifstream::badbit );
ifsref.open (fname , ifstream::in); // could fail ==> ifstream::failure exception
}
catch (ifstream::failure e)
{
throw FileError( fname + string(e.what() ) );
}
return ifsref;
}
/*----------------------------------------------------------------------*/
then in your try/catch
/*----------------------------------------------------------------------*/
catch (FileNotFound fnf) //catch a specific error
{
if (DEBUG) cerr << "[File Not Found Error: " << fnf.what() << "]" << endl;
... (handle it) ...
}
catch (FileError fe) //catch a specific type
{
if (DEBUG) cerr << "[File Error: " << fe.what() << "]" << endl;
... (handle it) ...
}
catch (runtime_error re ) // catch a generic type
{
if (DEBUG) cerr << "[Runtime error: " << re.what() << "]" << endl;
// determine type by string comparison
if ( re.what() == string("ResourceNotavailable") ) ...
if ( re.what() == string("NetWorkError") ) ...
...
}
catch ( ... ) // catch everything else
{ ... exit, rethrow, or ignore ... }
/*----------------------------------------------------------------------*/
The runtime-error class has good support in the c++ standard libraries,
and compilers know about it internally, and how to optimize memory and dispatch,
so you can use them over different code bases safely and confidently. The code is portable and compatible with many different compilers and architectures.
It may be preferable and somewhat faster to catch each error separately in a catch clause, from more specific to more generic,if you feel a series of string matches is a terrible waste of cpu and memory (the compiler optimizes these though ).
<stdexcept> gives you several kinds of exceptions in 2 groups:
Logic errors:
logic_error
domain_error
invalid_argument
length_error
out_of_range
Runtime errors:
runtime_error
range_error
overflow_error
underflow_error
usage syntax is slightly different for some of them.
Conventional Wisdom in C++ says that your exceptions should be relatively "flat",
meaning that large hierarchies of specific categories of exceptions should be eschewed in
favor of short generic but informative ones for general programming tasks. Domain specific tasks like network system logic, higher maths, etc. may benefit from specificity, but that can be achieved handily by making intelligent error strings with generic runtime/logic exceptions.
Lastly, My Point is: You can achieve all of this by
throwing and catching only runtime_error.
You don't have to create a whole trick-bag of highly specific exceptions
(like java does) for each class, each handling one specific error.
If you're using Visual C++ (managed), you can use the GetType() method to get the type of exception and handle it from there.
E.g.
try
{
// Run the application
Application::Run(mainForm);
}
catch (Exception^ e)
{
String^ exception_type = e->GetType()->ToString();
throw;
}
The string will contain something like "System.ArgumentOutOfRangeException".
Here's a curious one. I have a class A. It has an item of class B, which I want to initialize in the constructor of A using an initializer list, like so:
class A {
public:
A(const B& b): mB(b) { };
private:
B mB;
};
Is there a way to catch exceptions that might be thrown by mB's copy-constructor while still using the initializer list method? Or would I have to initialize mB within the constructor's braces in order to have a try/catch?
Have a read of http://weseetips.wordpress.com/tag/exception-from-constructor-initializer-list/)
Edit: After more digging, these are called "Function try blocks".
I confess I didn't know this either until I went looking. You learn something every day! I don't know if this is an indictment of how little I get to use C++ these days, my lack of C++ knowledge, or the often Byzantine features that litter the language. Ah well - I still like it :)
To ensure people don't have to jump to another site, the syntax of a function try block for constructors turns out to be:
C::C()
try : init1(), ..., initn()
{
// Constructor
}
catch(...)
{
// Handle exception
}
It's not particularly pretty:
A::A(const B& b) try : mB(b)
{
// constructor stuff
}
catch (/* exception type */)
{
// handle the exception
}
I know it has been awhile since this discussion started. But that try-and-catch construct mentioned by Adam is part of the C++ standard and is supported by Microsoft VC++ and GNU C++.
Here is the program that works. By the way the the catch generates automatically another exception to signal about the constructor failure.
#include <iostream>
#include <exception>
#include <string>
using namespace std;
class my_exception: public exception
{
string message;
public:
my_exception(const char* message1)
{
message = message1;
}
virtual const char* what() const throw()
{
cout << message << endl;
return message.c_str();
}
virtual ~my_exception() throw() {};
};
class E
{
public:
E(const char* message) { throw my_exception(message);}
};
class A
{
E p;
public:
A()
try :p("E failure")
{
cout << "A constructor" << endl;
}
catch (const exception& ex)
{
cout << "Inside A. Constructor failure: " << ex.what() << endl;
}
};
int main()
{
try
{
A z;
}
catch (const exception& ex)
{
cout << "In main. Constructor failure: " << ex.what() << endl;
}
return 0;
}
You could work with lazy initialization, though, that is hold a unique_ptr to Reader in MyClass and create it with new. That way, you do not even need the flag has_reader but you can just see if your unique_ptr is initial or not.
#include <iostream>
#include <memory>
using namespace std;
class MyOtherClass
{
public:
MyOtherClass()
{
throw std::runtime_error("not working");
}
};
class MyClass
{
public:
typedef std::unique_ptr<MyOtherClass> MyOtherClassPtr;
MyClass()
{
try
{
other = std::make_unique<MyOtherClass>();
}
catch(...)
{
cout << "initialization failed." << endl;
}
cout << "other is initialized: " << (other ? "yes" : "no");
}
private:
std::unique_ptr<MyOtherClass> other;
};
int main()
{
MyClass c;
return 0;
}
Of course, there are also solutions without using exceptions at all but I assumed that this is a prerequisite in your setting.
I don't see how you'd do that with initializer-list syntax, but I'm also a bit sceptical that you'll be able to do anything useful by catching the exception in your constructor. It depends on the design of the classes, obviously, but in what case are you going to fail to create "mB", and still have a useful "A" object?
You might as well let the exception percolate up, and handle it wherever the constructor for A is being called.