Exportation de classes de chaînes à l’aide de CStringT
Dans le passé, les développeurs MFC ont dérivé de CString
pour spécialiser leurs propres classes de chaînes. Dans Microsoft Visual C++.NET (MFC 8.0), la classe CString a été remplacée par une classe de modèle appelée CStringT. Cela a fourni plusieurs avantages :
Il a permis à la classe MFC
CString
d’être utilisée dans les projets ATL sans liaison dans la bibliothèque statique MFC ou la DLL plus volumineuse.Avec la nouvelle
CStringT
classe de modèle, vous pouvez personnaliserCString
le comportement à l’aide de paramètres de modèle qui spécifient des caractéristiques de caractère, similaires aux modèles de la bibliothèque standard C++.Lorsque vous exportez votre propre classe de chaîne à partir d’une DLL à l’aide
CStringT
d’une DLL, le compilateur exporte également automatiquement laCString
classe de base. ÉtantCString
donné qu’elle est elle-même une classe de modèle, elle peut être instanciée par le compilateur lorsqu’elle est utilisée, sauf si le compilateur est conscient qu’ilCString
est importé à partir d’une DLL. Si vous avez migré des projets de Visual C++ 6.0 vers Visual C++.NET, vous avez peut-être vu des erreurs de symboles d’éditeur de liens pour une multiplication définieCString
en raison de la collision de l’importationCString
à partir d’une DLL et de la version instanciée localement. La bonne façon de procéder est décrite ci-dessous.
Le scénario suivant entraîne la génération d’erreurs de symboles par l’éditeur de liens pour multiplier les classes définies. Supposons que vous exportez une CString
classe dérivée (CMyString
) à partir d’une DLL d’extension MFC :
// MyString.h
class AFX_EXT_CLASS CMyString : public CString
{
// Your implementation code
};
Le code consommateur utilise un mélange de CString
et CMyString
. « MyString.h » n’est pas inclus dans l’en-tête précompilé, et certaines utilisations ne CString
sont pas visibles CMyString
.
Supposons que vous utilisez les classes et CMyString
les CString
classes dans des fichiers sources distincts, Source1.cpp et Source2.cpp. Dans Source1.cpp, vous utilisez CMyString
et #include MyString.h. Dans Source2.cpp, vous utilisez CString
, mais ne #include Pas MyString.h. Dans ce cas, l’éditeur de liens se plaindra de CStringT
la multiplication définie. Cela est dû CString
à l’importation à partir de la DLL qui exporte CMyString
, et instanciée localement par le compilateur via le CStringT
modèle.
Pour résoudre ce problème, procédez comme suit :
Exportez CStringA
et (et CStringW
les classes de base nécessaires) à partir de MFC90.DLL. Les projets qui incluent MFC utilisent toujours la DLL MFC exportée CStringA
et CStringW
, comme dans les implémentations MFC précédentes.
Créez ensuite une classe dérivée exportable à l’aide du CStringT
modèle, comme CStringT_Exported
indiqué ci-dessous, par exemple :
#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
};
Dans AfxStr.h, remplacez les éléments précédents CString
, CStringA
et CStringW
typedefs comme suit :
typedef CStringT_Exported< wchar_t,
StrTraitMFC< wchar_t > > CStringW;
typedef CStringT_Exported< char,
StrTraitMFC< char > > CStringA;
typedef CStringT_Exported< TCHAR,
StrTraitMFC< TCHAR > > CString;
Il existe plusieurs mises en garde :
Vous ne devez pas l’exporter
CStringT
elle-même, car cela entraîne l’exportation d’un projet ATL uniquement pour exporter une classe spécialiséeCStringT
.L’utilisation d’une classe dérivée exportable à partir de
CStringT
réduire la nécessité de réinscrireCStringT
les fonctionnalités. Le code supplémentaire est limité aux constructeurs de transfert vers laCStringT
classe de base.CString
,CStringA
etCStringW
ne doit être marqué__declspec(dllexport/dllimport)
que lorsque vous générez avec une DLL partagée MFC. Si vous établissez une liaison avec une bibliothèque statique MFC, vous ne devez pas marquer ces classes comme exportées ; sinon, l’utilisation interne desCString
CStringA
DLL utilisateur etCStringW
à l’intérieur marqueCString
également l’exportation.