C++的例外情况的问题上重新引发的原始异常
题
将以下的追加()在捕捉导致重新引发的异常看到的效果的追加()被叫什么?
try {
mayThrowMyErr();
} catch (myErr &err) {
err.append("Add to my message here");
throw; // Does the rethrow exception reflect the call to append()?
}
同样,如果我改写这种方式,将位切发生,如果实际的例外是由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?
}
解决方案
在这两种情况下,由于你抓住参考,你是有效改变态的原始异常的对象(其中可以认为是居住在 一个神奇的存储位置将保持有效的期间后退 -- 0x98e7058
在例如以下)。但是,
- 在第一种情况下,由于你重新引发与
throw;
(它不同throw err;
, ,保持原来的异常对象,你的修改,在上述"神奇的地理位置"在0x98e7058
) 将 反映在电话追加() - 在第二种情况下,由于你扔东西明确, 复制 的
err
将创造了然后扔个新的(在一个不同的"神奇的地理位置"0x98e70b0
-因为所有编译器知道err
可能是一个目的堆关于被unwinded样e
在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;
}
结果是:
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
也参见:
其他提示
这个问题是相当的旧的和有一个答案适当的时间要求。然而,我只是想增加一个注如何做到适当的例外处理,因为 C++11 我相信这一相对应的很好你是什么努力实现与您的附加功能:
使用 std::nested_exception
和 std::throw_with_nested
它描述了在计算器 在这里, 和 在这里,, ,你怎么可以 得到回溯上你的例外 在你的代码,而不需要一个调试器或繁琐的登录,可通过简单地写入一个适当的例外处理,这将再次引发嵌套的例外情况。
因为你可以这样做任何衍生出异常类,可以添加了很多的信息这样一种回溯!你也可以来看看我 兆瓦在。, ,其中一个回溯会看起来像这样的东西:
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"
是,重新抛出重新抛出原始的异常对象,这已通过参考修改。您还可以赶上基类参考,通过将其修改,并且仍然能够通过throw;
重新抛出原衍生的异常类型。
对于第一个问题,是的。
但对于第二,参照维拉德答案。 你需要仔细设计你的异常对象来处理拷贝构造函数。按照惯例,基类没有认识到它的孩子,所以你很可能会失去通过派生类中携带的附加数据。
不隶属于 StackOverflow