2010-11-23 4 views
4

Я использую экспортированный классКак использовать экспортированный класс (__declspec (dllexport)) в шаблоне stl?

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

Когда я делаю это, я получаю предупреждение C4251 говоря m_map: класс «станд :: Карта < _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 >; 

внутри включенного заголовка. Обратите внимание на экстерн здесь. В одном модуле компиляции объявить такой же, но без экстерном и без FOO_API, таким образом:

template class Templ<MyClass, int >; 

Это будет означать, что код, используя вашу библиотеку не экземпляр шаблона, но будет использовать один в вашей библиотеке. Это особенно полезно, когда шаблон имеет виртуальных членов.

Если шаблон является одним из стандартной библиотеки или повысить, то код, использующий ваш, должен будет использовать ту же версию, что и ваша, или может возникнуть серьезная проблема.

Учитывая, что в вашем собственном примере оно появляется в частной области, и вы хотите реорганизовать его из интерфейса для своей библиотеки. В идеале ваша библиотека должна публиковать публичные методы и другие члены, кроме передовых объявлений. Частные копии-конструкторы и назначения для того, чтобы сделать класс несовместимым и не назначаемым, в порядке - они не являются частью реализации, они являются частью интерфейса вашего класса (вы говорите, что вы не можете копировать или назначать их).

2

Вы не можете экспортировать класс с элементами, которые не экспортируются. Возможным решением будет использование идиомы Pimpl. С помощью Pimpl члены класса не знакомы с пользователем. Поэтому классы stl не должны экспортироваться. Для дальнейшего чтения о Pimpl проверьте следующее: http://c2.com/cgi/wiki?PimplIdiom или http://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

@ Дэвид, не могли бы вы рассказать об этом идиоме Pimpl? – Atul 2010-11-23 08:25:28

+0

@atul отредактировал мое сообщение с примером – 2010-11-23 08:38:22