Exportación de clases de cadena mediante CStringT

En el pasado, los desarrolladores de MFC han derivado de CString para especializar sus propias clases de cadena. En Microsoft Visual C++.NET (MFC 8.0), la clase CString se reemplazó por una clase de plantilla denominada CStringT. Esto proporcionó varias ventajas:

  • Permitió que la clase CString de MFC se usara en proyectos ATL sin vincular en la biblioteca estática o DLL de MFC más grande.

  • Con la nueva clase de plantilla CStringT, puede personalizar el comportamiento de CString mediante parámetros de plantilla que especifican rasgos de caracteres, de forma similar a las plantillas de la biblioteca estándar de C++.

  • Al exportar su propia clase de cadena desde un archivo DLL mediante CStringT, el compilador también exporta automáticamente la clase base CString. Dado que CString es una clase de plantilla, puede crear instancias del compilador cuando se usa, a menos que el compilador tenga en cuenta que CString se importa desde un archivo DLL. Si ha migrado proyectos de Visual C++ 6.0 a Visual C++.NET, es posible que haya visto errores de símbolo del vinculador para una multiplicación definida como CString debido a la colisión de la importación de CString desde un archivo DLL y la versión de creación de instancias local. La forma adecuada de hacerlo se describe a continuación.

El escenario siguiente hará que el enlazador genere errores de símbolo para las clases definidas por multiplicación. Supongamos que va a exportar una clase derivada de CString (CMyString) de un archivo DLL de extensión MFC:

// MyString.h
class AFX_EXT_CLASS CMyString : public CString
{
   // Your implementation code
};

El código de consumidor usa una combinación de CString y CMyString. "MyString.h" no se incluye en el encabezado precompilado y algún uso de CString no tiene CMyString visible.

Supongamos que usa las clases CString y CMyString en archivos de código fuente independientes, Source1.cpp y Source2.cpp. En Source1.cpp, se usa CMyString y #include MyString.h. En Source2.cpp, se usa CString, pero no #include MyString.h. En este caso, el enlazador se quejará de que CStringT esté definido por multiplicación. Esto se debe a que el compilador, mediante la plantilla CStringT, importa CString desde el archivo DLL que exporta CMyString y crea instancias localmente.

Para resolver el problema, realice una de las acciones siguientes:

Exporte CStringA y CStringW (y las clases base necesarias) de MFC90.DLL. Los proyectos que incluyen MFC siempre usarán CStringA y CStringW exportados del archivo DLL de MFC, como en las implementaciones anteriores de MFC.

A continuación, cree una clase derivada exportable mediante la CStringT plantilla, como CStringT_Exported se muestra a continuación, por ejemplo:

#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
};

En AfxStr.h, reemplace las definiciones de tipo CString, CStringA y CStringW anteriores de la siguiente manera:

typedef CStringT_Exported< wchar_t, 
      StrTraitMFC< wchar_t > > CStringW;

typedef CStringT_Exported< char,
      StrTraitMFC< char > > CStringA;

typedef CStringT_Exported< TCHAR,
      StrTraitMFC< TCHAR > > CString;

Hay algunas advertencias:

  • No debe exportarse CStringT, porque esto hará que los proyectos de ATL solo exportan una clase CStringT especializada.

  • El uso de una clase derivada exportable de CStringT minimiza la necesidad de volver a implementar la funcionalidad CStringT. El código adicional se limita a reenviar constructores a la clase base CStringT.

  • CString, CStringA y CStringW solo se deben marcar cuando __declspec(dllexport/dllimport) se compila con un archivo DLL de MFC compartido. Si se vincula con una biblioteca estática de MFC, no debe marcar estas clases como exportadas; de lo contrario, el uso interno de CString, CStringA y CStringW dentro de los archivos DLL de usuario también marcará CString como exportado.

CStringT (clase)

Consulte también

Uso de CStringT
Uso de CString