コンパイラ警告 (レベル 2) C4251
'type' : クラス 'type1' は、クラス 'type2' のクライアントによって使用される DLL インターフェイスを備えている必要があります
解説
この警告は、クラスが __declspec(dllexport)
または __declspec(dllimport)
でマークされている場合で、そのクラスのメンバーである非静的データ メンバー、またはその基底クラスのメンバーである非静的データ メンバーに、__declspec(dllexport)
または __declspec(dllimport)
でマークされていないクラス型が含まれる場合に発生します。 「例」を参照してください。
__declspec(dllexport)
として宣言されたクラスをエクスポートするときにデータが破損する可能性を最小限に抑えるために、次のことを確認してください。
- すべての静的データが、DLL からエクスポートされた関数を介してアクセスされること。
- クラスのインライン化されたメソッドのどれも、静的データを変更できないこと。
- クラスのインライン化されたメソッドのどれも、CRT 関数または、静的データを使用するその他のライブラリ関数を使用しないこと。 詳細については、「DLL の境界を越えて CRT オブジェクトを渡す場合に発生する可能性のあるエラー」を参照してください。
- (インライン化されているかどうかにかかわらず) クラスのどのメソッドも、EXE および DLL のインスタンス化に静的データの違いがある型を使用できないこと。
DLL からクラスをエクスポートするときの問題は、次の方法で回避できます。
- クラスが仮想関数を持つように定義する。
- 仮想デストラクターを定義する。
- 型のインスタンスをインスタンス化および削除する関数を定義する。
クラスの派生元が C++ 標準ライブラリの型であり、コンパイルしているのがデバッグ リリースであり (/MTd
)、コンパイラのエラー メッセージが _Container_base
を参照している場合、C4251 は無視してかまいません。
__declspec(dllexport)
や __declspec(dllimport)
のクラスへの追加については慎重な検討を行ってください。ほとんどの場合、これは適切な選択ではなく、実装の詳細の変更を難しくするため、メンテナンスがより困難になる可能性があるためです。
例
// C4251.cpp
// Compile with /std:c++20 /EHsc /W2 /c C4251.cpp
#include <vector>
class __declspec(dllexport) X
{
public:
X();
~X();
void do_something();
private:
void do_something_else();
std::vector<int> data; // warning c4251
};
この警告を修正するには、クラスを __declspec(dllexport)
または __declspec(dllimport)
でマークしないようにしてください。 代わりに、クライアントによって直接使用されるメソッドのみをマークします。 次に例を示します。
// C4251_fixed.cpp
// Compile with /std:c++20 /EHsc /W2 /c C4251-fixed.cpp
#include <vector>
class X
{
public:
__declspec(dllexport) X();
__declspec(dllexport) ~X();
__declspec(dllexport) void do_something();
private:
void do_something_else();
std::vector<int> data;
};