C++ 类定义不可见时捕获异常

C++ 类定义不可见时捕获异常,c++,exception,C++,Exception,我正在处理一个问题,即一个损坏的输入文件导致抛出异常。异常类是在实现文件中定义的,因此对我不可见。它确实继承自std::exception 我尝试简单地向前声明异常类,因为我只是通过引用来捕获它。但是,这给了我一个错误:无效使用不完整类型编译器错误(在Linux上使用GCC6.2)。我假设编译器需要完整的异常对象类型,以便在需要时可以重新引发异常 这就是我想做的: // library.cpp namespace FOO { struct SomeException : public std

我正在处理一个问题,即一个损坏的输入文件导致抛出异常。异常类是在实现文件中定义的,因此对我不可见。它确实继承自
std::exception

我尝试简单地向前声明异常类,因为我只是通过引用来捕获它。但是,这给了我一个
错误:无效使用不完整类型
编译器错误(在Linux上使用GCC6.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]:

处理程序中的异常声明描述 可能导致输入该处理程序的异常。 异常声明不应表示不完整类型、抽象类类型或右值引用类型。 异常声明不得表示指向不完整类型的指针或引用,但[cv void*]除外

因此,没有理想和干净的解决方案。但可能是一个可以接受的解决方法:从中派生的类是多态的。因此,您可以考虑使用(最终结合)来标识<代码> catch(STD::异常和E)< /Cord>块。p> 我想,当
时,区分未知异常应该是一种可以接受的方法。what()
不是替代方法。然而,不便之处在于标准中没有定义
type\u 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;
}
//某处
类MyExcept:public std::exception{};
...
//其他地方
试一试{
抛出std::exception();
}捕获(标准::异常&e){

std::我可以说这是实现该异常的人的一个设计错误。似乎正确的做法是要求他们修复它。您正在处理一个损坏的/有错误的库,应该要求修复它。传播到用户代码的任何异常的定义必须对用户代码可见。Forward-声明它不会有帮助,因为您无法使用前向声明访问对象(我认为您需要访问此对象,否则,为什么要捕获它)?@Francois这是我担心人们会说的。如果能说服他们改变它,他们可能会改变。如果不能……是的,通过引用捕获是正确的方法——但是你可以通过指针捕获,在这种情况下,你不需要类定义,我想正向定义应该足够了。你将拥有谁拥有异常,因此应该将其删除的问题-以及对象切片的问题(如果是您,并且他们没有实现虚拟析构函数)。综合考虑,让他们更改它是最好的。@SergeyA我现在不需要访问异常对象。我只想能够捕获它,以便能够记录错误这比“出错”更具体。谢谢你证实我的怀疑。这看起来是我能做的最好的了,直到库被改变。