Avviso del compilatore (livello 2) C4251
'type': la classe 'type1' deve avere dll-interface da usare dai client della classe 'type2'
Osservazioni:
Questo avviso si verifica se una classe è contrassegnata con __declspec(dllexport)
o __declspec(dllimport)
e un membro dati non statico membro della classe o di un membro di una delle relative classi di base, ha un tipo che è un tipo di classe non contrassegnato con __declspec(dllexport)
o __declspec(dllimport)
. Vedere Esempio.
Per ridurre al minimo la possibilità di danneggiamento dei dati durante l'esportazione di una classe dichiarata come __declspec(dllexport)
, assicurarsi che:
- Tutti i dati statici sono accessibili tramite funzioni esportate dalla DLL.
- Nessun metodo inlined della classe può modificare i dati statici.
- Nessun metodo inlined della classe usa funzioni CRT o altre funzioni di libreria che usano dati statici. Per altre informazioni, vedere Potenziali errori che passano oggetti CRT attraverso limiti DLL.
- Nessun metodo della classe (inlined o meno) può usare i tipi in cui l'istanza di EXE e DLL presenta differenze di dati statici.
È possibile evitare problemi durante l'esportazione di una classe da una DLL tramite:
- Definizione della classe per avere funzioni virtuali.
- Definizione di un distruttore virtuale.
- Definizione delle funzioni per creare un'istanza ed eliminare istanze del tipo.
È possibile ignorare C4251 se la classe è derivata da un tipo nella libreria standard C++, si sta compilando una versione di debug (/MTd
) e il messaggio di errore del compilatore fa riferimento a _Container_base
.
Pensa attentamente all'aggiunta __declspec(dllexport)
o __declspec(dllimport)
a una classe perché non è sempre la scelta giusta e può rendere più difficile la manutenzione perché rende più difficile modificare i dettagli di implementazione.
Esempio
// 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
};
Per correggere questo avviso, non contrassegnare la classe con __declspec(dllexport)
o __declspec(dllimport)
. Contrassegnare invece solo i metodi usati direttamente da un client. Ad esempio:
// 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;
};