Eksportowanie klas ciągów przy użyciu CStringT
W przeszłości deweloperzy MFC pochodzili z CString
, aby specjalizować własne klasy ciągów. W programie Microsoft Visual C++.NET (MFC 8.0) klasa CString została zastąpiona przez klasę szablonu o nazwie CStringT. Zapewniało to kilka korzyści:
Klasa MFC mogła być używana w projektach ATL bez łączenia w większej bibliotece statycznej MFC
CString
lub bibliotece DLL.Dzięki nowej
CStringT
klasie szablonu można dostosowaćCString
zachowanie przy użyciu parametrów szablonu, które określają cechy znaków, podobnie jak szablony w standardowej bibliotece języka C++.Podczas eksportowania własnej klasy ciągów z biblioteki DLL przy użyciu
CStringT
programu kompilator automatycznie eksportuje klasę bazowąCString
. PonieważCString
sam jest klasą szablonu, może zostać utworzone przez kompilator, jeśli jest używany, chyba że kompilator jest świadomy, żeCString
jest importowany z biblioteki DLL. W przypadku migrowania projektów z programu Visual C++ 6.0 do programu Visual C++.NET mogą wystąpić błędy symboli konsolidatora zdefiniowane przez mnożenieCString
ze względu na kolizjęCString
zaimportowanego z biblioteki DLL i lokalnie utworzonej wersji. Odpowiedni sposób, aby to zrobić, jest opisany poniżej.
Poniższy scenariusz spowoduje, że konsolidator generuje błędy symboli dla mnożenia zdefiniowanych klas. Załóżmy, że eksportujesz klasę pochodną CString
(CMyString
) z biblioteki DLL rozszerzenia MFC:
// MyString.h
class AFX_EXT_CLASS CMyString : public CString
{
// Your implementation code
};
Kod odbiorcy używa kombinacji elementów CString
i CMyString
. Element "MyString.h" nie jest uwzględniony w prekompilowanej nagłówku, a niektóre użycie elementu nie ma CMyString
widocznegoCString
.
Załóżmy, że klasy i CMyString
są używane CString
w osobnych plikach źródłowych, Source1.cpp i Source2.cpp. W Source1.cpp używasz CMyString
i #include MyString.h. W Source2.cpp użyj polecenia CString
, ale nie #include MyString.h. W takim przypadku konsolidator będzie narzekać na CStringT
zdefiniowanie mnożenia. Jest to spowodowane CString
tym, że zarówno importowane z biblioteki DLL, która eksportuje CMyString
element , jak i tworzone lokalnie przez kompilator za pośrednictwem szablonu CStringT
.
Aby rozwiązać ten problem, wykonaj następujące czynności:
Eksportuj CStringA
i CStringW
(oraz niezbędne klasy bazowe) z MFC90.DLL. Projekty zawierające MFC zawsze będą używać wyeksportowanych CStringA
bibliotek DLL MFC i CStringW
, jak w poprzednich implementacjach MFC.
Następnie utwórz klasę pochodną z możliwością eksportowania przy użyciu szablonu CStringT
, jak CStringT_Exported
pokazano poniżej, na przykład:
#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
};
W pliku AfxStr.h zastąp poprzednie CString
definicje typów , CStringA
i CStringW
w następujący sposób:
typedef CStringT_Exported< wchar_t,
StrTraitMFC< wchar_t > > CStringW;
typedef CStringT_Exported< char,
StrTraitMFC< char > > CStringA;
typedef CStringT_Exported< TCHAR,
StrTraitMFC< TCHAR > > CString;
Istnieje kilka zastrzeżeń:
Nie należy eksportować
CStringT
samego siebie, ponieważ spowoduje to eksportowanie wyspecjalizowanychCStringT
klas tylko do projektów ATL.Korzystanie z klasy pochodnej z możliwością eksportowania zminimalizuje
CStringT
konieczność ponownego zaimplementowaniaCStringT
funkcji. Dodatkowy kod jest ograniczony do przekazywania konstruktorów do klasy bazowejCStringT
.CString
,CStringA
iCStringW
powinny być oznaczone__declspec(dllexport/dllimport)
tylko podczas kompilowania z udostępnioną biblioteką DLL MFC. W przypadku łączenia z biblioteką statyczną MFC nie należy oznaczać tych klas jako eksportowanych; w przeciwnym razie wewnętrzne użycieCString
bibliotek DLL ,CStringA
iCStringW
wewnątrz użytkownika będzie oznaczaćCString
, jak również eksportowane.