我正在处理一个问题,即输入文件损坏导致引发异常。异常类在实现文件中定义,因此对我不可见。它确实继承自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()
消息进行字符串比较,但这看起来很丑。
还有其他选择吗?
(顺便说一句,我在Google上看不到任何提及,但这似乎是一种反模式,即“仅抛出异常”)。
答案 0 :(得分:1)
如果您无权访问原始课程,则将无法正确捕获它:
C ++标准/ [句柄除外]:
处理程序中的例外声明描述了 可能导致输入 handler 的异常。 exception-declaration 不得表示不完整类型,抽象类类型或右值引用类型。 除了[ cv void *]之外, exception-declaration 不得表示指针或对不完整类型的引用。
因此,没有理想且干净的解决方案。但也许可以接受的解决方法:从std::exception派生的类是多态的。因此,您可以考虑使用typeid()
(最终与type_index
结合使用)来标识catch (std::exception& e)
块中的实类型。
恕我直言,.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;
}