在 C 中创建自定义异常

新手上路,请多包涵

我正在学习 C++,当我尝试创建自己的异常并将它们扔到 Linux 上时,我正在体验。

我创建了一个小型测试项目来测试我的实现,下面是我的异常类头文件。

 class TestClass : public std::runtime_error
{
public:
    TestClass(char const* const message) throw();
    virtual char const* what() const throw();
};

异常类的源文件是

using namespace std;

TestClass::TestClass(char const* const message) throw()
    : std::runtime_error(message)
{

}

char const * TestClass::what() const throw()
{
    return exception::what();
}

在我的主应用程序中,我正在调用一个函数,该函数抛出我的异常并在 try/catch 中捕获它,如下所示:

 void runAFunctionAndthrow();

/*
 *
 */
int main(int argc, char** argv) {
    try
    {
        cout << "About to call function" << endl;
        runAFunctionAndthrow();
    }
    catch (TestClass ex)
    {
        cout << "Exception Caught: " << ex.what() << endl;
    }

    return 0;
}

void runAFunctionAndthrow()
{
    cout << "going to run now. oh dear I need to throw an exception" << endl;

    stringstream logstream;
    logstream << "This is my exception error. :(";
    throw TestClass(logstream.str().c_str());
}

当我运行时,我期望得到以下输出:

即将调用函数

现在要跑了。哦,亲爱的,我需要抛出一个异常

异常捕获:这是我的异常错误。 :(

相反,我得到的是

即将调用函数

现在要跑了。哦,亲爱的,我需要抛出一个异常

异常捕获:std::exception

请注意最后一行显示 std::exception 而不是我的实际异常消息“这是我的异常错误”。

为什么会这样,它在 Windows 上可以正常工作,但在 Linux 上却可以。

从我在各种帖子中看到的内容来看,我所做的是正确的,所以我错过了什么。

原文由 Boardy 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 405
2 个回答

您的 what() 返回:

  return exception::what();

std::exception::what() 的返回值 指定如下

指向带有解释性信息的以空字符结尾的字符串的指针。

而已。仅此而已,仅此而已。您显示的文本当然可以称为“解释性信息”。这是对 what() 的返回值的唯一要求(除了这里不相关的另一个)。

换句话说,C++ 不保证您使用 what() 获得的确切内容。 what() 你看到的是 what() 你懂的,俗话说。

如果您希望您的异常以某种方式描述自己,则由您来实现它,作为 what() 的一部分。

原文由 Sam Varshavchik 发布,翻译遵循 CC BY-SA 3.0 许可协议

您需要自己实现 what() 方法或使用 std::runtime_error::what() 如评论中所述

说:

 class TestClass : public std::runtime_error
{
    std::string what_message;
public:
    const char* what() override
    {
        return what_message.c_str();
    }
};

此外,最好使用 noexcept 而不是 throw() 并且只有在您阅读了它们之后 - 链接

在你的 try-catch 中:

 catch (const TestClass& myException)

而不是 catch(TestClass myException) - 否则你会做一个可能导致异常抛出的隐式复制。它还破坏了多态性:如果您想 catch pure virtual interface 实现实例,则需要使用引用。

原文由 andrgolubev 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题