Esportazione di classi String tramite CStringT
In passato, gli sviluppatori MFC hanno derivato da CString
per specializzare le proprie classi di stringhe. In Microsoft Visual C++.NET (MFC 8.0), la classe CString è stata sostituita da una classe modello denominata CStringT. In questo modo sono stati offerti diversi vantaggi:
Ha consentito l'uso della classe MFC
CString
nei progetti ATL senza il collegamento nella libreria statica MFC o nella DLL più grande.Con la nuova
CStringT
classe modello, è possibile personalizzareCString
il comportamento usando parametri di modello che specificano tratti di carattere, simili ai modelli nella libreria standard C++.Quando si esporta una classe stringa personalizzata da una DLL usando
CStringT
, il compilatore esporta automaticamente anche laCString
classe di base. PoichéCString
si tratta di una classe modello, può essere creata un'istanza dal compilatore quando viene usata, a meno che il compilatore non sappia cheCString
viene importato da una DLL. Se è stata eseguita la migrazione di progetti da Visual C++ 6.0 a Visual C++.NET, potrebbero essere stati visualizzati errori di simboli del linker per una moltiplicazione definitaCString
a causa del conflitto tra l'importazioneCString
da una DLL e la versione di cui è stata creata un'istanza locale. Il modo appropriato per eseguire questa operazione è descritto di seguito.
Lo scenario seguente causerà la generazione di errori di simboli da parte del linker per la moltiplicazione delle classi definite. Si supponga di esportare una CString
classe derivata daCMyString
una DLL di estensione MFC:
// MyString.h
class AFX_EXT_CLASS CMyString : public CString
{
// Your implementation code
};
Il codice consumer usa una combinazione di CString
e CMyString
. "MyString.h" non è incluso nell'intestazione precompilata e alcuni utilizzi di CString
non sono CMyString
visibili.
Si supponga di usare le CString
classi e CMyString
in file di origine separati, Source1.cpp e Source2.cpp. In Source1.cpp usare CMyString
e #include MyString.h. In Source2.cpp si usa CString
, ma non si #include MyString.h. In questo caso, il linker si lamenta della CStringT
moltiplicazione definita. Ciò è causato dall'importazione CString
sia dalla DLL che esporta CMyString
e creata un'istanza in locale dal compilatore tramite il CStringT
modello.
Per risolvere questo problema, eseguire le operazioni seguenti:
Esportare CStringA
e CStringW
(e le classi di base necessarie) da MFC90.DLL. I progetti che includono MFC useranno sempre la DLL MFC esportata CStringA
e CStringW
, come nelle implementazioni MFC precedenti.
Creare quindi una classe derivata esportabile usando il CStringT
modello, come illustrato di CStringT_Exported
seguito, ad esempio:
#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
};
In AfxStr.h sostituire i typedef , CStringA
e CStringW
precedenti CString
come indicato di seguito:
typedef CStringT_Exported< wchar_t,
StrTraitMFC< wchar_t > > CStringW;
typedef CStringT_Exported< char,
StrTraitMFC< char > > CStringA;
typedef CStringT_Exported< TCHAR,
StrTraitMFC< TCHAR > > CString;
Esistono diverse avvertenze:
Non è consigliabile esportare
CStringT
se stesso perché ciò causerà l'esportazione di una classe specializzataCStringT
solo di progetti ATL.L'uso di una classe derivata esportabile da
CStringT
riduce al minimo la necessità di implementareCStringT
nuovamente la funzionalità. Il codice aggiuntivo è limitato ai costruttori di inoltro allaCStringT
classe base.CString
,CStringA
eCStringW
devono essere contrassegnati__declspec(dllexport/dllimport)
solo quando si compila con una DLL condivisa MFC. Se si esegue il collegamento con una libreria statica MFC, non è consigliabile contrassegnare queste classi come esportate; in caso contrario, anche l'uso interno di ,CStringA
eCStringW
all'interno delleCString
DLL utente contrassegneràCString
come esportato.