生成导出包含 ATL::CString 成员的类的 DLL 时出现警告 C4251

Posted

技术标签:

【中文标题】生成导出包含 ATL::CString 成员的类的 DLL 时出现警告 C4251【英文标题】:Warning C4251 when building a DLL that exports a class containing an ATL::CString member 【发布时间】:2011-01-09 02:50:18 【问题描述】:

我正在将基于 ATL 的静态库转换为 DLL,并且在任何使用 ATL CString 类(在 atlstr.h 中找到)的导出类上都收到以下警告:

警告 C4251: 'Foo::str_' : 类 'ATL::CStringT' 需要使用 dll 接口 由“Foo”类的客户

我正确地将Foo 类声明为通过__declspec(dllexport) 导出。这是我可以安全忽略的警告还是我做错了什么? DLL 项目设置设置为与 ATL 动态链接,但这似乎没有任何区别。

例如:

#ifdef DLLTEST_EXPORTS
#define DLLTEST_API __declspec(dllexport)
#else
#define DLLTEST_API __declspec(dllimport)
#endif

// This class is exported from the DLLTest.dll
class DLLTEST_API Foo

public:
 Foo();
 CString str_; // WARNING C4251 HERE
;

此 DLL 的所有客户端也将使用 ATL。

【问题讨论】:

如果您能够确保库和客户端都是针对完全相同版本的 ATL 库构建的,那么您可以忽略它。 【参考方案1】:

This thread 给出了我认为更好的答案,作者是 Doug Harrison(VC++ MVP):

[此警告]在您使用时发出 一个非 dllexported 类 X dllexported class Y. 有什么不好 关于那个?好吧,假设 Y 有一个 调用 a 的内联函数 y_f 属于 X 的函数 x_f 是 也不内联。如果 y_f 是内联的 在一些没有的客户内部 静态链接X,链接会失败, 因为找不到 x_f。

【讨论】:

如果未导出的类确实用于内联函数,为什么不只发出警告?就像现在一样,即使没有问题,它们也会迫使您以某种方式使您的代码更加混乱,因为私有成员始终用于非内联函数中。 @Knitschi:(1) 从技术上讲,我认为警告是由编译器前端发出的,它不知道内联决策,(2) 我个人认为应该完全忽略这个警告。即使在内联函数中使用了未导出的类 - 损坏是链接错误,而不是运行时错误,应该立即修复。 网络存档:web.archive.org/web/20170811142318/http://…【参考方案2】:

这个 Microsoft 页面帮助了我。

How to export an instantiation of a Standard Template Library (STL) class and a class that contains a data member that is an STL object

【讨论】:

WebArchive web.archive.org/web/20141227011407/http://support.microsoft.com/…【参考方案3】:

Here is a thread 对此进行了很好的讨论。

简而言之,编译器会警告您,实际上,您的导出类并未将接口与实现分开。如果客户无法访问有问题的成员,请将它们设为私有并 #pragma 取消该成员/类的警告。如果成员可以被客户端访问和使用,那么您将需要通过访问器和修改器提供对成员的间接访问。

【讨论】:

那么如果警告对象已经是类私有的,我们可以放心地忽略这个警告吗?【参考方案4】:

当我犯了使用运行时库单/多线程而不是单/多线程 DLL 构建 DLL 的愚蠢错误时,我通常会收到此警告。您可能需要在您的项目设置中进行检查。

【讨论】:

以上是关于生成导出包含 ATL::CString 成员的类的 DLL 时出现警告 C4251的主要内容,如果未能解决你的问题,请参考以下文章

包含另一个类作为成员变量的类的构造函数

导出的类中可以有私有成员吗? [复制]

包含具有 CString 成员变量的类的集合仅存储首字母

在没有任何构造函数的类的情况下,在 C++11 中自动生成类成员函数

从 C++ dll 导出一个类?

java——内部类