Extending std::exception

So you're writing some C++ code, feeling all object oriented and all, and you decide you'd like an application specific exception whenever one of your methods has an issue. You'd like to have error messages that the exception can print up if thrown and you think to yourself, "hey, I'll just extend std::exception, add the error string, and be on my way."

Problem: So here is the puzzle. What is wrong with this code:

  1.  
  2. #include <exception>
  3. #include <string>
  4. using namespace std;
  5. class my_error : public exception {
  6. private:
  7. string m_err;
  8. public:
  9. my_error ( const string &err) : m_err(err) {}
  10. const char* what() { return m_err.c_str(); }
  11. };
  12.  

Think about it for a bit before scrolling down more. Take a look at the header definition for exception.

Ok, ready to move on? Did you find the problem?

Answer:

The standard exception does not declare it's copy constructor virtual.

  1.  
  2. exception& operator= (const exception&) throw();
  3.  

This is in part because in order to provide exception safe c++, the exception class can't throw exceptions itself. This is the same reason using strings member variables is discouraged for exceptions. Their constructors can also throw exceptions. Anyway, the result is that if client code catches std::exception, copies the exception, and prints it, m_str hasn't been copied and you get garbage or errors. Not what was expected was it.

Solution

This whole problem was loaded just slightly. There is already a standard exception that can take a string message as an argument.

  1.  
  2. #include <stdexcept>
  3. class my_exc : public runtime_error {
  4. public:
  5. my_exc ( const string &err ) : runtime_error (err ) {}
  6. // there, you can add more methods here.
  7. // remember, you can't add data members any more here
  8. // than you can add them to exception derived classes though.
  9. };
  10.  

Get it? Got it? Good.

2 Responses to “Extending std::exception”


  1. jansson

    I would like to comment that there is quite a lot to read about the purpose and usage of the exception inhertiance hiearchy in the C++ Standard.

    Thank you for a nice posting.

  2. rk

    Hi,

    1. Constructors are never virtual, I think you mean the assignment operator.

    2. Since you are catching a base class exception reference or a pointer u really do not need to overload the assignment operator. I think you are trying
    catch(std::exception e) which is not the right way to do it.

    3. The runtime_error uses std::string as a member variable.

    Ramesh



css.php