当类定义不可见时捕获异常
Catch exception when class definition is not visible
我正在处理一个问题,即损坏的输入文件导致引发异常。异常类是在实现文件中定义的,因此对我不可见。它确实继承自std::exception
。
我尝试简单地向前声明异常类,因为我只是通过引用来获取它。然而,这给了我一个error: invalid use of incomplete type
编译器错误(在Linux上使用GCC 6.2(。我想编译器需要完整的异常对象类型,以便在需要时可以重新抛出异常。
这就是我想做的:
// library.cpp
namespace FOO {
struct SomeException : public std::exception
{
// string member, virtual dtor, ctor taking one arg and virtual what()
};
void doStuff() {
}
}
// my main.cpp
namespace FOO
{
struct SomeException;
}
int main()
{
try
{
FOO::doStuff();
}
catch (FOO::SomeException& e)
{
// ignore e, but I know where it came from so log
// an appropriate message
}
catch (std::exception& e)
{
// most other exceptions, log `what()` message
}
catch(...)
{
// tell user to contact customer support
}
}
仅仅打印what()
消息不适合我的上下文。
我可以要求其他团队将他们的异常类定义移动到一个头中。这可能是一个缓慢的过程。我想我也可以对what()
消息进行字符串比较,但这看起来很难看。
还有其他选择吗?
(顺便说一句,我看不到谷歌对此有任何提及,但这似乎是一种反模式,即"只扔例外"(。
如果您没有访问原始类的权限,您将无法正确捕获它:
C++标准/[除.handle]:
处理程序中的异常声明描述可能导致输入处理程序的异常。异常声明不应表示不完整类型、抽象类类型或右值引用类型。异常声明不应表示指向不完整类型的指针或引用,[cvvoid*]除外。
所以没有理想而干净的解决方案。但也许可以接受的解决方案是:从std::exception派生的类是多态的。因此,您可以考虑使用typeid()
(最终与type_index
结合使用(来识别catch (std::exception& e)
块中的真实类型。
IMHO,当.what()
不是备选方案时,区分未知异常应该是一种可以接受的方式。然而,不便之处在于标准中没有定义type_info
数据(例如typeid(e).name()
(的值,这使得任何硬编码值都是不可移植的。
概念证明:
//somewhere
class MyExcept : public std::exception { };
...
// somewhere else
try {
throw std::exception();
} catch (std::exception &e) {
std::cout <<"case 1: " << typeid(e).name() << std::endl;
}
try {
throw MyExcept();
} catch (std::exception &e) {
std::cout <<"case 2: "<< typeid(e).name() << std::endl;
}
在线演示
- 当类定义不可见时捕获异常
- 来自 Android 应用程序内部的 boost 类型的 boost::wrapexcept<boost::system::system_error> 的未捕获异常
- 如何通过 pybind11 从 python 中的C++中捕获异常?
- 信号后未捕获异常
- 捕获异常后如何退出程序执行
- C++ 捕获异常后进行清理的标准方法是什么?
- 使用模板类引发和捕获异常
- E/libc++abi:终止于类型为google::protobuf::FatalException的未捕获异常
- 如果在生成 std::thread 后引发,则未捕获异常
- C++ 未捕获异常,程序将终止并中止
- C++程序在第一次尝试时会给出垃圾,但如果它捕获异常并重试,则会给出适当的值
- 仅捕获异常就可以检测所有二进制文件在C 中读取错误是否足够
- 如何捕获 I/O 异常(确切地说是 I/O,而不是 std::exception)
- 为什么捕获异常播放允许尾括号
- throw() 函数应该总是在异常时展开堆栈并允许捕获异常还是必须调用 std::terminate ?
- 捕获自定义 UART 类信号
- C++ 异常处理:将异常定义为对象
- 寻求与类型为 std::invalid_argument 的未捕获异常相关的运行时错误的建议: stoi:无转换
- C ,在多个块中捕获用户定义的异常
- 从自定义sqrt函数捕获异常在c++中失败