Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing Exception class in C++

So, I am try to write a simple base Exception class for C++, based on the Java Exception class. I'm sure there are great libraries out there already, but I am doing this for practice, not production code, and I'm curious and always looking to learn. One of the things the Java's Exception does, which I would like to also implement, is the concept of a 'cause'. In Java, a new Exception with a cause looks like:

Exception cause = new Exception();
Exception newExcept = new Exception(cause);

However, in C++, passing an Exception as an argument to the constructor is how the copy constructor is called. So, there's the conceptual disconnect between copying the Exception and creating a new Exception with a cause. This isn't a problem in Java, obviously.

I guess I'm just wondering what the best way to handle this would be. A few ideas I had were:

  • Differentiate with a dummy variable
  • Just create new Exception, and called setCause() method
  • Something like copy constructor is Exception(Exception &) and constructor with cause is Exception(Exception *)

Thanks

like image 943
Roadrunner-EX Avatar asked Feb 26 '23 06:02

Roadrunner-EX


2 Answers

The exception - when allocated on the stack (I would strongly recomend this) - is freed after the catch clause. So you need to create a copy of the "inner" exception in the newly created exception. If you catch a base class of your exception it will loose it's correct type unless you give your exception a clone method.

#include <string>
#include <exception>

class MyBaseException : public std::exception
{
public:
    MyBaseException(const std::string& what = std::string("MyBaseException"))
        : m_BaseException(0), m_What(what) {}  //Constructor without inner exception

    MyBaseException(const MyBaseException& innerException, const std::string& what = std::string("MyBaseException"))
        : m_BaseException(innerException.clone()), m_What(what) {}  //Constructor with inner exception

    template <class T>  // valid for all subclasses of std::exception
    MyBaseException(const T& innerException, const std::string& what = std::string("MyBaseException"))
        : m_BaseException(new T(innerException)), m_What(what) {}

    virtual ~MyBaseException() throw()
        { if(m_BaseException) { delete m_BaseException; } } //don't forget to free the copy of the inner exception
    const std::exception* base_exception() { return m_BaseException; }
    virtual const char* what() const throw()
        { return m_What.c_str(); } //add formated output for your inner exception here
private:
    const std::exception* m_BaseException;
    const std::string m_What;
    virtual const std::exception* clone() const
        { return new MyBaseException(); } // do what ever is necesary to copy yourselve
};

int main(int argc, char *argv[])
{
    try {
        try {
            throw std::exception();
        }
        catch(const std::exception& e) {
            throw MyBaseException(e, "bad");
        }
    }
    catch (const MyBaseException& e) {
        throw MyBaseException(e, "even worse");
    }
    //throw MyBaseException(1, "will not compile");
}
like image 122
David Feurle Avatar answered Mar 07 '23 07:03

David Feurle


You could use the factory model:

Exception cause = Exception.Create();
Exception newExcept = Exception.Create( Exception cause );
like image 31
yhw42 Avatar answered Mar 07 '23 09:03

yhw42