在C ++中实现Exception类

时间:2010-09-10 04:41:54

标签: java c++ exception copy-constructor

因此,我尝试基于Java Exception类为C ++编写一个简单的基本Exception类。 我确信那里已经有很棒的图书馆了,但我这样做是为了练习,而不是生产代码,我很好奇并且总是想学习。 Java的Exception所做的事情之一,我想要实现,是'原因'的概念。在Java中,带有原因的新异常如下所示:

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

但是,在C ++中,将Exception作为参数传递给构造函数是如何调用复制构造函数的。因此,在复制Exception和创建具有原因的新Exception之间存在概念上的脱节。显然,这在Java中不是问题。

我想我只是想知道处理这个问题的最佳方法是什么。我的一些想法是:

  • 区分虚拟变量
  • 只需创建新的Exception,并调用setCause()方法
  • 复制构造函数为Exception(Exception &),构造函数为Exception(Exception *)

由于

4 个答案:

答案 0 :(得分:5)

异常 - 在堆栈上分配时(我强烈推荐这个) - 在catch子句之后被释放。因此,您需要在新创建的异常中创建“内部”异常的副本。如果你捕获异常的基类,除非你给你的异常一个克隆方法,否则它会松开它的正确类型。

#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");
}

答案 1 :(得分:2)

您可以使用工厂模型:

Exception cause = Exception.Create();
Exception newExcept = Exception.Create( Exception cause );

答案 2 :(得分:1)

只需将原因异常的字符串添加到当前异常中:

try
{
    throw std::runtime_error("Failed to work");
}
catch(std::exception const& e)
{
    // New exception (add origianl exception text).
    throw std::runtime_error(std::string("We were doing poobar when: ") + e.what());
}

答案 3 :(得分:0)

你的问题不清楚,甚至看起来都不是Java,而是图书馆支持的Java习语。我猜你所描述的成语是将原始异常作为参数传递给你在重新抛出时创建的异常。

解决方案是创建一个library_exception(或任何你想要调用的东西)

class library_exception: public std::exception
{
 ...
 public:
   library_exception(const  std::exception &e)
 ...
}
...
catch(const std::exception &e)
{
  ...
  throw library_exception(e);
}

不同的类没有复制构造函数。