2013-05-03 128 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

相關問題