Errore del compilatore C2280
'declaration': tentativo di fare riferimento a una funzione eliminata
Il compilatore ha rilevato un tentativo di fare riferimento a una deleted
funzione. Questo errore può essere causato da una chiamata a una funzione membro contrassegnata in modo esplicito come = deleted
nel codice sorgente. Questo errore può anche essere causato da una chiamata a una funzione membro speciale implicita di uno struct o di una classe dichiarata automaticamente e contrassegnata come deleted
dal compilatore. Per altre informazioni su quando il compilatore genera default
automaticamente o deleted
funzioni membro speciali, vedere Funzioni membro speciali.
Esempio: Funzioni eliminate in modo esplicito
Una chiamata a una funzione in modo esplicito deleted
causa questo errore. Una funzione membro in modo esplicito deleted
implica che la classe o lo struct è intenzionalmente progettato per impedirne l'uso, quindi per risolvere questo problema, è necessario modificare il codice per evitarlo.
// C2280_explicit.cpp
// compile with: cl /c /W4 C2280_explicit.cpp
struct A {
A();
A(int) = delete;
};
struct B {
A a1;
A a2 = A(3); // C2280, calls deleted A::A(int)
// To fix, remove the call to A(int)
};
void f() {
B b; // calls implicit B::B(void)
}
Esempio: Membri dati non inizializzati
Un membro dati o const
un membro dati di tipo riferimento non inizializzato fa in modo che il compilatore dichiari in modo implicito un deleted
costruttore predefinito. Per risolvere questo problema, inizializzare il membro dati quando viene dichiarato.
// C2280_uninit.cpp
// compile with: cl /c C2280_uninit.cpp
struct A {
const int i; // uninitialized const-qualified data
// members or reference type data members cause
// the implicit default constructor to be deleted.
// To fix, initialize the value in the declaration:
// const int i = 42;
} a; // C2280
Esempio: Membri dati reference e const
Un const
membro dati del tipo di riferimento o fa in modo che il compilatore dichiari un deleted
operatore di assegnazione di copia. Dopo l'inizializzazione, questi membri non possono essere assegnati, quindi una copia o uno spostamento semplice non possono funzionare. Per risolvere questo problema, è consigliabile modificare la logica per rimuovere le operazioni di assegnazione che causano l'errore.
// C2280_ref.cpp
// compile with: cl /c C2280_ref.cpp
extern int k;
struct A {
A();
int& ri = k; // a const or reference data member causes
// implicit copy assignment operator to be deleted.
};
void f() {
A a1, a2;
// To fix, consider removing this assignment.
a2 = a1; // C2280
}
Esempio: Elimina la copia implicita
Se una classe dichiara un costruttore di spostamento o un operatore di assegnazione di spostamento, ma non dichiara in modo esplicito un costruttore di copia, il compilatore dichiara in modo implicito un costruttore di copia e lo definisce come deleted
. Analogamente, se una classe dichiara un costruttore di spostamento o un operatore di assegnazione di spostamento, ma non dichiara in modo esplicito un operatore di assegnazione di copia, il compilatore dichiara in modo implicito un operatore di assegnazione di copia e lo definisce come deleted
. Per risolvere questo problema, è necessario dichiarare in modo esplicito questi membri.
Quando viene visualizzato l'errore C2280 in connessione a , unique_ptr
è quasi certamente perché si sta tentando di richiamare il relativo costruttore di copia, che è una deleted
funzione. Per impostazione predefinita, non è possibile copiare un oggetto unique_ptr
. Usare invece un costruttore di spostamento per trasferire la proprietà.
// C2280_move.cpp
// compile with: cl /c C2280_move.cpp
class base
{
public:
base();
~base();
base(base&&);
// Move constructor causes copy constructor to be
// implicitly declared as deleted. To fix this
// issue, you can explicitly declare a copy constructor:
// base(base&);
// If you want the compiler default version, do this:
// base(base&) = default;
};
void copy(base *p)
{
base b{*p}; // C2280
}
Esempio: Membri varianti e volatili
Le versioni del compilatore precedenti a Visual Studio 2015 Update 2 non erano conformi e generavano costruttori e distruttori predefiniti per unioni anonime. Questi vengono ora dichiarati in modo implicito come deleted
. Queste versioni hanno consentito anche una definizione implicita non conforme dei costruttori di default
copia e spostamento, default
nonché degli operatori di assegnazione di copia e spostamento nelle classi e negli struct con volatile
variabili membro. Il compilatore considera ora questi costruttori e operatori di assegnazione non semplici e non genera default
implementazioni. Quando una classe di questo tipo è un membro di un'unione o un'unione anonima all'interno di una classe, i costruttori di copia e spostamento e copiano e spostano gli operatori di assegnazione dell'unione o della classe vengono definiti in modo implicito come deleted
. Per risolvere questo problema, è necessario dichiarare in modo esplicito le funzioni membro speciali necessarie.
// C2280_variant.cpp
// compile with: cl /c C2280_variant.cpp
struct A {
A() = default;
A(const A&);
};
struct B {
union {
A a;
int i;
};
// To fix this issue, declare the required
// special member functions:
// B();
// B(const B& b);
};
int main() {
B b1;
B b2(b1); // C2280
}
Esempio: Membri di base indiretti eliminati
Le versioni del compilatore precedenti a Visual Studio 2015 Update 2 non erano conformi e consentivano a una classe derivata di chiamare funzioni membro speciali di classi di base derivate indirettamente private virtual
. Il compilatore genera ora l'errore del compilatore C2280 quando viene effettuata una chiamata di questo tipo.
In questo esempio la classe top
deriva indirettamente da una classe virtuale base
privata. Nel codice conforme, in questo modo i membri di base
non sono accessibili a top
; un oggetto di tipo top
non può essere costruito o eliminato definitivamente per impostazione predefinita. Per risolvere questo problema nel codice basato sul comportamento del compilatore precedente, modificare la classe intermedia in modo da usare protected virtual
la derivazione o modificare la classe in modo da usare la top
derivazione diretta:
// C2280_indirect.cpp
// compile with: cl /c C2280_indirect.cpp
class base
{
protected:
base();
~base();
};
class middle : private virtual base {};
// Possible fix: Replace line above with:
// class middle : protected virtual base {};
class top : public virtual middle {}; // C4594, C4624
// Another possible fix: use direct derivation:
// class top : public virtual middle, private virtual base {};
void destroy(top *p)
{
delete p; // C2280
}