Condividi tramite


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 baseprivata. 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
}