【发布时间】:2014-08-08 16:59:03
【问题描述】:
我不确定应该如何使用异常。我经常想知道“我必须在这里捕获这个,还是在调用堆栈中更高?”诸如此类的事情。但是我创建了一个小的异常类来拥有某种类似 C# 的异常,可以显示一堆异常:
class Exception : public std::exception
{
protected:
std::string _trace;
public:
Exception()
: _trace( "[ERROR - " + (std::string) DateTime() + "]"
{ }
Exception & push( const std::string & msg )
{
this->_trace += '\n\t' + msg;
return *this;
}
virtual const char * what() const
{
return this->_trace.c_str();
}
};
我可以这样使用:
function depth0()
{
try
{
depth1();
}
catch( Exception & exc )
{
throw exc.push( "depth0() - Failed." );
}
}
function depth1()
{
try
{
depth2();
}
catch( Exception & exc )
{
throw exc.push( "depth1() - Failed." );
}
}
function depth2()
{
try
{
depth3();
}
catch( Exception & exc )
{
throw exc.push( "depth2() - Failed." );
}
}
function depth3()
{
if( something goes wrong )
{
throw Exception().push( "depth3() - Failed." );
}
}
try
{
depth0();
}
catch( Exception & exc )
{
std::cout << exc.what() << std::endl;
}
我不必在调用堆栈的每个深度都捕获和抛出,这只是一个示例。
这是使用异常的正确方法吗?这不是违反例外哲学吗? (我还不明白)。
谢谢你:)
PS : 我使用 Java 和 C# 标记,因为这通常是关于异常的,即使示例是在 C++ 中的。
【问题讨论】:
-
你应该很少在 C++ 中尝试捕捉,而是围绕 RAII 习惯构建你的代码:en.m.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization
-
谢谢。我读了你的文章,但我不明白与此的关系。
-
不回答您的问题,但作为 C++ 的提示:您可以使用
throw;(无参数)重新抛出异常。这意味着您不会像在您的示例中那样抛出副本:exc.push(...); throw; -
阅读“好处”部分并尝试编写异常安全的 C++ 代码,该代码在使用 RAII 和不使用 RAII 的范围内分配内存
-
@Matthias247 它会抛出副本吗?它不会抛出参考吗? :o
标签: java c# c++ exception callstack