C++中在构造函数中抛出自定义异常 throw ()

3

我看到有人说自定义异常类中不应该包含除了基本类型以外的内容,因为这样可能会在异常中抛出另一个异常(就像梦中的梦一样)。并且你应该按值抛出异常,按引用捕获异常。

以下是我的异常类头文件:

class DeepthroatException : public std::runtime_error {
  public:
  DeepthroatException(const char* err); // set err member to err

  private:
  // Error description
  const char* err;
};

但是我不喜欢它,因为它引入了一个与内存管理有关的问题,这对肉眼是不可见的,我需要使用地雷探测器。如果可能的话,我想改用std::string

但是第一段中存在的问题,让我考虑了以下解决方案:

#include <string>
class DeepthroatException : public std::runtime_error {
  public:
  DeepthroatException(std::string err) throw(); // set err member to err, no throw

  private:
  // Error description
  std::string err;
};

这样做可以吗?


你可以将字符串参数传递给 runtime_error,并让它处理问题。 - Bo Persson
@BoPersson 是的,但我在构造函数中做了一些额外的事情,比如设置错误代码。上面的代码是简化的。我想知道是否有一种方法可以保证即使使用非基本数据类型(例如字符串),也不会抛出任何额外的异常,或者这不可能? - A Beautiful Indian Man
您可以设置错误代码,然后调用 runtime_error 构造函数。 - Joseph Thomson
1
如果你构建一个字符串,如果系统完全没有内存,就会出现bad_alloc异常。说throw()并不能帮助代码不抛出异常,只会让情况变得更糟。你可能会问自己是否想尝试处理这种情况,或者是否可以接受bad_alloc(很快就会发生)。 - Bo Persson
对于你的第一个版本异常构造函数 "DeepthroatException(const char* err)",我认为它非常好。你可以向它传递一个字符串,而无需进行内存管理,例如 DeepthroatException("My error message")。"My error message" 存储在只读内存空间中,因此 DeepthroatException 不需要管理它的内存空间,仅需将地址保存在 "const char* err" 中即可。 - Jun Ge
1个回答

1

使用std::string也可能会遇到std::bad_alloc的问题。但这个问题已经固有于std::runtime_error,因为它的构造函数可以接受一个std::string作为参数:

explicit runtime_error( const std::string& what_arg );
explicit runtime_error( const char* what_arg );

这样做是因为复制异常不应该抛出,所以实现可能会分配另一个字符串并将参数内容复制到其中。如果您真的不希望抛出第二个异常,请将构造函数标记为noexcept并确保它永远不会失败,如果它失败了,您的程序将立即关闭。

您可以通过在构造函数中使用字符串来继承std::runtime_error的行为,如下所示:

DeepthroatException(const std::string& err) noexcept :
    std::runtime_error(err)
{
    // ...
}

此时,您可以删除err数据成员,因为runtime_error将为您提供内部字符串,您可以通过what()引用它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接