Экспорт строковых классов с помощью CStringT
В прошлом разработчики MFC производились от CString
специализации собственных строковых классов. В Microsoft Visual C++.NET (MFC 8.0) класс CString был заменен классом шаблона CStringT. Это обеспечило несколько преимуществ:
Это позволило использовать класс MFC
CString
в проектах ATL без связывания в более крупной статической библиотеке или библиотеке DLL MFC.С помощью нового
CStringT
класса шаблона можно настроитьCString
поведение с помощью параметров шаблона, которые указывают признаки символов, аналогичные шаблонам в стандартной библиотеке C++.При экспорте собственного класса строк из библиотеки DLL с помощью
CStringT
компилятор также автоматически экспортирует базовыйCString
класс. Так какCString
это класс шаблона, он может быть создан компилятором при использовании, если компилятор не знает, чтоCString
импортируется из библиотеки DLL. Если вы перенесли проекты из Visual C++ 6.0 в Visual C++.NET, возможно, вы видели ошибки символов компоновщика для умножения, определяемого из-заCString
столкновенияCString
импортированного из библиотеки DLL и локально созданной версии. Ниже описано правильное выполнение этого действия.
Следующий сценарий приведет к возникновению ошибок символов компоновщика для умножения определенных классов. Предположим, что вы экспортируете производный CString
класс (CMyString
) из библиотеки DLL расширения MFC:
// MyString.h
class AFX_EXT_CLASS CMyString : public CString
{
// Your implementation code
};
В коде потребителя используется смесь CString
и CMyString
. "MyString.h" не включается в предварительно скомпилированные заголовки, а некоторые виды использования CString
не отображаются CMyString
.
Предположим, что вы используете CString
и CMyString
классы в отдельных исходных файлах, Source1.cpp и Source2.cpp. В Source1.cpp используется CMyString
и #include MyString.h. В Source2.cpp используется CString
, но не #include MyString.h. В этом случае компоновщик будет жаловаться на CStringT
умножение определения. Это вызвано импортом CString
из библиотеки DLL, которая экспортирует CMyString
и создает экземпляр локально компилятором с помощью CStringT
шаблона.
Чтобы устранить эту проблему, выполните следующие действия.
Экспорт CStringA
и CStringW
(и необходимые базовые классы) из MFC90.DLL. Проекты, включающие MFC, всегда будут использовать экспортированные CStringA
библиотеки DLL MFC, CStringW
как и в предыдущих реализациях MFC.
Затем создайте экспортируемый производный класс с помощью CStringT
шаблона, как CStringT_Exported
показано ниже, например:
#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
};
В AfxStr.h замените предыдущие CString
CStringA
и CStringW
typedefs следующим образом:
typedef CStringT_Exported< wchar_t,
StrTraitMFC< wchar_t > > CStringW;
typedef CStringT_Exported< char,
StrTraitMFC< char > > CStringA;
typedef CStringT_Exported< TCHAR,
StrTraitMFC< TCHAR > > CString;
Существует несколько предостережения:
Не следует экспортировать себя, так как это приведет к экспорту
CStringT
специализированногоCStringT
класса только для ATL.Использование экспортируемого производного класса из
CStringT
минимизации необходимости повторной реализацииCStringT
функциональных возможностей. Дополнительный код ограничен переадресацией конструкторов в базовыйCStringT
класс.CString
,CStringA
иCStringW
должны быть помечены__declspec(dllexport/dllimport)
только при создании с помощью общей библиотеки DLL MFC. При связывании со статической библиотекой MFC не следует пометить эти классы как экспортированные; в противном случае внутреннее использование ,CStringA
а такжеCStringW
внутри пользовательскихCString
библиотек DLL будет помечатьсяCString
как экспортированные.