【问题标题】:std::exception subclass, string member variablestd::exception 子类,字符串成员变量
【发布时间】:2021-10-31 23:48:19
【问题描述】:

以下代码可以正常工作:

#include <exception>

using namespace std;

class FileException : public exception { // error occurs here
    int _error;
    // string _error; <-- this would cause the error
public:
    FileException(int error);
    // FileException(string error);
    const char* what() const throw();
};

但是一旦我将_error的类型更改为字符串,就会出现以下编译错误:

覆盖函数的异常规范比基础版本更宽松

【问题讨论】:

  • 从 std::runtime_error 派生。您可以将一个字符串传递给它的构造函数,它将存储它以使用 what() 进行重试。因此,您不需要管理字符串。

标签: c++ string exception


【解决方案1】:

std::string 的析构函数是 not no-throw,这导致 FileException 的隐式析构函数 not no-throw。但是std::exception的析构函数是no-throw,所以会出现编译错误。

你可以声明一个显式的无抛出析构函数:

virtual ~FileException() throw() {}

或者只是从std::runtime_error 继承而不是std::exception,后者有一个接受std::string 输入的构造函数。

【讨论】:

  • 使用第二种方法,错误仍然存​​在......但是,如果我添加析构函数,错误就消失了。谢谢
  • @alex:你继承了 runtime_error 删除了字符串成员吗?你不应该需要它。 Runtime_error 已经为你做了一切。
【解决方案2】:

简化为:

// Derive from std::runtime_error rather than std::exception
// std::runtime_error (unlike std::exception) accepts a string as an argument that will
// be used as the error message.
//
// Note: Some versions of MSVC have a non standard std::exception that accepts a string
//       Do not rely on this.
class FileException : public std::runtime_error
{
public:
    // Pass error msg by const reference.
    FileException(std::string const& error)
        // Pass the error to the standard exception
        : std::runtime_error(error)
    {}
    // what() is defined in std::runtime_error to do what is correct
};

【讨论】:

  • 如果 'std::runtime_error' 不正确,则可以选择将 'error.c_str()' 传递给 std::exception。
  • @MooingDuck:std::exception 只有一个默认构造函数和复制构造函数。没有采用 C-String 的构造函数。 std::runtime_error 将 std::string 或 C-String 作为其构造函数中的参数。
【解决方案3】:

我赞成上述方法,

g++ 似乎抱怨如果 默认构造函数不存在。

以下添加使事情起作用:

using namespace std;

class MyException : public runtime_error {
public:
  /* add the following line: */
  MyException() : runtime_error("MyException") { } // default constructor

  MyException( string const& error ) : runtime_error(error) { }  // ctor w/string
};

此外,一个例外列表很容易创建:

MyException FileNotFound ( "File Not Found" );
MyException ReadOnly     ( "ReadOnly"       );
MyException Unkown       ( "Unknown"        );

...
throw FileNotFound;
...

在捕获这些异常时,如果您不需要特殊性,请笼统地捕获它们:

catch( runtime_error re) {  cout << "Runtime Error: " << re.what() << endl;  ... }

由于所有 MyExceptions 都从 runtime_error 下降,因此会全部捕获它们并 您也不会错过系统中的任何其他运行时错误。

catch( exception e) {  cout << "exception: " << e.what() << endl;  ... }

全部抓住。

在 C++ 中,您还可以抛出和捕获任何类型(int、布尔值、指针等)。它有时更简单 只是在功能块中抛出/捕获一个字符串或一个 int。

多个类应该只抛出和捕获代码库标准异常及其子类,(并且都以相同的方式),但是,主要是为了一致性和维护,而且因为 c++ 编译器知道如何优化异常机制和链接它们,并且可以生成有关它们的智能警告和错误,从而简化调试。

“错误:“0x137F”是给 IBM 人的,而不是“今年项目的第三个人”...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-01
    • 2017-11-21
    相关资源
    最近更新 更多