次の方法で共有


CStringT を使用した文字列クラスのエクスポート

従来、MFC 開発者は、CString から派生させて独自の文字列クラスを作成してきました。 Microsoft Visual C++.NET (MFC 8.0) では、CString クラスの代わりに、CStringT と呼ばれるテンプレート クラスを使用するようになりました。 これには、いくつかの利点があります。

  • より大きな MFC スタティック ライブラリまたは DLL でリンクを使用せずに、ATL プロジェクトで MFC CString クラスを使用できるようになりました。

  • 新しい CStringT テンプレート クラスを使用すると、標準テンプレート ライブラリ (STL: Standard Template Library) のテンプレートと同様に、文字の特徴を指定するテンプレート パラメーターを使用して、CString の動作をカスタマイズできます。

  • CStringT を使用して DLL から独自の文字列クラスをエクスポートすると、コンパイラは CString 基本クラスも自動的にエクスポートします。 CString 自体はテンプレート クラスなので、CString が DLL からインポートされることをコンパイラが認識しない限り、コンパイラの使用時にインスタンス化される可能性があります。 プロジェクトを Visual C++ 6.0 から Visual C++.NET に移行した場合、DLL からインポートされた CString とローカルでインスタンス化されたバージョンの競合が原因で、重複して定義された CString に関するリンカー シンボル エラーが発生することがあります。 エラーを発生させずに適切に使用する方法については、以下で説明します。 この問題の詳細については、MSDN ライブラリ CD-ROM または https://support.microsoft.com/default.aspx にあるサポート技術情報の文書「Linking Errors When you Import CString-derived Classes」 (Q309801) を参照してください。

次のシナリオでは、リンカーで重複して定義されたクラスに関するシンボル エラーが発生します。 CString 派生クラス (CMyString) を MFC 拡張 DLL からエクスポートしていると仮定します。

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

コンシューマー コードで、CString と CMyString が一緒に使用されています。■訳文不要■ MyString.h" はプリコンパイル済みヘッダーに含まれていないため、CString の使用法によっては、CMyString が表示されません。

個別のソース ファイル (Source1.cpp および Source2.cpp) で CString クラスおよび CMyString クラスを使用すると仮定します。 Source1.cpp では、CMyString および #include MyString.h を使用します。 Source2.cpp では、CString を使用しますが、#include MyString.h を使用しません。 この場合、リンカーでは、CStringT が重複して定義されていることを示すエラーが発生します。 これは、CString が、CMyString をエクスポートする DLL からインポートされると同時に、コンパイラによって CStringT テンプレートが使用されローカルでインスタンス化されることが原因です。

この問題を解決するには、次のように操作します。

MFC90.DLL. から CStringA および CStringW (さらに、必要な基本クラス) をエクスポートします。 MFC を含むプロジェクトでは、以前の MFC 実装と同様に、MFC DLL からエクスポートされた CStringA および CStringW が常に使用されます。

次に、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 では、以前の CStringCStringA、および CStringW の各 typedef を次のように置き換えます。

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

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

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

いくつかの注意点を次に示します。

  • CStringT 自体はエクスポートしないでください。このエクスポートが原因で ATL 専用プロジェクトがプロジェクトに特化した CStringT クラスをエクスポートするためです。

  • エクスポートできる派生クラスを CStringT から使用すると、CStringT 機能を再実装する必要性を最小限に抑えることができます。 追加のコードは、構造体を CStringT 基本クラスに転送することに制限されています。

  • CStringCStringA、および CStringW は、MFC 共有 DLL でビルドする場合のみ、__declspec(dllexport/dllimport) に設定する必要があります。 MFC スタティック ライブラリとリンクする場合、これらのクラスをエクスポート済みに設定しないでください。それ以外の場合は、CStringCStringA、および CStringW をユーザー DLL の内部で使用すると、CString が同様にエクスポート済みに設定されます。

関連トピック

CStringT クラス

参照

その他の技術情報

CStringT の使用

CString の使用