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.
An exception should be caught by reference rather than by value. The analyzer detected a potential error that has to do with catching an exception by value. It is much better and safer to catch exceptions by reference.
To be more specific, if you caught std::exception by reference and you just simply use throw; , you will still rethrow the original SpecialException , while if you throw e , that SpecialException will be copied into std::exception so we lose information pretty much the same way as we lost information in the case of ...
Exception handling in C++ is done using three keywords: try , catch and throw . To catch exceptions, a portion of code is placed under exception inspection. This is done by enclosing this portion of code in a try block. When an exception occurs within the try block, control is transferred to the exception handler.
You should always list catched exceptions. They are predicted. If you want to catch unpredicted exceptions and handle them the same way, you should catch RuntimeException instead.
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"; }
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