2010-11-23 62 views
4

我使用的是出口類如何在stl模板中使用導出的類(__declspec(dllexport))?

class __declspec(dllexport) myclass 
{ 
private: 
template __declspec(dllexport) class std::map<myclass*,int>;  
std::map<myclass*,int>m_map; 
//something 
};  

當我這樣做,我得到一個警告C4251說m_map:類「的std ::地圖< _Kty,_Ty>」必須有DLL接口使用的myclass類的客戶端。
有關我如何解決此問題的任何想法?
Atul

回答

6

你不應該使用__declspec(dllexport)的成頭文件使用DLL的代碼將被使用,因爲他們需要正在使用__declspec(dllimport)。

因此,如果設置了特定的其他定義,則應該創建一個使用dllexport的宏;如果不是,則使用dllimport。

在某處一個共同的頭:

#ifdef EXPORTING_FOO 
#define FOO_API __declspec(dllexport) 
#else 
#define FOO_API __declspec(dllimport) 
#endif 

您可以實例化一個模板:包含的頭內

extern template class FOO_API Templ<MyClass, int >; 

。注意這裏的外部。 在一個編譯單元聲明相同,但沒有extern和無FOO_API,即:

template class Templ<MyClass, int >; 

這將意味着使用您的庫中的代碼不會實例化的模板,但將使用一個在您的圖書館。這在模板具有虛擬成員時特別有用。

如果模板是來自標準庫或boost的模板,則使用您的代碼必須使用與您的代碼相同的版本,否則可能會出現嚴重問題。

鑑於在你自己的例子中,它出現在私人區域,表明你想重新將它從你的圖書館的界面中重構出來。理想情況下,您的圖書館應該只公開公開的方法和除正向聲明之外的成員。私人拷貝構造函數和賦值爲了使一個類不可複製和不可賦值是好的 - 它們不是實現的一部分,它們是你類的接口的一部分(你說你不能拷貝或賦值它們)。

2

您無法導出未導出成員的類。一個可能的解決方案是使用Pimpl成語。使用Pimpl時,用戶不知道該課程的成員。所以不需要導出stl類。用於進一步閱讀PIMPL檢查以下內容: http://c2.com/cgi/wiki?PimplIdiomhttp://www.gamedev.net/reference/articles/article1794.asp

實施例:

myclass.h:

class __declspec(dllexport) myclass 
{ 
public: 
    myclass(); 
    virtual ~myclass(); 
private: 
    myclass(const myclass& other) {} 
    myclass& operator=(const myclass& rhs) {return *this;} 
    myclassImpl* m_Pimpl; 
}; 

myclass.cpp:

#include "myclass.h" 
#include "myclassImpl.h" 


myclass::myclass() 
    :m_Pimpl(new myclassImpl()) 
{} 

myclass::~myclass() { 
    delete m_Pimpl; 
} 

myclassImpl.h:

class myclassImpl { 
private: 
    std::map<myclass*,int>m_map; 
}; 
+0

@大衛,請您詳細說明這個皮姆普成語嗎? – Atul 2010-11-23 08:25:28

+0

@atul用一個例子編輯我的帖子 – 2010-11-23 08:38:22

相關問題