Exportieren von Zeichenfolgenklassen mit CStringT
In der Vergangenheit haben MFC-Entwickler von CString
der Spezialisierung ihrer eigenen Zeichenfolgenklassen abgeleitet. In Microsoft Visual C++.NET (MFC 8.0) wurde die CString-Klasse durch eine Vorlagenklasse namens CStringT ersetzt. Dies hat mehrere Vorteile zur Verfügung gestellt:
Die MFC-Klasse
CString
konnte in ATL-Projekten ohne Verknüpfung in der größeren statischen MFC-Bibliothek oder DLL verwendet werden.Mit der neuen
CStringT
Vorlagenklasse können Sie das Verhalten mithilfe von Vorlagenparametern anpassenCString
, die Zeicheneigenschaften angeben, ähnlich wie die Vorlagen in der C++-Standardbibliothek.Wenn Sie Ihre eigene Zeichenfolgenklasse aus einer DLL exportieren,
CStringT
exportiert der Compiler auch automatisch dieCString
Basisklasse. DaCString
es sich selbst um eine Vorlagenklasse handelt, kann sie beim Verwenden vom Compiler instanziiert werden, es sei denn, der Compiler ist sich bewusst, dassCString
aus einer DLL importiert wird. Wenn Sie Projekte von Visual C++ 6.0 zu Visual C++.NET migriert haben, wurden möglicherweise Linkersymbolfehler für eine multiplizierteCString
Definition aufgrund der Kollision derCString
importierten DLL und der lokal instanziierten Version angezeigt. Die richtige Vorgehensweise hierzu wird unten beschrieben.
Das folgende Szenario führt dazu, dass der Linker Symbolfehler für multiplizierte definierte Klassen erzeugt. Gehen Sie davon aus, dass Sie eine CString
abgeleitete Klasse (CMyString
) aus einer MFC-Erweiterungs-DLL exportieren:
// MyString.h
class AFX_EXT_CLASS CMyString : public CString
{
// Your implementation code
};
Der Verbrauchercode verwendet eine Mischung aus CString
und CMyString
. "MyString.h" ist nicht im vorkompilierten Header enthalten, und einige Verwendungen von CString
"MyString.h" sind CMyString
nicht sichtbar.
Gehen Sie davon aus, dass Sie die Klassen und CMyString
Die CString
Klassen in separaten Quelldateien, Source1.cpp und Source2.cpp verwenden. In Source1.cpp verwenden CMyString
und #include MyString.h. In Source2.cpp verwenden CString
Sie , aber nicht #include MyString.h. In diesem Fall beschwert sich der Linker darüber CStringT
, dass er multipliziert wird. Dies wird dadurch verursacht, dass CString
beide aus der DLL importiert werden, die CMyString
vom Compiler über die CStringT
Vorlage lokal exportiert und instanziiert wird.
Gehen Sie wie folgt vor, um dieses Problem zu beheben:
Exportieren CStringA
und CStringW
(und die erforderlichen Basisklassen) aus MFC90.DLL. Projekte, die MFC enthalten, verwenden immer die exportierte CStringA
MFC-DLL und CStringW
, wie in früheren MFC-Implementierungen.
Erstellen Sie dann eine exportierbare abgeleitete Klasse mithilfe der CStringT
Vorlage, wie CStringT_Exported
unten dargestellt, z. B.:
#ifdef _AFXDLL
#define AFX_EXT_CSTRING AFX_EXT_CLASS
#else
#define AFX_EXT_CSTRING
#endif
template< typename BaseType, class StringTraits >
class AFX_EXT_CSTRING CStringT_Exported
: public CStringT< BaseType, StringTraits >
{
// Reimplement all CStringT<> constructors and
// forward to the base class implementation
};
Ersetzen Sie in AfxStr.h die vorherigen CString
CStringA
, und CStringW
typedefs wie folgt:
typedef CStringT_Exported< wchar_t,
StrTraitMFC< wchar_t > > CStringW;
typedef CStringT_Exported< char,
StrTraitMFC< char > > CStringA;
typedef CStringT_Exported< TCHAR,
StrTraitMFC< TCHAR > > CString;
Es gibt mehrere Vorbehalte:
Sie sollten sich nicht selbst exportieren
CStringT
, da dies dazu führt, dass NUR ATL-Projekte eine spezialisierteCStringT
Klasse exportieren.Die Verwendung einer exportierbaren abgeleiteten Klasse verhindert
CStringT
, dass die Funktionalität erneut implementiertCStringT
werden muss. Zusätzlicher Code ist auf das Weiterleiten von Konstruktoren an dieCStringT
Basisklasse beschränkt.CString
,CStringA
undCStringW
sollte nur markiert__declspec(dllexport/dllimport)
werden, wenn Sie mit einer gemeinsam genutzten MFC-DLL erstellen. Wenn Sie eine Verknüpfung mit einer statischen MFC-Bibliothek herstellen, sollten Sie diese Klassen nicht als exportiert markieren. andernfalls werden interne Verwendungen von ,CStringA
undCStringW
innerhalb vonCString
Benutzer-DLLs ebenfalls als exportiert markiertCString
.