Dela via


Kompilatorfel C2280

"deklaration": försöker referera till en borttagen funktion

Anmärkningar

Kompilatorn upptäckte ett försök att referera till en deleted funktion. Det här felet kan orsakas av ett anrop till en medlemsfunktion som uttryckligen har markerats som = deleted i källkoden. Det här felet kan också orsakas av ett anrop till en implicit särskild medlemsfunktion i en struct eller klass som automatiskt deklareras och markeras som deleted av kompilatorn. Mer information om när kompilatorn automatiskt genererar default eller deleted särskilda medlemsfunktioner finns i Särskilda medlemsfunktioner.

Exempel: Uttryckligen borttagna funktioner

Ett anrop till en explicit deleted funktion orsakar det här felet. En explicit deleted medlemsfunktion innebär att klassen eller structen avsiktligt är utformad för att förhindra dess användning, så för att åtgärda det här problemet bör du ändra koden för att undvika det.

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

Exempel: Uninitialiserade datamedlemmar

En oinitialiserad referenstyp som datamedlem eller const som datamedlem gör att kompilatorn implicit deklarerar en deleted standardkonstruktor. Åtgärda problemet genom att initiera datamedlemmen när den deklareras.

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

Exempel: Referens- och const-datamedlemmar

En const datamedlem eller referenstyp gör att kompilatorn deklarerar en deleted kopieringstilldelningsoperator. När de har initierats kan de här medlemmarna inte tilldelas till, så en enkel kopia eller flytt kan inte fungera. För att åtgärda det här problemet rekommenderar vi att du ändrar logiken för att ta bort tilldelningsåtgärderna som orsakar felet.

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

Exempel: Flyttning tar bort implicit kopia

Om en klass deklarerar en flyttkonstruktor eller flytttilldelningsoperator, men inte uttryckligen deklarerar en kopieringskonstruktor, deklarerar kompilatorn implicit en kopieringskonstruktor och definierar den som deleted. Om en klass deklarerar en flyttkonstruktor eller flytttilldelningsoperator, men inte uttryckligen deklarerar en kopieringstilldelningsoperator, deklarerar kompilatorn implicit en kopieringstilldelningsoperator och definierar den som deleted. För att åtgärda det här problemet måste du uttryckligen deklarera dessa medlemmar.

När du ser felet C2280 i anslutning till en unique_ptrberor det nästan säkert på att du försöker anropa dess kopieringskonstruktor, som är en deleted funktion. En unique_ptr kan inte kopieras. Använd en flyttkonstruktor för att överföra ägarskap i stället.

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

Exempel: Variant och volatila medlemmar

Versioner av kompilatorn före Visual Studio 2015 Update 2 var icke-kompatibla och genererade standardkonstruktorer och destruktorer för anonyma fackföreningar. Dessa deklareras nu implicit som deleted. Dessa versioner tillät också icke-standard implicit definition av default kopierings- och flyttkonstruktorer och default kopierings- och flyttilldelningsoperatorer i klasser och strukturer som har volatile medlemsvariabler. Kompilatorn anser nu att dessa har icke-triviala konstruktorer och tilldelningsoperatorer och genererar default inte implementeringar. När en sådan klass är medlem i en union, eller en anonym union i en klass, definieras kopierings- och flyttkonstruktörer samt kopierings- och flyttassigneringsoperatorer för unionen eller klassen implicit som deleted. För att åtgärda det här problemet måste du uttryckligen deklarera de särskilda medlemsfunktioner som krävs.

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

Exempel: Indirekta basmedlemmar har tagits bort

Versioner av kompilatorn före Visual Studio 2015 Update 2 var icke-överensstämmande och tillät en härledd klass att anropa särskilda medlemsfunktioner för indirekt härledda private virtual basklasser. Kompilatorn utfärdar nu kompilatorfelet C2280 när ett sådant anrop görs.

I det här exemplet härleds klassen top indirekt från privata virtuella base. I enlighet med kod, gör detta medlemmarna i base otillgängliga för top. Ett objekt av typen top kan inte skapas eller förstöras som standard. Åtgärda det här problemet i kod som förlitade sig på det gamla kompilatorbeteendet genom att ändra mellanklassen så att den använder protected virtual härledning eller ändra klassen så att den top använder direkt härledning:

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