2010-11-23 5 views
4

ich eine exportierte Klasse bin mitWie verwendet man eine exportierte Klasse (__declspec (dllexport)) in einer STL-Vorlage?

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

Wenn ich das tue, erhalte ich eine Warnung C4251 sagen m_map: Bedürfnisse DLL-Schnittstelle verwendet werden müssen, Klasse ‚std :: map < _Kty, _Ty>‘ durch Kunden der Klasse myclass.
Irgendwelche Ideen, wie ich das lösen kann?
Atul

Antwort

6

Sie sollten nicht verwenden __declspec (dllexport) in den Header-Dateien, die Code Ihre DLL verwenden werden, da sie brauchen Verwenden Sie __declspec (dllimport).

Daher sollten Sie einen Makro erstellen, der dllexport verwendet, wenn eine bestimmte andere Definition festgelegt ist, und dllimport, wenn dies nicht der Fall ist.

In einem gemeinsamen Header irgendwo:

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

Sie können eine Vorlage instanziiert:

extern template class FOO_API Templ<MyClass, int >; 

innerhalb einer mitgelieferten Header. Beachten Sie das Extern hier. Innerhalb einer Übersetzungseinheit erklären die gleiche, aber ohne die extern und ohne FOO_API, also:

template class Templ<MyClass, int >; 

Diese bedeuten, dass der Code Ihrer Bibliothek verwendet, wird die Vorlage nicht instanziiert sondern wird das in Ihrer Bibliothek werden. Dies ist besonders nützlich, wenn die Vorlage virtuelle Mitglieder hat.

Wenn die Vorlage eine aus der Standardbibliothek oder dem Boost ist, muss der Code, der Ihren verwendet, die gleiche Version verwenden wie Ihre oder es könnte ein ernstes Problem sein.

Gegeben, dass in Ihrem eigenen Beispiel erscheint es im privaten Bereich schlägt vor, Sie es aus der Schnittstelle für Ihre Bibliothek umgestalten wollen. Im Idealfall sollte Ihre Bibliothek nur öffentliche Methoden und Member außer Forward-Deklarationen verfügbar machen. Private Kopierkonstruktoren und Zuweisungen, um eine Klasse nicht kopierbar und nicht zuweisbar zu machen, sind in Ordnung - sie sind nicht wirklich Teil der Implementierung, sie sind Teil der Schnittstelle Ihrer Klasse (Sie sagen, dass Sie sie nicht kopieren oder zuweisen können)).

+0

So habe ich es 2010 gemacht, aber jetzt habe ich tatsächlich eine Datei stdafx.h oder ähnliches, die von allen Projektquellen, aber nicht von externen Benutzerquellen enthalten ist und die FOO_API oder was auch immer definiert. Der Header führt dann einfach #ifndef FOO_API aus und führt auch eine # pragma comment lib aus. – CashCow

2

Sie können keine Klasse mit Elementen exportieren, die nicht exportiert werden. Eine mögliche Lösung wäre die Verwendung des Pimpl-Idioms. Mit Pimpl sind die Mitglieder der Klasse dem Benutzer nicht bekannt. Daher müssen keine STL-Klassen exportiert werden. Für weitere über Pimpl Lesen prüfen: http://c2.com/cgi/wiki?PimplIdiom oder http://www.gamedev.net/reference/articles/article1794.asp

Beispiel:

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

@ David, Können Sie bitte dieses Pimpl Idiom erarbeiten? – Atul

+0

@atul hat meinen Beitrag mit einem Beispiel bearbeitet –

+0

Gut, aber Sie machen sich mehr Probleme, den Destruktor virtuell zu machen. Niemand wird von ihnen abgeleitet werden, denn wenn Sie Polymorphie wollen, legen Sie das in den pImpl. Sie sollten Ihre Klasse auch nicht kopierbar und nicht zuweisbar machen. – CashCow