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_ptrangezeigt 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 deleteddeklariert. 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 deleteddefiniert. 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 baseabgeleitet. Im konformen Code kann auf die Elemente nicht base zugegriffen topwerden; 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
}