Wil*_*mKF 109 c++ exception rethrow
catch中的以下append()是否会导致重新抛出的异常以查看append()被调用的效果?
try {
mayThrowMyErr();
} catch (myErr &err) {
err.append("Add to my message here");
throw; // Does the rethrow exception reflect the call to append()?
}
Run Code Online (Sandbox Code Playgroud)
类似地,如果我以这种方式重写它,如果myErr导出实际异常,是否会发生位切片?
try {
mayThrowObjectDerivedFromMyErr();
} catch (myErr &err) {
err.append("Add to my message's base class here");
throw err; // Do I lose the derived class exception and only get myErr?
}
Run Code Online (Sandbox Code Playgroud)
vla*_*adr 145
在这两种情况下,由于您通过引用捕获,因此您实际上正在改变原始异常对象的状态(您可以将其视为驻留在一个神奇的内存位置,该位置将在后续展开期间保持有效 - 0x98e7058在下面的示例中).然而,
throw;(与throw err;保存原始异常对象不同,修改后,在所说的"魔法位置" 0x98e7058)将反映对append()的调用err将被创建,然后重新抛出(在不同的"神奇的位置" 0x98e70b0-因为所有的编译器知道err可能是堆栈有关的物体被unwinded,就像e是at 0xbfbce430,而不是在"魔术位置" 0x98e7058),因此在基类实例的复制构造期间,您将丢失特定于派生类的数据.简单的程序来说明发生了什么:
#include <stdio.h>
struct MyErr {
MyErr() {
printf(" Base default constructor, this=%p\n", this);
}
MyErr(const MyErr& other) {
printf(" Base copy-constructor, this=%p from that=%p\n", this, &other);
}
virtual ~MyErr() {
printf(" Base destructor, this=%p\n", this);
}
};
struct MyErrDerived : public MyErr {
MyErrDerived() {
printf(" Derived default constructor, this=%p\n", this);
}
MyErrDerived(const MyErrDerived& other) {
printf(" Derived copy-constructor, this=%p from that=%p\n", this, &other);
}
virtual ~MyErrDerived() {
printf(" Derived destructor, this=%p\n", this);
}
};
int main() {
try {
try {
MyErrDerived e;
throw e;
} catch (MyErr& err) {
printf("A Inner catch, &err=%p\n", &err);
throw;
}
} catch (MyErr& err) {
printf("A Outer catch, &err=%p\n", &err);
}
printf("---\n");
try {
try {
MyErrDerived e;
throw e;
} catch (MyErr& err) {
printf("B Inner catch, &err=%p\n", &err);
throw err;
}
} catch (MyErr& err) {
printf("B Outer catch, &err=%p\n", &err);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
结果:
Base default constructor, this=0xbfbce430
Derived default constructor, this=0xbfbce430
Base default constructor, this=0x98e7058
Derived copy-constructor, this=0x98e7058 from that=0xbfbce430
Derived destructor, this=0xbfbce430
Base destructor, this=0xbfbce430
A Inner catch, &err=0x98e7058
A Outer catch, &err=0x98e7058
Derived destructor, this=0x98e7058
Base destructor, this=0x98e7058
---
Base default constructor, this=0xbfbce430
Derived default constructor, this=0xbfbce430
Base default constructor, this=0x98e7058
Derived copy-constructor, this=0x98e7058 from that=0xbfbce430
Derived destructor, this=0xbfbce430
Base destructor, this=0xbfbce430
B Inner catch, &err=0x98e7058
Base copy-constructor, this=0x98e70b0 from that=0x98e7058
Derived destructor, this=0x98e7058
Base destructor, this=0x98e7058
B Outer catch, &err=0x98e70b0
Base destructor, this=0x98e70b0
Run Code Online (Sandbox Code Playgroud)
另见:
GPM*_*ler 20
这个问题相当陈旧,并且答案适合于被问及的时间.但是,我只想添加一个关于如何在C++ 11之后进行适当异常处理的注释,我相信这与您尝试使用append函数实现的内容非常吻合:
std::nested_exception和std::throw_with_nested它在StackOverflow 这里和这里描述了如何通过简单地编写一个适当的异常处理程序来重新抛出嵌套异常,如何在代码内部获得异常回溯,而无需调试器或繁琐的日志记录.
由于您可以对任何派生的异常类执行此操作,因此可以向此类回溯添加大量信息!您也可以在GitHub上查看我的MWE,其中回溯看起来像这样:
Library API: Exception caught in function 'api_function'
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
54916 次 |
| 最近记录: |