Compilerfehler C2280
'Deklaration': Versuch, auf eine gelöschte Funktion zu verweisen
Der Compiler hat versucht, auf eine deleted
Funktion zu verweisen. Dieser Fehler kann durch einen Aufruf einer Memberfunktion verursacht werden, die explizit im = deleted
Quellcode markiert wurde. Dieser Fehler kann auch durch einen Aufruf einer impliziten speziellen Memberfunktion einer Struktur oder Klasse verursacht werden, die automatisch vom Compiler deklariert und gekennzeichnet deleted
wird. Weitere Informationen dazu, wann der Compiler automatisch generiert oder deleted
spezielle Memberfunktionen generiertdefault
, finden Sie unter Special member functions.
Beispiel: Explizit gelöschte Funktionen
Ein Aufruf einer expliziten deleted
Funktion verursacht diesen Fehler. Eine explizite deleted
Memberfunktion impliziert, dass die Klasse oder Struktur absichtlich darauf ausgelegt ist, die Verwendung zu verhindern. Um dieses Problem zu beheben, sollten Sie den Code ändern, um es zu vermeiden.
// 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)
}
Beispiel: Nicht initialisierte Datenmmber
Ein nicht initialisiertes Verweistyp-Datenmemmemm oder const
-member bewirkt, dass der Compiler implizit einen deleted
Standardkonstruktor deklariert. Um dieses Problem zu beheben, initialisieren Sie das Datenelement, wenn es deklariert wird.
// 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
Beispiel: Referenz- und Const-Datenmber
Ein const
oder ein Verweistypdatenmemm bewirkt, dass der Compiler einen deleted
Kopierzuweisungsoperator deklariert. Nach der Initialisierung können diese Member nicht mehr zugewiesen werden, sodass eine einfache Kopie oder Verschiebung nicht mehr funktioniert. Um dieses Problem zu beheben, empfehlen wir, Ihre Logik so zu ändern, dass die Zuordnungsvorgänge entfernt werden, die den Fehler verursachen.
// 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
}
Beispiel: Movable löscht implizite Kopie
Wenn eine Klasse einen Verschiebungskonstruktor oder einen Zuweisungsoperator deklariert, aber nicht explizit einen Kopierkonstruktor deklariert, deklariert der Compiler implizit einen Kopierkonstruktor und definiert ihn als deleted
. Wenn eine Klasse einen Verschiebungskonstruktor oder einen Zuweisungsoperator deklariert, aber nicht explizit einen Kopierzuweisungsoperator deklariert, deklariert der Compiler implizit einen Kopierzuweisungsoperator und definiert ihn als deleted
. Um dieses Problem zu beheben, müssen Sie diese Member explizit deklarieren.
Wenn der Fehler C2280 in Verbindung mit einem unique_ptr
angezeigt wird, ist es fast sicher, weil Sie versuchen, den Kopierkonstruktor aufzurufen, der eine deleted
Funktion ist. Standardmäßig kann ein unique_ptr
Nicht kopiert werden. Verwenden Sie stattdessen einen Verschiebungskonstruktor, um den Besitz zu übertragen.
// 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
}
Beispiel: Variant- und volatile Member
Versionen des Compilers vor Visual Studio 2015 Update 2 waren nicht konform und generierten Standardkonstruktoren und Destruktoren für anonyme Vereinigungen. Diese werden jetzt implizit als deleted
deklariert. Diese Versionen haben auch eine nicht konforme implizite Definition von default
Kopier- und Verschiebungskonstruktoren sowie default
Kopieren und Verschieben von Zuordnungsoperatoren in Klassen und Strukturen mit volatile
Membervariablen zugelassen. Der Compiler betrachtet diese nun als nicht triviale Konstruktoren und Zuordnungsoperatoren und generiert default
keine Implementierungen. Wenn eine solche Klasse Mitglied einer Union ist oder eine anonyme Vereinigung innerhalb einer Klasse ist, werden die Konstruktoren kopieren und verschieben und Zuordnungsoperatoren der Union oder Klasse implizit als deleted
definiert. Um dieses Problem zu beheben, müssen Sie die erforderlichen speziellen Memberfunktionen explizit deklarieren.
// 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
}
Beispiel: Indirekte Basismitglieder gelöscht
Versionen des Compilers vor Visual Studio 2015 Update 2 waren nicht konform und erlaubten einer abgeleiteten Klasse, spezielle Memberfunktionen indirekt abgeleiteter private virtual
Basisklassen aufzurufen. Der Compiler gibt jetzt compilerfehler C2280 aus, wenn ein solcher Aufruf erfolgt.
In diesem Beispiel wird die Klasse top
indirekt von der privaten virtuellen Klasse base
abgeleitet. Im konformen Code kann auf die Elemente nicht base
zugegriffen top
werden; ein Objekt vom Typ top
kann nicht standardmäßig konstruiert oder zerstört werden. Um dieses Problem im Code zu beheben, der auf dem alten Compilerverhalten basiert, ändern Sie die Zwischenklasse, um die Ableitung zu verwenden protected virtual
, oder ändern Sie die Klasse, um die top
direkte Ableitung zu verwenden:
// 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
}