Udostępnij przez


Ostrzeżenie kompilatora (poziom 2) C4251

'typ': 'type1' musi mieć interfejs DLL, aby być używanym przez klientów typu 'type2'

Uwagi

To ostrzeżenie występuje, jeśli klasa jest oznaczona elementem __declspec(dllexport) lub __declspec(dllimport) i niestatyczną składową danych, która jest składową klasy lub składowej jednej z jej klas bazowych, ma typ, który jest typem klasy, który nie jest oznaczony jako __declspec(dllexport) lub __declspec(dllimport). Zobacz przykład.

Aby zminimalizować możliwość uszkodzenia danych podczas eksportowania klasy zadeklarowanej jako __declspec(dllexport), upewnij się, że:

  • Dostęp do wszystkich danych statycznych jest uzyskiwany za pośrednictwem funkcji eksportowanych z biblioteki DLL.
  • Żadne wbudowane metody klasy nie mogą modyfikować danych statycznych.
  • Żadna ze wbudowanych metod klasy nie używa funkcji CRT ani innych funkcji bibliotek, które używają danych statycznych. Aby uzyskać więcej informacji, zobacz Potencjalne błędy przekazywania obiektów CRT przez granice bibliotek DLL.
  • Żadne metody twojej klasy (niezależnie od tego, czy są wstawione, czy nie) nie mogą używać typów, w których instancje w pliku EXE i DLL mają różnice w danych statycznych.

Podczas eksportowania klasy z biblioteki DLL można uniknąć problemów, wykonując następujące czynności:

  • Definiowanie klasy w celu posiadania funkcji wirtualnych.
  • Definiowanie destruktora wirtualnego.
  • Definiowanie funkcji do tworzenia i usuwania wystąpień typu.

Możesz zignorować język C4251, jeśli klasa pochodzi z typu w standardowej bibliotece języka C++, kompilujesz wydanie debugowania (/MTd), a komunikat o błędzie kompilatora odwołuje się do _Container_base.

Starannie pomyśl o dodaniu __declspec(dllexport) lub __declspec(dllimport) do klasy, ponieważ prawie zawsze nie jest to właściwy wybór i może utrudnić konserwację, ponieważ utrudnia zmianę szczegółów implementacji.

Przykład

Poniższy przykład generuje 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
};

Aby naprawić to ostrzeżenie, nie oznaczaj klasy __declspec(dllexport) lub __declspec(dllimport). Zamiast tego należy oznaczyć tylko metody, które są używane bezpośrednio przez klienta. Na przykład:

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