description | title | ms.date | helpviewer_keywords | ms.assetid | |
---|---|---|---|---|---|
Learn more about: Exporting String Classes Using CStringT |
Exporting String Classes Using CStringT |
11/04/2016 |
|
bdfc441e-8d2a-461c-9885-46178066c09f |
In the past, MFC developers have derived from CString
to specialize their own string classes. In Microsoft Visual C++.NET (MFC 8.0), the CString class was superseded by a template class called CStringT. This provided several benefits:
-
It allowed the MFC
CString
class to be used in ATL projects without linking in the larger MFC static library or DLL. -
With the new
CStringT
template class, you can customizeCString
behavior using template parameters that specify character traits, similar to the templates in the C++ Standard Library. -
When you export your own string class from a DLL using
CStringT
, the compiler also automatically exports theCString
base class. SinceCString
is itself a template class, it may be instantiated by the compiler when used, unless the compiler is aware thatCString
is imported from a DLL. If you have migrated projects from Visual C++ 6.0 to Visual C++.NET, you might have seen linker symbol errors for a multiply-definedCString
because of the collision of theCString
imported from a DLL and the locally instantiated version. The proper way to do this is described below.
The following scenario will cause the linker to produce symbol errors for multiply defined classes. Assume that you are exporting a CString
-derived class (CMyString
) from an MFC extension DLL:
[!code-cppNVC_MFC_DLL#6]
The consumer code uses a mixture of CString
and CMyString
. "MyString.h" is not included in the precompiled header, and some usage of CString
does not have CMyString
visible.
Assume that you use the CString
and CMyString
classes in separate source files, Source1.cpp and Source2.cpp. In Source1.cpp, you use CMyString
and #include MyString.h. In Source2.cpp, you use CString
, but do not #include MyString.h. In this case, the linker will complain about CStringT
being multiply defined. This is caused by CString
being both imported from the DLL that exports CMyString
, and instantiated locally by the compiler through the CStringT
template.
To resolve this problem, do the following:
Export CStringA
and CStringW
(and the necessary base classes) from MFC90.DLL. Projects that include MFC will always use the MFC DLL exported CStringA
and CStringW
, as in previous MFC implementations.
Then create a exportable derived class using the CStringT
template, as CStringT_Exported
is below, for example:
[!code-cppNVC_MFC_DLL#7]
In AfxStr.h, replace the previous CString
, CStringA
, and CStringW
typedefs as follows:
[!code-cppNVC_MFC_DLL#8]
There are several caveats:
-
You should not export
CStringT
itself because this will cause ATL-only projects to export a specializedCStringT
class. -
Using an exportable derived class from
CStringT
minimizes having to re-implementCStringT
functionality. Additional code is limited to forwarding constructors to theCStringT
base class. -
CString
,CStringA
, andCStringW
should only be marked__declspec(dllexport/dllimport)
when you are building with an MFC shared DLL. If linking with an MFC static library, you should not mark these classes as exported; otherwise, internal use ofCString
,CStringA
, andCStringW
inside user DLLs will markCString
as exported as well.