2013-05-03 79 views
1

我明白为什么我有C4251警告,当我编译我的代码为here解释。我的问题是,如果可访问的导出类成员来自STL,我们可以忽略C4251警告吗?我举一个简单的例子来说明我的问题:在这种情况下,我可以忽略C4251警告吗?

dll.h

#include <iostream> 
#include <string> 

using namespace std; 

class __declspec(dllexport) HelloWorld 
{ 
public: 
    string name; 
    HelloWorld(); 
    HelloWorld(const string &str); 

}; 

dll.cpp

#include "dll.h" 

HelloWorld::HelloWorld() 
{ 
    name =""; 
} 
HelloWorld::HelloWorld(const string &str) 
{ 
name = str; 
} 

我已经获得的警告信息是如下:

Warning 1 warning C4251: 'HelloWorld::name' : class 'std::basic_string<_Elem,_Traits,_Ax>' needs to have dll-interface to be used by clients of class 'HelloWorld' *\dll.h 9 

我的问题是:我可以忽略这个警告吗?我如何使用这个库的方式也很简单:

#include "dll.h" 
#include <iostream> 
using namespace std; 

int main(void) 
{ 
    HelloWorld myworld; 
    myworld.name = "Tom's world"; 
    cout<<myworld.name<<endl; 
    return 0; 
} 
+3

只是第一点 - 我不会把'using namespace std'放在头文件中。它强制你的头文件的所有用户把这个名字空间导入他们的代码中。 – 2013-05-03 15:28:12

+2

就个人而言,如果API *很简单,我根本不会使用'std :: string',而是坚持使用'char'等外部接口。 – 2013-05-03 15:29:05

回答

5

可以忽略,但你应该明白为什么会这样,什么是你可能遇到的问题。

模板是在编译时启动。这意味着它可能取决于您编译代码的方式。最可能改变代码的是预编译器定义(例如#define _NDEBUG或-D_NDEBUG作为命令行参数)。

如果您的DLL接口包含依赖于在编译时发生的事件的对象类型,则您的DLL的所有客户端都必须确保这些类型在其代码中的编译方式与您的代码中的编译方式相同,否则可能会发生错误。

编译相同也意味着使用相同的编译器。编译器之间的差异还可以使得生成的可执行文件的代码不同,而不同的编译器通常使用不同的STL库。

我举一个例子:

template <typename T> 
class A 
{ 
    int m_data; 
#ifndef NDEBUG 
    int m_debugData; 
#endif 

public: 
    void func() 
    { 
     m_data =0; 
#ifndef NDEBUG 
     m_debugData = 0; 
#endif 
    } 
}; 

在这个例子中,如果您的DLL与NDEBUG和使用代码编译编译没有NDEBUG,要求从用户代码FUNC()可能会导致运行时错误。

+0

@JirkaHanika你说得对,我会将其添加到答案中。 – selalerer 2013-05-03 15:39:22

+0

+1 - 很好的例子 – 2013-05-03 15:43:21

+0

@selalerer感谢您的详细解释。我写了一个类似于你给出的例子的简单程序,并且需要时遇到运行时错误。你能解释为什么这个运行时错误会发生吗?谢谢! – feelfree 2013-05-03 16:12:24

6

要暴露在你的DLL接口的标准C++库的实现细节,你需要从他们的方式实施的标准C++库,并会保持与各过去和未来版本相兼容的编译器供应商(S)一些担保您打算使用的编译器。否则,稍后您可能会遇到非常晦涩的崩溃。

这特定的供应商是very clear这些兼容性保证的程度:

C4251可以如果从标准C++库中的类型导出,编译一个调试释放(/ MTD),并且其中被忽略编译器错误消息引用_Container_base。

欲了解更多背景,请咨询this post

因此,答案是 “没有”。如果今天有效,明天可能会中断。

的情况类似于弊端诸如在一个DLL分配存储器,而在另一个DLL释放它。

,当前的风险和腐败几乎为零,如果DLL和它的所有客户端都使用完全相同的编译器版本和编译设置编译,如果你从来没有混合调试和你的日常工作发布二进制文件。但是这种危险的设计习惯违背了DLL的二进制可重用性,并可能以非明显和昂贵的方式限制您的未来。继续感受到编译器的警告是你可以做的最不重要的事情。

+0

谢谢,这是一个非常深思熟虑的评论。 – feelfree 2013-05-03 16:22:23

相关问题