在 C++ 中实现 Exception 类

发布于 2024-09-18 04:13:38 字数 591 浏览 3 评论 0原文

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

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

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

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

  • 用虚拟变量区分
  • 只需创建新的 Exception,并调用 setCause() 方法
  • 像复制构造函数这样的东西是 Exception(Exception &) ,而带有 Cause 的构造函数是 Exception (例外 *)

谢谢

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

三五鸿雁 2024-09-25 04:13:38

异常 - 当在堆栈上分配时(我强烈推荐这样做) - 在 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");
}

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");
}
老街孤人 2024-09-25 04:13:38

您可以使用工厂模型:

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

You could use the factory model:

Exception cause = Exception.Create();
Exception newExcept = Exception.Create( Exception cause );
江城子 2024-09-25 04:13:38

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

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());
}

Just add the string of the cause exception to the current exception:

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());
}
魄砕の薆 2024-09-25 04:13:38

你的问题不清楚,甚至似乎不是正确的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);
}

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

You're question is unclear, and doesn't even seem to be Java properly but a Java idiom which is supported by a library. I am guessing the idiom you describe is passing the original exception as an argument to an exception you create when rethrowing.

The solution is to create a library_exception ( or whatever you want to call it )

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

Different classes no copy constructor called.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文