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

24

我正在将一个基于ATL的静态库转换为动态链接库,在任何导出使用ATL CString 类(在atlstr.h中找到)的类中,都会得到以下警告:

警告 C4251: 'Foo::str_' : 类 'ATL::CStringT' 需要具有dll界面才能被'Foo'类的客户端使用

我正确地通过__declspec(dllexport)导出Foo类。这是我可以安全忽略的警告吗?或者我做错了什么?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库构建的,那么您可以忽略它。 - Zoltan Tirinda
4个回答

20

这个帖子提供了我认为更好的答案,来自Doug Harrison(VC++ MVP):

当您在dllexported类Y中使用一个非dllexported类X时,将会发出此警告。这有什么不好的呢?嗯,假设Y有一个内联函数y_f,该函数调用属于X的函数x_f,而x_f不是内联的。如果y_f在某个没有静态链接X的客户端中被内联,则链接将失败,因为找不到x_f。


为什么不仅在内联函数中真正使用未导出的类时发出警告呢?现在,即使私有成员始终在非内联函数中使用,它们也会强制您以某种方式使代码变得混乱,即使没有问题。 - Knitschi
4
@Knitschi: (1) 技术上来说,我认为这些警告是由编译器前端发出的,它对内联决策一无所知。(2) 我个人认为应该完全省略此警告。即使未导出的类在内联函数中被使用,也只会导致链接错误,而不是运行时错误,并且应立即进行修复。 - Ofek Shilon
3
WebArchive: https://web.archive.org/web/20170811142318/http://www.microsoft-questions.com/microsoft/VC-Language/30952961/a-solution-to-warning-c4251--class-needs-to-have-dllinterface.aspx - KindDragon

14

4
WebArchive https://web.archive.org/web/20141227011407/http://support.microsoft.com/kb/168958这篇文章介绍了如何在Windows中进行批处理文件的编写、调试和运行。它还包括了一些实用的技巧和注意事项,如如何执行批处理文件以及如何设置环境变量等。此外,该文还提供了一些常见的批处理错误和解决方法,帮助读者更好地理解批处理文件的工作原理。 - KindDragon

9
以下是翻译的结果:

这里有一个讨论线程,内容与此相关。

简而言之,编译器警告你的导出类没有将接口与实现分离。如果涉及到的成员不会被客户端所使用,将它们设置为private,并使用#pragma消除该成员/类的警告即可。如果这些成员是对客户端可见且被客户端使用的,则需要通过访问器和修改器来提供间接访问。


10
如果所警告的对象已经是类内部私有的,我们可以安全地忽略此警告吗? - meawoppl

0

当我犯了一个愚蠢的错误,使用运行时库Single/Multithreaded而不是Single/MultithreadedDLL来构建DLL时,通常会出现这个警告。你可能需要在项目设置中检查它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接