Exportar classes de cadeia de caracteres usando CStringT
No passado, os desenvolvedores do MFC fizeram derivação de CString
para especializar suas próprias classes de cadeia de caracteres. No .NET (MFC 8.0) do Microsoft Visual C++, a classe CString foi substituída por uma classe de modelo chamada CStringT. Isso forneceu vários benefícios:
Permitiu que a classe
CString
do MFC fosse usada em projetos da ATL sem vinculação na biblioteca estática no MFC maior ou na DLL.Com a nova classe de modelo
CStringT
, você pode personalizar o comportamentoCString
usando parâmetros de modelo que especificam características de caractere, semelhantes aos modelos na Biblioteca Padrão C++.Quando você exporta sua própria classe de cadeia de caracteres de uma DLL usando
CStringT
, o compilador também exporta automaticamente a classe baseCString
. ComoCString
é uma classe de modelo, ela pode ser instanciada pelo compilador quando usada, a menos que o compilador esteja ciente de queCString
é importado de uma DLL. Se você migrou projetos do Visual C++ 6.0 para o Visual C++ .NET, talvez tenha visto erros de símbolo do vinculador para umCString
com multiplicação definida devido à colisão doCString
importado de uma DLL e da versão localmente instanciada. A maneira adequada de fazer isso é descrita abaixo.
O cenário a seguir fará com que o vinculador produza erros de símbolo para multiplicar classes definidas. Suponha que você esteja exportando uma classe derivada de CString
(CMyString
) de uma DLL de extensão MFC:
// MyString.h
class AFX_EXT_CLASS CMyString : public CString
{
// Your implementation code
};
O código do consumidor usa uma mistura de CString
e CMyString
. "MyString.h" não está incluído no cabeçalho pré-compilado e alguns usos de CString
não têm CMyString
visível.
Suponha que você use as classes CString
e CMyString
em arquivos de origem separados, Source1.cpp e Source2.cpp. Em Source1.cpp, você usa CMyString
e #include MyString.h. Em Source2.cpp, você usa CString
, mas não usa #include MyString.h. Nesse caso, o vinculador reclamará de CStringT
ter sido definido por multiplicação. Isso é causado por CString
ser importado da DLL que exporta CMyString
e instanciado localmente pelo compilador por meio do modelo CStringT
.
Para resolver esse problema, execute uma das seguintes ações:
Exporte CStringA
e CStringW
(e as classes base necessárias) de MFC90.DLL. Os projetos que incluem o MFC sempre usarão a DLL do MFC exportada CStringA
e CStringW
, como nas implementações anteriores do MFC.
Em seguida, crie uma classe derivada exportável usando o CStringT
modelo, como CStringT_Exported
está abaixo, por exemplo:
#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
};
No AfxStr.h, substitua os typedefs CString
, CStringA
e CStringW
anteriores da seguinte maneira:
typedef CStringT_Exported< wchar_t,
StrTraitMFC< wchar_t > > CStringW;
typedef CStringT_Exported< char,
StrTraitMFC< char > > CStringA;
typedef CStringT_Exported< TCHAR,
StrTraitMFC< TCHAR > > CString;
Existem várias advertências:
Você não deve exportar apenas
CStringT
porque isso fará com que projetos somente ATL exportem uma classeCStringT
especializada.O uso de uma classe derivada exportável de
CStringT
minimiza a necessidade de implementar novamente a funcionalidadeCStringT
. O código adicional é limitado ao encaminhamento de construtores para a classe baseCStringT
.CString
,CStringA
eCStringW
só devem ser marcados como__declspec(dllexport/dllimport)
quando você estiver criando com uma DLL compartilhada do MFC. Se estiver vinculando com uma biblioteca estática do MFC, você não deverá marcar essas classes como exportadas. Caso contrário, o uso interno deCString
,CStringA
eCStringW
nas DLLs do usuário também marcaráCString
como exportado.