在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::异常

请注意,最后一行显示的是std::exception,而不是我实际的异常消息"This is my exception error"。

为什么,它在Windows上可以工作,但在Linux上可以。

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

您的what()返回:

return exception::what();

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

指向以null结尾的字符串的指针,其中包含解释信息。

就这样。没有别的,没有别的。你展示的文本当然可以作为"解释性信息"。这是对what()的返回值的唯一要求(除了另一个与此处无关的要求)。

换句话说,C++不能保证使用what()得到的内容的准确性。俗话说,你看到的what()就是你得到的what()

如果你想让你的异常以某种方式描述自己,那就由你来实现它,作为what()的一部分。

您需要自己实现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(),并且只有在阅读了它们之后才使用-链接。

在你的尝试中:

catch (const TestClass& myException)

而不是catch(TestClass myException)-否则,您将执行隐式复制,这可能会导致异常抛出。它还打破了多态性:如果想要catchpure virtual interface实现实例,则需要使用引用。

您需要一种方法来指定一个自定义错误消息到std::exception,而afaik是不允许的。有关可能的解决方案,请参见此。

关于答案的大部分信息都是由Sam Varshavchik提供的但我想补充一点投掷和接球时一个好的规则是

";按值抛出通过引用捕获">

所以你的投掷很好:

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

使用了对TestClass的隐式转换,然后通过值传递。

该规则的关键点是最大限度地减少不同堆栈帧之间的内存分配处理

另一方面,你的捕获不符合规则(因为你是按价值捕获的):

catch (TestClass ex)
{
cout << "Exception Caught: " << ex.what() << endl;
}

catch应该是(const TestClass&ex)

这个规则的关键点是基类和派生类之间的隐式转换。

相关内容

最新更新