共用方式為


編譯器警告 (層級 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:

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