Correct way to inherit from std::exception
C++ExceptionC++ Problem Overview
I've just created exception hierarchy and wanted to pass char*
to constructor of one of my derived classes with a message telling what's wrong, but apparently std::exception
doesn't have constructor which would allow me to do so. Yet there is a class member called what()
which would suggest that some information can be passed.
How can I (can I?) pass text to derived class of a std::exception
in order to pass info with my exception class, so I can say somewhere in the code:
throw My_Exception("Something bad happened.");
C++ Solutions
Solution 1 - C++
I use the following class for my exceptions and it works fine:
class Exception: public std::exception
{
public:
/** Constructor (C strings).
* @param message C-style string error message.
* The string contents are copied upon construction.
* Hence, responsibility for deleting the char* lies
* with the caller.
*/
explicit Exception(const char* message)
: msg_(message) {}
/** Constructor (C++ STL strings).
* @param message The error message.
*/
explicit Exception(const std::string& message)
: msg_(message) {}
/** Destructor.
* Virtual to allow for subclassing.
*/
virtual ~Exception() noexcept {}
/** Returns a pointer to the (constant) error description.
* @return A pointer to a const char*. The underlying memory
* is in posession of the Exception object. Callers must
* not attempt to free the memory.
*/
virtual const char* what() const noexcept {
return msg_.c_str();
}
protected:
/** Error message.
*/
std::string msg_;
};
Solution 2 - C++
If you want to make use of the string constructor, you should inherit from std::runtime_error or std::logic_error which implements a string constructor and implements the std::exception::what method.
Then it's just a case of calling the runtime_error/logic_error constructor from your new inherited class, or if you're using c++11 you can use constructor inheritance.
Solution 3 - C++
How about this:
class My_Exception : public std::exception
{
public:
virtual char const * what() const { return "Something bad happend."; }
};
Or, create a constructor accepting the description if you like...
Solution 4 - C++
If your goal is to create an exception so that you do not throw a generic exception (cpp:S112) you may just want to expose the exception you inherit from (C++11) with a using declaration.
Here is a minimal example for that:
#include <exception>
#include <iostream>
struct myException : std::exception
{
using std::exception::exception;
};
int main(int, char*[])
{
try
{
throw myException{ "Something Happened" };
}
catch (myException &e)
{
std::cout << e.what() << std::endl;
}
return{ 0 };
}
As Kilian points out in the comment section the example depends on a specific implementation of std::exception that offers more constructors than are mentioned here.
In order to avoid that you can use any of the convenience classes predefined in the header <stdexcept>
. See these "Exception categories" for inspiration.
Solution 5 - C++
The what
method is virtual, and the meaning is that you should override it to return whatever message you want to return.
Solution 6 - C++
Here is an example
class CommunicationError: public std::exception {
public:
explicit CommunicationError(const char* message) : msg(message) {}
CommunicationError(CommunicationError const&) noexcept = default;
CommunicationError& operator=(CommunicationError const&) noexcept = default;
~CommunicationError() override = default;
const char* what() const noexcept override { return msg; }
private:
const char* msg;
};