Delen via


Compilerfout C2280

'declaratie': een poging om te verwijzen naar een verwijderde functie

Opmerkingen

De compiler heeft een poging gedetecteerd om te verwijzen naar een deleted functie. Deze fout kan worden veroorzaakt door een aanroep van een lidfunctie die expliciet is gemarkeerd als = deleted in de broncode. Deze fout kan ook worden veroorzaakt door een aanroep naar een impliciete speciale lidfunctie van een struct of klasse die automatisch wordt gedeclareerd en gemarkeerd als deleted door de compiler. Zie Speciale lidfuncties voor meer informatie over wanneer de compiler automatisch functies genereert default of deleted speciale lidfuncties.

Voorbeeld: Expliciet verwijderde functies

Een aanroep van een expliciete deleted functie veroorzaakt deze fout. Een expliciet deleted lidfunctie impliceert dat de klasse of struct opzettelijk is ontworpen om het gebruik ervan te voorkomen. U kunt dit probleem dus oplossen door de code te wijzigen om dit te voorkomen.

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

Voorbeeld: Niet-geïnitialiseerde gegevensleden

Een niet-geïnitialiseerd verwijzingstype gegevenslid of const gegevenslid zorgt ervoor dat de compiler impliciet een deleted standaardconstructor declareert. U kunt dit probleem oplossen door het gegevenslid te initialiseren wanneer het wordt gedeclareerd.

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

Voorbeeld: Leden van referentie- en constgegevens

Een const of verwijzingstypegegevenslid zorgt ervoor dat de compiler een deleted operator voor kopieertoewijzing declareert. Zodra deze leden zijn geïnitialiseerd, kunnen deze leden niet worden toegewezen, zodat een eenvoudige kopie of verplaatsing niet kan werken. U kunt dit probleem oplossen door de logica te wijzigen om de toewijzingsbewerkingen te verwijderen die de fout veroorzaken.

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

Voorbeeld: Movable verwijdert impliciete kopie

Als een klasse een verplaatsingsconstructor of een toewijzingsoperator voor verplaatsen declareert, maar niet expliciet een kopieerconstructor declareert, declareert de compiler impliciet een kopieerconstructor en definieert deze als deleted. Als een klasse een verplaatsingsconstructor declareert of een toewijzingsoperator verplaatst, maar niet expliciet een operator voor een kopieertoewijzing declareert, declareert de compiler impliciet een operator voor de kopieertoewijzing en definieert deze als deleted. U kunt dit probleem oplossen door deze leden expliciet te declareren.

Wanneer u de fout C2280 in verband met een unique_ptrziet, is het bijna zeker omdat u de copy-constructor probeert aan te roepen. Dit is een deleted functie. Een kan standaard unique_ptr niet worden gekopieerd. Gebruik in plaats daarvan een verplaatsingsconstructor om het eigendom over te dragen.

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

Voorbeeld: Variant- en vluchtige leden

Versies van de compiler vóór Visual Studio 2015 Update 2 waren niet-conform en gegenereerde standaardconstructors en destructors voor anonieme vakbonden. Deze worden nu impliciet gedeclareerd als deleted. In deze versies is ook niet-conforme impliciete definitie van default kopieer- en verplaatsingsconstructors toegestaan en default operatoren voor het kopiëren en verplaatsen van toewijzingen in klassen en structs met volatile lidvariabelen. De compiler beschouwt deze nu als niet-triviale constructors en toewijzingsoperatoren en genereert default geen implementaties. Wanneer een dergelijke klasse lid is van een samenvoeging of een anonieme samenvoeging binnen een klasse, worden de kopieer- en verplaatsingsconstructors en operatoren voor het kopiëren en verplaatsen van toewijzingen van de samenvoeging of klasse impliciet gedefinieerd als deleted. U kunt dit probleem oplossen door expliciet de vereiste speciale lidfuncties te declareren.

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

Voorbeeld: Indirecte basisleden verwijderd

Versies van de compiler vóór Visual Studio 2015 Update 2 waren niet-conform en gaven een afgeleide klasse toestemming om speciale lidfuncties van indirect afgeleide private virtual basisklassen aan te roepen. De compiler geeft nu compilerfout C2280 op wanneer een dergelijke aanroep wordt gedaan.

In dit voorbeeld is klasse top indirect afgeleid van privé virtueel base. Als u code conformeert, kunnen de leden van base dit type niet toegankelijk topzijn; een object van het type top kan niet standaard worden geconstrueerd of vernietigd. Als u dit probleem wilt oplossen in code die afhankelijk is van het oude compilergedrag, wijzigt u de tussenliggende klasse om afleiding te gebruiken protected virtual of wijzigt u de top klasse zodat deze directe afleiding gebruikt:

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