Reputation: 36237
I am learning C++ and I am experiencing when I try and create my own exception and throw them on Linux.
I've created a small test project to test my implementation and below is my exception class header file.
class TestClass : public std::runtime_error
{
public:
TestClass(char const* const message) throw();
virtual char const* what() const throw();
};
The source file for the exception class is
using namespace std;
TestClass::TestClass(char const* const message) throw()
: std::runtime_error(message)
{
}
char const * TestClass::what() const throw()
{
return exception::what();
}
In my main app, I am calling a function which throws my exception and catches it in a try/catch as follows:
void runAFunctionAndthrow();
/*
*
*/
int main(int argc, char** argv) {
try
{
cout << "About to call function" << endl;
runAFunctionAndthrow();
}
catch (TestClass ex)
{
cout << "Exception Caught: " << ex.what() << endl;
}
return 0;
}
void runAFunctionAndthrow()
{
cout << "going to run now. oh dear I need to throw an exception" << endl;
stringstream logstream;
logstream << "This is my exception error. :(";
throw TestClass(logstream.str().c_str());
}
When I run I'm expecting to get the following output:
About to call function
Going to run now. oh dear I need to throw an exception
Exception Caught: This is my exception error. :(
Instead what I am getting is
About to call function
going to run now. oh dear I need to throw an exception
Exception Caught: std::exception
Notice the last line it says std::exception instead of my actual exception message "This is my exception error".
Why is this, it works OK on Windows but on Linux it does this.
From what I've seen on various posts what I've done is correct so what am I missing.
Upvotes: 56
Views: 104285
Reputation: 1242
The most succinct way to create a custom exception since C++11 is using
the parent constructor of std::runtime_error
:
struct my_exception: std::runtime_error {
using std::runtime_error::runtime_error;
}
This will inherit all std::runtime_error
constructors which covers the majority of exception-handling needs.
Upvotes: 1
Reputation: 885
You need your own implementation of what() method or use std::runtime_error::what()
as written in comments
Say:
class TestClass : public std::runtime_error
{
std::string what_message;
public:
const char* what() const override
{
return what_message.c_str();
}
};
Also, better use noexcept
instead of throw()
and only after you read about them - link.
And in your try-catch:
catch (const TestClass& myException)
Instead of catch(TestClass myException)
- otherwise you do an implicit copy which can potentially result in an exception throw. It also breaks the polymorphism: if you want to catch
pure virtual interface
implementation instance, you would need to use a reference.
Upvotes: 31
Reputation: 11
First of most of the info about the answer had been given by Sam Varshavchik But I want to add one thing When throwing and catching A good rule is
"Throw by value catch by reference "
So your throw was fine as:
void runAFunctionAndthrow()
{
cout << "going to run now. oh dear I need to throw an exception" << endl;
stringstream logstream;
logstream << "This is my exception error. :(";
throw **TestClass(logstream.str().c_str())**;
}
used an implicit conversion to TestClass and then it got passed by value.
the Key point in that rule is to minimize memory allocating handling between different stack frames
your catch on the other hand dosen't follow the rule (since you catch by value):
catch (TestClass ex)
{
cout << "Exception Caught: " << ex.what() << endl;
}
the catch should be (const TestClass& ex)
the key point in this rule is implicit conversion between base class and derived class.
Upvotes: 1
Reputation: 121
You need a way to specify a custom error message to std::exception which afaik is not allowed. See this for a possible solution.
Upvotes: 2
Reputation: 118435
Your what()
returns:
return exception::what();
The return value from std::exception::what()
is specified as follows:
Pointer to a null-terminated string with explanatory information.
That's it. Nothing more, nothing else. The text you're showing certainly qualifies as an "explanatory information". And this is the only requirement for the return value of what()
(except for one other one which is not germane here).
In other words, C++ does not guarantee the exact contents of what you get with what()
. what()
you see is what()
you get, as the saying goes.
If you want your exception to describe itself, in some way, it's up to you to implement that, as part of your what()
.
Upvotes: 41