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.
Related
#include <iostream>
#include <exception>
using namespace std;
struct MyException : public exception {
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) {
//Other errors
}
}
In above program, initializing MyException class is done in catch function parameter as catch(MyException& e) and initialization can also be done without & symbol.
My doubt is object of MyException class really created when & is used? What is the trick here?
the initialization happens here:
throw MyException();
because there you are creating a new instance of the class MyException...
anonymous instance (the object is not assigned to any variable declared by you) but there is the point where the constructor of your class is invoked and in consequence the initialization.
There's nothing special about exception classes. They're simply classes. Yes, they are intended to be used to communicate exception information, but any type can be used for that. So don't get hung up on the exception code itself; it has nothing to do with when the object is created. return MyException(); would create an object of type MyException. So does throw MyException();.
I'd like to catch an exception while trying to use copy constructor of some class, which would throw.
#include <iostream>
class dont_copy_me {
public:
dont_copy_me() {}
dont_copy_me(const dont_copy_me& rhs) {throw;}
dont_copy_me(dont_copy_me&& rhs) {throw;}
~dont_copy_me() {}
};
int main() {
try {
dont_copy_me obj;
dont_copy_me obj_1(obj);
} catch(...) {
std::cout << "exception caught" << std::endl;
}
return 0;
}
But I keep getting
terminate called without an active exception
Aborted (core dumped)
What is wrong? How do I catch the exception thrown by copy constructor? (because that's what I need)
Actually throw an exception like this:
#include <iostream>
#include <stdexcept>
class dont_copy_me {
public:
dont_copy_me() {}
dont_copy_me(const dont_copy_me& rhs) {throw std::runtime_error("Fail!");}
dont_copy_me(dont_copy_me&& rhs) {throw std::runtime_error("Fail!");}
~dont_copy_me() {}
};
int main() {
try {
dont_copy_me obj;
dont_copy_me obj_1(obj);
} catch(...) {
std::cout << "exception caught" << std::endl;
}
return 0;
}
This does what you need. Here you can find a list of standard exceptions (under "Exception categories").
The empty throw expression only works when you are already handling an active exception:
Rethrows the currently handled exception. Abandons the execution of the current catch block and passes control to the next matching exception handler (but not to another catch clause after the same try block: its compound-statement is considered to have been 'exited'), reusing the existing exception object: no new objects are made. This form is only allowed when an exception is presently being handled (it calls std::terminate if used otherwise). The catch clause associated with a function-try-block must exit via rethrowing if used on a constructor.
From here, emphasis mine.
Your catch (...) block is fine, the problem is your program does not throw an exception.
There are two forms of throw expression:
throw <some-exception> create and throw an exception
throw re-throw the current exception
In your code, you are calling the second form from your copy constructors. Use the first form instead.
The second form is used when you want to some partial handling of an exception. Here's a contrived example program that uses both forms:
#include <cstdexcept>
#include <cstdlib>
#include <iostream>
int main()
{
int ret = EXIT_FAILURE ;
try
{
try
{
throw std::logic_error("Fail!"); // form 1
ret = EXIT_SUCCESS;
}
catch (...)
{
std::clog << "re-throwing" << std::endl;
throw; // form 2
}
}
catch (...)
{
std::cerr << "unhandled exception" << std::endl;
}
return ret;
}
See: http://en.cppreference.com/w/cpp/language/throw
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;
}
I have a try catch statement in my main function
try
{
app.init();
}
catch(std::string errorMessage)
{
std::cout << errorMessage;
return 1;
}
but when I throw "SOME_ERROR"; The console output is simply
terminate called after throwing an instance of 'char const*'
Aborted (core dumped)
How can I make errorMessage output to the console?
Please do not throw anything which is not derived from std::exception.
An exemption might be an exception intended to terminate the program (providing an internal state, though)
You either intend to throw std::string OR catch const char*:
throw std::string("error")
catch(const char* message)
However as pointed out, it's better just to derive from std::exception:
#include <iostream>
// must include these
#include <exception>
#include <stdexcept>
struct CustomException : std::exception {
const char* what() const noexcept {return "Something happened!\n";}
};
int main () {
try {
// throw CustomException();
// or use one already provided
throw std::runtime_error("You can't do that, buddy.");
} catch (std::exception& ex) {
std::cout << ex.what();
}
return 0;
}
You need to derive something from std::exception. <--if you want memory safety
It has a method: virtual const char* ::std::exception::what() const noexcept;
Build your char* you want to see in the constructor, store it, return it for what() then free it in the destructor for memory safe exceptions.
I like boost::exception quite a bit, but I'm quite bothered it does not provide a proper what() function out of the box. Now don't get confused, it does have a nice boost::diagnostic_information that contains all the information I would like to see in my hypothetic what() function but since boost::exception does not inherit from std::exception the what() function I get if I multiple inherit (as suggested from the tutorial, see line below) is the default useless what() from the std::exception base that explains nothing about the exception.
struct my_exception: virtual std::exception, virtual boost::exception { };
Now obviously I tried to override what() and make it return boost::diagnostic_information but somehow it just does not work, so I'm a bit puzzled. That might be because it would loop but I'm not quite sure.
PS: The reason I want to implement what() right is that it is shown by default by a lot of tools if your program dies from them (e.g. the gnu compiler will show a nice fatal error, and display what(), boost unit tests tools etc.).
Here's a link to the test code below
#include <boost/exception/all.hpp>
struct my_exception: virtual std::exception, virtual boost::exception {};
struct my_exception2: virtual std::exception, virtual boost::exception {
virtual const char* what() const throw() {
return "WHAT";
}
};
struct my_exception3: virtual std::exception, virtual boost::exception {
virtual const char* what() const throw() {
return boost::diagnostic_information(this).c_str();
}
};
int main() {
try {
BOOST_THROW_EXCEPTION(my_exception());
} catch (const std::exception& e){
std::cout << e.what() << std::endl;
//This is useless ___ std::exception
}
try {
BOOST_THROW_EXCEPTION(my_exception());
} catch (const boost::exception& e){
std::cout << boost::diagnostic_information(e) << std::endl;
//This is what I'd like to see ___ main.cpp(39): Throw in function int main() ___ Dynamic exception type: boost::exception_detail::clone_impl ___ std::exception::what: std::exception
}
try {
BOOST_THROW_EXCEPTION(my_exception2());
} catch (const std::exception& e){
std::cout << e.what() << std::endl;
//Overriding what usually works ___ WHAT
}
try {
BOOST_THROW_EXCEPTION(my_exception3());
} catch (const std::exception& e){
std::cout << e.what() << std::endl;
//But somehow here it does not work ___ Unknown exception.
}
}
First, boost::diagnostic_information takes an exception by (const) reference, and this is a pointer:
return boost::diagnostic_information(*this).c_str();
^-- here
Second, once you've fixed that, as you've correctly anticipated this results in infinite recursion as boost::diagnostic_information calls std::exception::what(). It is possible to work around this with a guard member or something similar:
struct my_exception3: std::exception, boost::exception {
mutable bool in_what = false;
virtual const char* what() const throw() {
struct g { bool &b; ~g() { b = false; } } guard{in_what};
return in_what ? "WHAT" : (in_what = true, boost::diagnostic_information(*this).c_str());
}
};
Finally, you're using c_str from a destructed temporary string. I'll leave the solution to that problem as an exercise.
And the winner is...
namespace boost {
char const * diagnostic_information_what( boost::exception const & e ) throw();
}