C++ exception class extension syntax - c++

I am taking a course online and came across some syntax I am not really sure I understand.
#include <iostream>
#include <exception>
using namespace std;
class derivedexception: public exception {
virtual const char* what() const throw() {
return "My derived exception";
}
} myderivedexception;
int main() {
try {
throw myderivedexception;
}
catch (exception& e) {
cout << e.what() << '\n';
}
}
My Problem is with:
virtual const char* what() const throw()
What does this line mean?
also, what is with the
} myderivedexception;
in the end of the class declaration?

This line:
virtual const char* what() const throw()
says that what is a virtual method that returns a pointer to a constant char (which means it can be used to return a string literal, or the contents of a std::string obtained by calling the string::c_str() function), is itself constant so it doesn't modify any class members, and it does not throw any exceptions.
This line:
} myderivedexception;
creates an instance of the derivedexception class named myderivedexception. You probably do not want to do this, but instead throw an unnamed exception:
throw derivedexception();

Related

Exceptions & C-style strings

I've problem with exceptions:
#include <iostream>
#include <cstring>
#include <exception>
class except :public std::exception
{
char* err;
public:
except(const char* s) noexcept
{
err = new char[strlen(s) + 1];
strcpy(err, s);
err[strlen(s)] = 0; //is it necessary??
}
virtual const char* what() noexcept
{return err;}
virtual ~except() noexcept
{delete err;}
};
double div(const double& a, const double& b) noexcept
{
if (b == 0.0)
throw except("DIVIDED BY 0");
return a / b;
}
int main()
{
try
{
std::cout << div(5.0, 0.0);
}
catch (std::exception &ex)
{
std::cout << ex.what();
}
return 0;
}
I want to print "DIVIDED BY 0" but I get:
terminate called after throwing an instance of 'except'
what(): std::exception
Aborted
Process returned 134 (0x86)
Shall I put noexcept in every function/member function that doesn't throw any exceptions?
Is err[strlen(s)] = 0 necessary? (in except::except(const char* s))
I want to print "DIVIDED BY 0" but I get: terminate called after throwing an instance of 'except'
double div(const double& a, const double& b) noexcept
You are claiming that you won’t throw an exception, but you are lying. The result is the call to std::terminate when you actually throw.
The problem is a actually twofold. Firstly, as #manni66 suggests, div should not be declared noexcept and this does cause a run-time error, but removing it does not solve the issue.
The second problem is that what has been declared:
virtual const char* what() noexcept;
whereas it's declared in std::exception as:
virtual const char* what() const noexcept;
and this difference in signature means that when it's caught by the handler for std::exception, it calls std::exception::what() and not except::what()
A couple of points worth mentioning:
Ensure that your function overloads exactly match those in the base class.
If you are expecting a certain type of exception to be thrown then try to catch that first with a specific handler and use an appropriate name for the exception for clarity.
As others have mentioned, please try to use the std::string class if you can. It will make things easier and safer. Although in this case, as point two eludes to, a string member is not really necessary as the class is specific enough not to need further qualification.
Don't create an exception class unless it's adding some specific value (though the value, may simply be that you want to specifically catch a certain type of exception and handle in a certain way.) If you wanted a more general exception then std::runtime_error or in this case std::overflow_error would be decent choices and both take a std::string as an argument to the constructor, so no need to create your own exception class.
For example:
#include <exception>
using namespace std;
class divide_by_zero : public std::exception
{
public:
virtual const char* what() const noexcept { return "DIVIDED BY 0"; }
};
double div(const double& a, const double& b)
{
if (b == 0.0)
throw divide_by_zero();
return a / b;
}
int main()
{
try
{
std::cout << div(5.0, 0.0);
}
catch (divide_by_zero &ex)
{
std::cout << ex.what();
}
catch (std::exception &ex)
{
std::cout << ex.what();
}
return 0;
}
Output:
DIVIDED BY 0

Catching strings for output

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.

How to supplement boost::exception with a proper what() function

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();
}

catching std::exception by reference?

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.

C++ throw dereferenced pointer

What is the type of the exception object in the following thrown:
Question1> range_error r("error"); throw r;
Answer1> an object of range_error
Question2> exception *p = &r; throw *p;
Answer2> a sliced object of exception
Question3> exception *p = &r; throw p;
Answer3> a pointer pointing to range_error is thrown. The capture-handling can access the range_error member functions through dynamic binding.
Do I get these question right?
// Updated and Compiled and Run on VS2010
#include <iostream>
using namespace std;
class ExClassA
{
public:
virtual void PrintMe() const
{
cout << "ExClassA" << endl;
}
};
class ExClassB : public ExClassA
{
public:
virtual void PrintMe() const
{
cout << "ExClassB" << endl;
}
};
int main(int argc, char* argv[])
{
ExClassB exClassB;
ExClassA *p = &exClassB;
try
{
throw *p;
}
catch (const ExClassA& e)
{
e.PrintMe();
}
try
{
throw p;
}
catch (const ExClassA* e)
{
e->PrintMe();
}
}
The first try-catch of above program prints "ExClassA"
The second try-catch of above program prints "ExClassB"
Throwing an object always results in the thrown object being a copy of the object you threw, based on the static type of that object. Thus your first two answers are correct.
The third one is a little more complicated. If you catch(range_error*) you won't catch the exception because the types don't match. If you catch(exception*) you won't be able to access members of range_error in the caught pointer; you can dynamic_cast that pointer back to a range_error pointer though.
I think you are right in all three. The type of the thrown object (IIRC) is the static type of the object being thrown. I would have to dig into the standard for a while to find the exact quotes, but a simple example seems to confirm this:
struct base {};
struct derived : base {};
void t() {
derived d;
base * b = &d;
throw *b;
}
int main() {
try {
t();
} catch ( derived const & ) {
std::cout << "derived" << std::endl;
} catch ( base const & ) {
std::cout << "base" << std::endl;
}
}
If the dynamic type of the object being thrown was used, then *b would have type derived and the first catch would succeed, but empirically the second catch is executed (g++).
In the last case, the object thrown is a pointer to exception that refers to a range_error object. The slight difference is again what can be caught, the compiler will not catch in a catch (range_error*) block. The answer is correct, but I would have specified the type of the pointer, as much as the type of the pointee. (The type of the pointer is somehow implicit in the answer)
All three answers are correct. Just note that you'll have to catch a
pointer type in the third case.
The usual way to throw an exception is:
throw range_error("error");
At the throw site, you normally know the exact type of exception you
want to throw. About the only exception I can think of is when the
exception was passed in as an argument, e.g.:
void f( std::exception const& whatToDoInCaseOfError )
{
// ...
throw whatToDoInCaseOfError; // slices
}
It's not a frequence case, but if you want to support it, you'll need a
separate exception hierarchy of your own, with a virtual raise
function:
class MyExceptions
{
public:
virtual ~MyExceptions() {}
virtual void raise() const = 0;
};
template<typename ExceptionType>
class ConcreteException : public ExceptionType, public MyExceptions
{
public:
virtual void raise() const
{
throw *this;
}
};
The client code then wraps the exception he wants to be thrown in a
ConcreteException, and you call the raise function on it, rather
than invoke throw directly.