当类定义不可见时捕获异常

时间:2018-11-02 14:41:03

标签: c++ exception

我正在处理一个问题,即输入文件损坏导致引发异常。异常类在实现文件中定义,因此对我不可见。它确实继承自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上看不到任何提及,但这似乎是一种反模式,即“仅抛出异常”)。

1 个答案:

答案 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;
}

Online demo