Mengekspor kelas string menggunakan CStringt
Di masa lalu, pengembang MFC telah berasal dari CString
untuk mengkhasanalisasi kelas string mereka sendiri. Di Microsoft Visual C++.NET (MFC 8.0), kelas CString digantikan oleh kelas templat yang disebut CStringT. Ini memberikan beberapa manfaat:
Ini memungkinkan kelas MFC
CString
digunakan dalam proyek ATL tanpa menautkan di pustaka statis MFC atau DLL yang lebih besar.Dengan kelas templat baru
CStringT
, Anda dapat menyesuaikanCString
perilaku menggunakan parameter templat yang menentukan sifat karakter, mirip dengan templat di Pustaka Standar C++.Saat Anda mengekspor kelas string Anda sendiri dari DLL menggunakan
CStringT
, pengkompilasi juga secara otomatis mengeksporCString
kelas dasar. KarenaCString
itu sendiri kelas templat, itu mungkin dibuat oleh pengkompilasi ketika digunakan, kecuali kompiler menyadari bahwaCString
diimpor dari DLL. Jika Anda telah memigrasikan proyek dari Visual C++ 6.0 ke Visual C++.NET, Anda mungkin telah melihat kesalahan simbol linker untuk multiply-definedCString
karena tabrakanCString
yang diimpor dari DLL dan versi yang dibuat secara lokal. Cara yang tepat untuk melakukan ini dijelaskan di bawah ini.
Skenario berikut akan menyebabkan linker menghasilkan kesalahan simbol untuk kelas yang ditentukan perkalian. Asumsikan bahwa Anda mengekspor CString
kelas -turunan (CMyString
) dari DLL ekstensi MFC:
// MyString.h
class AFX_EXT_CLASS CMyString : public CString
{
// Your implementation code
};
Kode konsumen menggunakan campuran CString
dan CMyString
. "MyString.h" tidak disertakan dalam header yang telah dikommpilasikan sebelumnya, dan beberapa penggunaan CString
tidak terlihat CMyString
.
Asumsikan bahwa Anda menggunakan CString
kelas dan CMyString
dalam file sumber terpisah, Source1.cpp dan Source2.cpp. Di Source1.cpp, Anda menggunakan CMyString
dan #include MyString.h. Dalam Source2.cpp, Anda menggunakan CString
, tetapi jangan #include MyString.h. Dalam hal ini, linker akan mengeluh tentang CStringT
dikalikan yang ditentukan. Ini disebabkan oleh CString
diimpor dari DLL yang mengekspor CMyString
, dan dibuat secara lokal oleh pengkompilasi melalui CStringT
templat.
Untuk mengatasi masalah ini, lakukan hal berikut:
Ekspor CStringA
dan CStringW
(dan kelas dasar yang diperlukan) dari MFC90.DLL. Proyek yang mencakup MFC akan selalu menggunakan DLL MFC yang diekspor CStringA
dan CStringW
, seperti pada implementasi MFC sebelumnya.
Kemudian buat kelas turunan yang dapat diekspor menggunakan CStringT
templat, seperti CStringT_Exported
di bawah ini, misalnya:
#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
};
Di AfxStr.h, ganti typedefs , , CStringA
dan CStringW
sebelumnya CString
sebagai berikut:
typedef CStringT_Exported< wchar_t,
StrTraitMFC< wchar_t > > CStringW;
typedef CStringT_Exported< char,
StrTraitMFC< char > > CStringA;
typedef CStringT_Exported< TCHAR,
StrTraitMFC< TCHAR > > CString;
Ada beberapa peringatan:
Anda tidak boleh mengekspor
CStringT
dirinya sendiri karena ini akan menyebabkan proyek khusus ATL mengekspor kelas khususCStringT
.Menggunakan kelas turunan yang dapat diekspor dari
CStringT
meminimalkan harus menerapkanCStringT
kembali fungsionalitas. Kode tambahan terbatas pada meneruskan konstruktor keCStringT
kelas dasar.CString
,CStringA
, danCStringW
hanya boleh ditandai__declspec(dllexport/dllimport)
ketika Anda membangun dengan DLL bersama MFC. Jika menautkan dengan pustaka statis MFC, Anda tidak boleh menandai kelas ini sebagai diekspor; jika tidak, penggunaanCString
internal ,CStringA
, danCStringW
di dalam DLL pengguna juga akan ditandaiCString
sebagai diekspor.