C++ 从库中的std::exception派生:仅标头的解决方案是否可以捕获异常?

C++ 从库中的std::exception派生:仅标头的解决方案是否可以捕获异常?,c++,dll,std,C++,Dll,Std,在我们的跨平台开源库中,我们从std::exception派生,以定义可以在库代码和用户代码中捕获的自定义异常。我看到这实际上是一个推荐的过程,但是在Visual Studio 2015(或者更确切地说,是附带的新MSVC版本?)中,在实现类()中抛出了一个警告-请参见此处: 当然,我们可以忽略错误,但我觉得这似乎是错误的 与较旧的Visual Studio版本相比,出现警告的原因似乎是std::exception曾在较旧的MSVC版本中导出,但同时不再导出。不管是哪种情况,我觉得把它编译进图书

在我们的跨平台开源库中,我们从std::exception派生,以定义可以在库代码和用户代码中捕获的自定义异常。我看到这实际上是一个推荐的过程,但是在Visual Studio 2015(或者更确切地说,是附带的新MSVC版本?)中,在实现类()中抛出了一个警告-请参见此处:

当然,我们可以忽略错误,但我觉得这似乎是错误的

与较旧的Visual Studio版本相比,出现警告的原因似乎是std::exception曾在较旧的MSVC版本中导出,但同时不再导出。不管是哪种情况,我觉得把它编译进图书馆从来都不是“正确的方式”

从我在答案中读到的内容来看,更好的方法是“内联”类,因为导出基类(std::exception)可能会导致更复杂的问题。如果我理解正确,“内联”在这里意味着不使用“内联”关键字,而是将定义移动到标题中,不导出它。这是对的吗

假设这就是它的意思:我的问题是,抛出异常的编译库(在它的一个头中定义)是否允许在动态链接该库的可执行文件中正确捕获异常。但是如果编译器不同呢?运行时类型信息(RTTI)在这里似乎是相关的,那么即使使用不同的编译器版本,甚至不同的编译器,它也能保证以这种方式工作吗?如果这不起作用,如何以“正确”的方式解决这个问题?

引用问题中链接的帖子中的()

。。。将STL类型放在DLL的接口中会迫使您按照STL的规则进行播放(特别是,您不能混合使用不同的主要版本的VC,并且您的IDL设置必须匹配)。然而,有一个解决办法。C4251基本上是噪声,可以静音

混合编译器版本和选项可能(并且可能在某个时候)导致应用程序出现问题和不可预测的行为。因此,无法保证它会起作用,可能相反,它不会起作用

当使用上述内联技术(即仅标头实现)并确保项目中的设置和编译器一致时,可以在给定dll导出约束的情况下解决问题


鉴于它是一个开源项目,可以很容易地为客户机环境构建它,因此所提到的任何技术都应该是合适的,因为客户机将能够根据自己的编译器和所需的选项构建代码。

据我所知,有两种选择。(1) 在整个应用程序中需要相同的工具链。然后您可以忽略并使C4275和C4251静音。(2) 允许不同的工具链,只导出与C兼容的接口(没有包含虚拟函数、异常、内联线或任何其他新的跨模块边界的双jouterie的类)。介于两者之间的任何事情都是自找麻烦。我可能弄错了,但我总是选择选项1,我还没有看到任何问题的迹象。这是一个很好的观点,但你不会想知道我们有多少次提到了以下问题之一:用户将旧编译器版本的预编译二进制文件与新编译器相结合,创建可执行文件,并抱怨它不工作,或者抱怨我们没有提供预编译的二进制文件(哦,不,必须自己编译库!!!),或者有人强行混合调试和发布运行时(恐怖)并指责我们,或者有人用一个工具集在一台计算机上编译库,并用另一个工具集将其链接到另一台计算机上的可执行文件,我们可能确实应该添加某种编译时错误或类似的错误,以防止不匹配的toolsetsBijouterie之间的链接。今天我学到了一个新单词。如果我没弄错的话,你是说如果我们以某种方式限制编译器版本的混合,我们可以使用我们现在的dll导出异常,或者将其移动到仅限标头的实现,并且在这两种情况下都应始终有效(但我看不到将其移动到标头的好处),对吗?@Ident。对的这两种方法都有效。我慢慢地变得更热衷于内联选项,只是因为它提供的警告更少,并且在我们的环境中提供了更多的灵活性——但坦率地说,两者之间几乎没有什么区别——这是一个实现决策。