Как использовать экспортированный класс (__declspec (dllexport)) в шаблоне stl? - PullRequest
4 голосов
/ 23 ноября 2010

Я использую экспортированный класс

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

Когда я делаю это, я получаю предупреждение C4251 о том, что m_map: class 'std :: map <_Kty, _Ty>' должен иметь dll-интерфейс для использования клиентами класса myclass. Любые идеи о том, как я могу решить эту проблему?
Атул

Ответы [ 3 ]

6 голосов
/ 23 ноября 2010

Вы не должны использовать __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 >;

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

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

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

2 голосов
/ 23 ноября 2010

Никогда не пробовал, но эта ссылка, кажется, ищет эту проблему: http://support.microsoft.com/kb/168958

2 голосов
/ 23 ноября 2010

Вы не можете экспортировать класс с членами, которые не экспортируются.Возможным решением будет использование идиомы 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;
};
...