Partilhar via


Exportação de Classes de Strings usando CStringT

Observação

A biblioteca Microsoft Foundation Classes (MFC) e a Active Template Library (ATL) continuam a ser suportadas. No entanto, já não estamos a adicionar funcionalidades nem a atualizar a documentação.

No passado, os programadores de MFC derivaram de CString especializar as suas próprias classes de strings. No Microsoft Visual C++.NET (MFC 8.0), a classe CString foi substituída por uma classe template chamada CStringT. Isto trouxe vários benefícios:

  • Permitia que a classe MFC CString fosse usada em projetos ATL sem ligar à biblioteca estática maior MFC ou DLL.

  • Com a nova CStringT classe template, pode personalizar CString o comportamento usando parâmetros template que especificam traços de caracteres, semelhante aos templates na C++ Standard Library.

  • Quando exportas a tua própria classe string a partir de uma DLL usando CStringT, o compilador também exporta automaticamente a CString classe base. Como CString é ela própria uma classe modelo, pode ser instanciada pelo compilador quando utilizada, a menos que o compilador saiba que CString é importada de uma DLL. Se migrou projetos do Visual C++ 6.0 para o Visual C++.NET, pode ter visto erros nos símbolos do linker para uma versão múltipla CString definida devido à colisão entre a CString versão importada de uma DLL e a versão instanciada localmente. A forma correta de o fazer está descrita abaixo.

O cenário seguinte fará com que o linker produza erros de símbolo para classes definidas por múltiplas dimensões. Assuma que está a exportar uma CStringclasse derivada de -(CMyString) a partir de uma DLL de extensão MFC:

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

O código de consumo utiliza uma mistura de CString e CMyString. "MyString.h" não está incluído no cabeçalho pré-compilado, e alguma utilização de CString não tem CMyString visível.

Assuma que usas as CString classes e CMyString em ficheiros de origem separados, Source1.cpp e Source2.cpp. No Source1.cpp, usas CMyString e #include MyString.h. Em Source2.cpp, usas CString, mas não #include MyString.h. Neste caso, o linker queixar-se-á de CStringT ser definido por múltiplas formas. Isto é causado por CString ser importado da DLL que exporta CMyString, e instanciado localmente pelo compilador através do CStringT template.

Para resolver este problema, faça o seguinte:

Exportar CStringA e CStringW (e as classes base necessárias) de MFC90.DLL. Os projetos que incluem MFC usarão sempre a DLL MFC CStringA exportada e CStringW, como nas implementações anteriores de MFC.

Depois, 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
};

Em AfxStr.h, substitua os anteriores CString, CStringA, e CStringW typedefs da seguinte forma:

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 ressalvas:

  • Não deves exportar-se CStringT porque isso fará com que projetos exclusivos de ATL exportem uma classe especializada CStringT .

  • Usar uma classe derivada exportável minimiza CStringT a necessidade de reimplementar CStringT funcionalidades. O código adicional limita-se a encaminhar construtores para a CStringT classe base.

  • CString, CStringA, e CStringW só devem ser marcados __declspec(dllexport/dllimport) quando estás a construir com um DLL partilhado MFC. Se estiveres a ligar com uma biblioteca estática MFC, não deves marcar estas classes como exportadas; caso contrário, o uso interno de CString, , e CStringW as DLLs internas do utilizador também serão marcadas CStringCStringAcomo exportadas.

Classe CStringT

Consulte também

Utilização do CStringT
Utilização do CString