在我们的跨平台开源库中,我们派生自 std::exception 以定义可以在库代码和用户代码中捕获的自定义异常。我看到这实际上是一个推荐的过程,但在 Visual Studio 2015(或者更确切地说,伴随的新 MSVC 版本?)中,在实现类(warning C4275)中抛出警告 - 另请参见此处:How to dllexport a class derived from std::runtime_error?
当然我们可以忽略这个错误,但这对我来说似乎是错误的。
与旧的 Visual Studio 版本相比,出现警告的原因似乎是 std::exception 曾经在旧的 MSVC 版本中导出,但同时不再导出。无论哪种情况,我都觉得以将其编译到库中的形式继续进行这件事从来都不是“正确的方法”。
从我在答案中读到的内容来看,更好的方法是“内联”类,因为导出基类 (std::exception) 可能会导致更多的复杂性。如果我理解正确的话,这里的“内联”意味着不使用“内联”关键字,而是将定义移动到标题中并且不导出它。这甚至是正确的吗?
假设这是什么意思:我的问题是,抛出异常的编译库(在其 header 之一中定义)是否允许在动态链接该库的可执行文件中正确捕获异常。但是如果编译器不同怎么办?运行时类型信息 (RTTI) 似乎与此相关,那么即使使用不同的编译器版本甚至不同的编译器,这是否也能保证以上述方式工作?如果这不起作用,如何以“正确”的方式解决这个问题?
最佳答案
引自Microsoft Connect issue ( webarchive ) 在问题中链接的帖子中;
... putting STL types in your DLL's interface forces you to play by the STL's rules (specifically, you can't mix different major versions of VC, and your IDL settings must match). However, there is a workaround. C4251 is essentially noise and can be silenced...
混合编译器版本和选项可能(并且可能在某个时候)导致应用程序出现问题和不可预测的行为。所以,不能保证它会起作用,安静可能恰恰相反,它不会起作用。
当使用上面提到的内联技术(即仅 header 实现)并确保设置和编译器在项目中保持一致时,允许在给定 dll 导出约束的情况下进行变通。
鉴于它是一个开源项目,它可以很容易地为客户环境构建,所以提到的任何技术都应该是合适的,因为客户将能够根据他们想要的编译器和选项构建代码。
关于c++ - 从库中的 std::exception 派生:Does a headers-only solution work for catching exceptions?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32019547/