Export tříd řetězců pomocí CStringT
V minulosti vývojáři MFC odvozeni od CString
specializovat vlastní třídy řetězců. V aplikaci Microsoft Visual C++.NET (MFC 8.0) byla třída CString nahrazena třídou šablony s názvem CStringT. To poskytlo několik výhod:
Povolila použití třídy MFC
CString
v projektech ATL bez propojení ve větší statické knihovně MFC nebo knihovně DLL.Pomocí nové
CStringT
třídy šablony můžete přizpůsobitCString
chování pomocí parametrů šablony, které určují vlastnosti znaků, podobně jako šablony ve standardní knihovně C++.Při exportu vlastní třídy řetězců z knihovny DLL pomocí
CStringT
, kompilátor také automaticky exportujeCString
základní třídu. Vzhledem k tomuCString
, že je sama o sobě třída šablony, může být vytvořena kompilátorem při použití, pokud kompilátor neví, žeCString
je importován z knihovny DLL. Pokud jste migrovali projekty z Visual C++ 6.0 do Visual C++.NET, pravděpodobně jste viděli chyby symbolů linkeru pro násobení definovanéCString
kvůli koliziCString
importované z knihovny DLL a místně instance verze. Správný způsob, jak to udělat, je popsán níže.
Následující scénář způsobí, že linker vytvoří chyby symbolů pro násobení definovaných tříd. Předpokládejme, že exportujete odvozenou CString
třídu (CMyString
) z knihovny DLL rozšíření MFC:
// MyString.h
class AFX_EXT_CLASS CMyString : public CString
{
// Your implementation code
};
Kód příjemce používá kombinaci a CString
CMyString
. Text "MyString.h" není součástí předkompilované hlavičky a některé použití CString
není CMyString
viditelné.
Předpokládejme, že používáte CString
třídy v CMyString
samostatných zdrojových souborech, Source1.cpp a Source2.cpp. V Source1.cpp použijete CMyString
a #include MyString.h. V Source2.cpp použijete CString
, ale ne #include MyString.h. V tomto případě si linker stěžuje na CStringT
to, že se definuje násobení. Příčinou je CString
import z knihovny DLL, která exportuje CMyString
, a vytvoření instance místně kompilátorem prostřednictvím CStringT
šablony.
Pokud chcete tento problém vyřešit, postupujte takto:
Export CStringA
a CStringW
(a nezbytné základní třídy) z MFC90.DLL Projekty, které zahrnují MFC, budou vždy používat knihovny MFC DLL exportované CStringA
a CStringW
, stejně jako v předchozích implementacích MFC.
Pak vytvořte exportovatelnou odvozenou třídu pomocí CStringT
šablony, jak CStringT_Exported
je uvedeno níže, například:
#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
};
V AfxStr.h nahraďte předchozí CString
CStringA
, a CStringW
typedefs následujícím způsobem:
typedef CStringT_Exported< wchar_t,
StrTraitMFC< wchar_t > > CStringW;
typedef CStringT_Exported< char,
StrTraitMFC< char > > CStringA;
typedef CStringT_Exported< TCHAR,
StrTraitMFC< TCHAR > > CString;
Existuje několik upozornění:
Neměli byste exportovat
CStringT
sami, protože to způsobí, že projekty pouze ATL exportuje specializovanouCStringT
třídu.Použití exportovatelné odvozené třídy z
CStringT
minimalizace nutnosti znovu implementovatCStringT
funkce. Další kód je omezen na předávání konstruktorů doCStringT
základní třídy.CString
,CStringA
aCStringW
měla by být označena__declspec(dllexport/dllimport)
pouze při vytváření pomocí knihovny MFC sdílené knihovny DLL. Pokud je propojení se statickou knihovnou MFC, neměli byste tyto třídy označit jako exportované; jinak interní použitíCString
knihovny DLL aCStringA
CStringW
uvnitř uživatelských knihoven DLL se označíCString
také jako exportované.