How to dllexport a class derived from std::runtime_error?(如何 dllexport 从 std::runtime_error 派生的类?)
问题描述
我建立了一个库,提供从标准异常派生的异常类:
I have set up a library providing an exception class derived from the standard exception:
#include <stdexcept>
#include <string>
class BaseException : public std::runtime_error
{
public:
BaseException( std::string const & msg );
};
到目前为止,一切都很好.在 Unix 上编译和处理得很好.现在我准备将其编译为 Windows DLL:
So far, so good. Compiles and handles quite well on Unix. Now I am prepping this for compilation into a Windows DLL:
#ifdef WIN32
#define MY_EXPORT __declspec(dllexport)
#else
#define MY_EXPORT
#endif
#include <stdexcept>
#include <string>
class MY_EXPORT BaseException : public std::runtime_error
{
public:
BaseException( std::string const & msg );
};
然而,这给了我 警告 C4275:非 DLL 接口类'std::runtime_error' 用作 DLL 接口类 'BaseException' 的基础.
However, this gives me warning C4275: non – DLL-interface class 'std::runtime_error' used as base for DLL-interface class 'BaseException'.
不幸的是,我对 Microsoft 风格的文档有些过敏:过于冗长,而且不是很切题.它一直让我完全困惑,不知道实际期望我解决什么问题.
And unfortunately, I am somewhat allergic to Microsoft-style documentation: Excessively wordy, and not very to the point. It keeps leaving me utterly confused as to what is actually expected of me to solve my problem.
你们中的任何人都可以启发我吗?我可以删除基类,但随后捕获 std::runtime_error 或 std::exception 不会捕获我的自定义异常类,我更喜欢这样成为可能.所以……?
Can any of you enlighten me? I could just drop the base class, but then catching std::runtime_error or std::exception would not catch my custom exception class, and I would very much prefer this to be possible. So...?
推荐答案
在这种情况下,您有几个选择.
There are a few options for you in this type of situation.
- 导出.
- 忽略它.
- 内嵌它.
重要的是要记住,从 dll 导出类的正确"方法是导出整个类,包括基类和成员.出于这个原因,有几种技术,例如 CodeProject 上的这个,使用接口"和适当的工厂来创建类(和匹配的销毁).
It is important to bear in mind that the "correct" way to export class from a dll is to export the entire class, including bases and members. For this reason there are several techniques such as this one on CodeProject, that use an "interface" and appropriate factory to create the class (and matching destruction).
在这种情况下,这对您来说没有太大用处,尝试导出 std::runtime_error 可能更费力,并且可能会在以后引入更大的问题.
This is not too useful for you in this situation, trying to export std::runtime_error is probably more effort and likely to introduce even bigger issues later on.
取自 此处的 Microsoft Connect 站点(webarchive),这些错误系列本质上是噪音;
Taken from the Microsoft Connect site here (webarchive), the family of these errors are essentially noise;
我建议首先避免这种情况 - 将 STL 类型放在 DLL 的接口中会迫使您遵守 STL 的规则(特别是,您不能混合不同主要版本的 VC,并且您的 IDL 设置必须匹配).但是,有一个解决方法.C4251本质上是噪音,可以静音...
I recommend avoiding this in the first place - 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...
Stephan T. Lavavej(Micrsoft 的 C++ 库的维护者之一).
Stephan T. Lavavej (one of the maintainer's of Micrsoft's C++ library).
只要编译器选项在整个项目中是一致的,只需忽略此警告就可以了.
So long as the compiler options are consistent through the project, just silencing this warning should be just fine.
最后一个选项是内联定义 BaseException 类并且根本不导出它.
The final option is to define the BaseException class inline and not export it at all.
根据我的经验,内联选项对于异常类来说几乎总是最简单的.
In my experience, the inline option landed up almost always being the easiest for exception classes.
VS2015 的 C++ 运行时发生了变化,导致 std::exception 的导出发生了变化(它不是从运行时导出的).
Changes in the C++ runtime for VS2015, have resulted in changes to the exporting of std::exception (It is not exported from the runtime).
inline 选项现在似乎是这个时候最合适的(你的里程可能会有所不同).
The inline option now seems to be the most appropriate at this time (your mileage may vary).
class Exception : exception {
public:
char const* what() const override;
};
inline char const* Exception::what() const {
/*...*/
};
这篇关于如何 dllexport 从 std::runtime_error 派生的类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何 dllexport 从 std::runtime_error 派生的类?
基础教程推荐
- 通过引用传递 C++ 迭代器有什么问题? 2022-01-01
- CString 到 char* 2021-01-01
- 非静态 const 成员,不能使用默认赋值运算符 2022-10-09
- 为什么派生模板类不能访问基模板类的标识符? 2021-01-01
- 如果我为无符号变量分配负值会发生什么? 2022-01-01
- 为什么 RegOpenKeyEx() 在 Vista 64 位上返回错误代码 2021-01-01
- 为什么 typeid.name() 使用 GCC 返回奇怪的字符以及如 2022-09-16
- GDB 显示调用堆栈上函数地址的当前编译二进制文 2022-09-05
- 初始化列表*参数*评估顺序 2021-01-01
- 我应该对 C++ 中的成员变量和函数参数使用相同的名称吗? 2021-01-01
