【发布时间】:2017-04-06 21:38:22
【问题描述】:
我目前正在使用异常类型,并且在尝试重新抛出捕获的异常时发现了一些奇怪的东西。
从 C++ 规范中,我知道 throw 实际上会生成您尝试抛出的对象的副本,因此您最终将分割您捕获的任何残留派生类型信息。
为了避免这种情况,我已经看到建议重新throw 指向原始异常的指针,因为实际的原始对象将不会删除其派生部分。
但是,我在下面编写的简单示例程序似乎不能那样工作:
#include <exception>
#include <iostream>
#include <typeinfo>
class derived_exception : public std::exception { };
void rethrowException(bool anonymise) {
try {
throw derived_exception();
} catch(const std::exception& e) {
std::cout << "Caught: " << typeid(e).name() << " (std::exception)" << std::endl;
if(anonymise) {
throw;
} else {
throw &e;
}
}
}
int main() {
std::cout << "Re-throwing caught exception..." << std::endl;
try {
rethrowException(false);
} catch(const derived_exception* e) {
std::cout << "Re-caught: " << typeid(e).name() << " (derived_exception)" << std::endl;
} catch(const std::exception* e) {
std::cout << "Re-caught: " << typeid(e).name() << " (std::exception)" << std::endl;
}
std::cout << std::endl << "Re-throwing anonymous exception..." << std::endl;
try {
rethrowException(true);
} catch(const derived_exception& e) {
std::cout << "Re-caught: " << typeid(e).name() << " (derived_exception)" << std::endl;
} catch(const std::exception& e) {
std::cout << "Re-caught: " << typeid(e).name() << " (std::exception)" << std::endl;
}
}
输出./example:
Re-throwing caught exception...
Caught: 17derived_exception (std::exception)
Re-caught: PKSt9exception (std::exception)
Re-throwing anonymous exception...
Caught: 17derived_exception (std::exception)
Re-caught: 17derived_exception (derived_exception)
您可以成功地重新转换指针并检索派生类型信息,但指针类型最初仍是切片的。
有没有办法解决这个问题而不抓住基地并尝试dynamic_cast 回来?
谢谢
【问题讨论】:
-
derived_exception派生自exception,但derived_exception*不是派生自exception*。 -
作为推论,不要通过指针捕获异常 - 通过 const 引用捕获它们。
-
anonymise是一个错误的名称,因为当true时,你得到了正确的类型,如果为 false,你得到了基本类型...... -
投掷/接球系统不会为您提供
dynamic_cast指针。 -
“根据 C++ 规范,我知道 throw 实际上会生成您尝试抛出的对象的副本,因此您最终会分割您捕获的任何残留派生类型信息。” - 我不认为这是真的。
标签: c++ exception inheritance