我之前问过一个question https://stackoverflow.com/questions/3543725/should-exceptions-be-chained-in-c关于如何在 C++ 中链接异常,其中一个答案为如何完成它提供了一个很好的解决方案。问题是我看不懂代码,试图在评论中进行这种讨论实在是太麻烦了。所以我认为最好完全开始一个新问题。
代码包含在下面,我已经清楚地标记了我不明白的每个部分。代码下面包含了我不明白的内容的描述。代码是由土豆拍 https://stackoverflow.com/users/153285/potatoswatter.
Code
struct exception_data { // abstract base class; may contain anything
virtual ~exception_data() {}
};
struct chained_exception : std::exception {
chained_exception( std::string const &s;, exception_data *d = NULL )
: data(d), descr(s) {
try {
link = new chained_exception;
// ----------------------------------------------------------------
// How does this work (section 1)?
throw;
// ----------------------------------------------------------------
} catch ( chained_exception &prev; ) {
// ----------------------------------------------------------------
// How does this work (section 2)?
swap( *link, prev );
// ----------------------------------------------------------------
} // catch std::bad_alloc somehow...
}
friend void swap( chained_exception &lhs;, chained_exception &rhs; ) {
std::swap( lhs.link, rhs.link );
std::swap( lhs.data, rhs.data );
swap( lhs.descr, rhs.descr );
}
virtual char const *what() const throw() { return descr.c_str(); }
virtual ~chained_exception() throw() {
// --------------------------------------------------------------------
// How does this work (section 3)?
if ( link && link->link ) delete link; // do not delete terminator
// --------------------------------------------------------------------
delete data;
}
chained_exception *link; // always on heap
exception_data *data; // always on heap
std::string descr; // keeps data on heap
private:
chained_exception() : link(), data() {}
friend int main();
};
void f() {
try {
throw chained_exception( "humbug!" );
} catch ( std::exception & ) {
try {
throw chained_exception( "bah" );
} catch ( chained_exception &e; ) {
chained_exception *ep = &e;
for ( chained_exception *ep = &e; ep->link; ep = ep->link ) {
// Print ep->what() to std::cerr
}
}
}
try {
throw chained_exception( "meh!" );
} catch ( chained_exception &e; ) {
for ( chained_exception *ep = &e; ep->link; ep = ep->link ) {
// Print ep->what() to std::cerr
}
}
}
int main() try {
// ------------------------------------------------------------------------
// How does this work (section 4)?
throw chained_exception(); // create dummy end-of-chain
// ------------------------------------------------------------------------
} catch( chained_exception & ) {
// body of main goes here
f();
}
运行代码给出以下输出:
bah
humbug!
meh!
我不明白什么
-
throw;
inside try
-block:我以前从未见过这个。我唯一想到的地方throw;
有效的是在一个catch
-阻止重新抛出捕获的东西。那么这有什么作用呢?一些调试显然表明抛出的异常是之前抛出的异常,但那是在完全不同的内部try
-堵塞。事实上,甚至在外面struct
宣言!
-
交换字段:为什么我们需要swap异常字段?仅仅复制指针还不够吗?这是为了防止字段指向的结构被过早地从堆中删除吗?
-
Check link
and link
's link:我可以理解检查link
is not NULL
(即使删除NULL
指针没有作用),但是为什么需要检查link
's link?
-
抛出虚拟异常:为什么需要这个假人?它被抛出,但随后掉落。为什么我们需要这个作为链条的末端?
聪明的代码——对potatoswatter 的这一代码表示敬意。我认为我必须找到解决最后一项的方法。
throw;
重新抛出活动异常。它仅在以下情况下有效:catch
块在堆栈上。我不记得我是在哪里看到这个花絮的,但它可能是在其他一些问题的背景下出现的。裸露的抛出让我们可以通过在chained_exception
构造函数。换句话说,prev
构造函数中是对我们当前正在处理的异常的引用。
你在这里是正确的。这可以防止重复删除。
哨兵异常,抛出的异常main
,永远不应该被删除。此异常的一个识别属性是link
成员是NULL
.
这是我不喜欢的部分,但想不出一个简单的方法。唯一可见的chained_exception
构造函数只能在以下情况下被调用catch
块处于活动状态。 IIRC,没有主动的裸投catch
阻止是一个禁忌。所以,解决方法是投入main
并将所有代码放入catch
block.
现在,如果您在多线程代码中尝试此方法,请确保您很好地理解 (4)。您必须在线程入口点中复制此内容。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)