Partager via


Erreur du compilateur C2280

'déclaration' : tentative de référence d’une fonction supprimée

Le compilateur a détecté une tentative de référencer une deleted fonction. Cette erreur peut être due à un appel à une fonction membre qui a été explicitement marquée comme = deleted dans le code source. Cette erreur peut également être provoquée par un appel à une fonction membre spéciale implicite d’un struct ou d’une classe qui est automatiquement déclaré et marqué comme deleted par le compilateur. Pour plus d’informations sur le moment où le compilateur génère default automatiquement ou deleted des fonctions membres spéciales, consultez Fonctions membres spéciales.

Exemple : fonctions supprimées explicitement

Un appel à une fonction explicitement deleted provoque cette erreur. Une fonction membre explicite deleted implique que la classe ou le struct est intentionnellement conçu pour empêcher son utilisation, afin de résoudre ce problème, vous devez modifier votre code pour l’éviter.

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

Exemple : membres de données non initialisés

Un membre de données de type de référence non initialisé ou const un membre de données entraîne la déclaration implicite du compilateur d’un deleted constructeur par défaut. Pour résoudre ce problème, initialisez le membre de données lorsqu’il est déclaré.

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

Exemple : référencer et const data members

Un const membre de données de type référence ou de type provoque le compilateur à déclarer un opérateur d’affectation deleted de copie. Une fois initialisés, ces membres ne peuvent pas être affectés. Par conséquent, une copie ou un déplacement simple ne peut pas fonctionner. Pour résoudre ce problème, nous vous recommandons de modifier votre logique pour supprimer les opérations d’affectation qui provoquent l’erreur.

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

Exemple : Les suppressions mobiles suppriment la copie implicite

Si une classe déclare un constructeur de déplacement ou un opérateur d’affectation de déplacement, mais ne déclare pas explicitement un constructeur de copie, le compilateur déclare implicitement un constructeur de copie et le définit comme deleted. De même, si une classe déclare un constructeur de déplacement ou un opérateur d’affectation de déplacement, mais ne déclare pas explicitement un opérateur d’assignation de copie, le compilateur déclare implicitement un opérateur d’affectation de copie et le définit comme deleted. Pour résoudre ce problème, vous devez déclarer explicitement ces membres.

Lorsque vous voyez l’erreur C2280 en relation avec un unique_ptr, c’est presque certainement parce que vous tentez d’appeler son constructeur de copie, qui est une deleted fonction. Par conception, une unique_ptr copie ne peut pas être effectuée. Utilisez plutôt un constructeur de déplacement pour transférer la propriété.

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

Exemple : membres variants et volatiles

Les versions du compilateur antérieures à Visual Studio 2015 Update 2 étaient non conformes et générées par des constructeurs et des destructeurs par défaut pour les unions anonymes. Ceux-ci sont désormais déclarés implicitement comme deleted. Ces versions ont également autorisé la définition implicite non conforme des constructeurs de default copie et de déplacement, ainsi default que les opérateurs d’affectation de copie et de déplacement dans les classes et les structs qui ont volatile des variables membres. Le compilateur considère maintenant qu’il s’agit de constructeurs et d’opérateurs d’affectation non trivials et ne génère default pas d’implémentations. Lorsqu’une telle classe est membre d’une union ou d’une union anonyme à l’intérieur d’une classe, les constructeurs de copie et de déplacement et les opérateurs d’affectation de copie et de déplacement de l’union ou de la classe sont implicitement définis comme deleted. Pour résoudre ce problème, vous devez déclarer explicitement les fonctions membres spéciales requises.

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

Exemple : les membres de base indirects supprimés

Les versions du compilateur antérieures à Visual Studio 2015 Update 2 étaient non conformes et permettaient à une classe dérivée d’appeler des fonctions membres spéciales de classes de base dérivées private virtual indirectement. Le compilateur émet maintenant l’erreur du compilateur C2280 lorsqu’un tel appel est effectué.

Dans cet exemple, la classe top dérive indirectement de virtual privé base. Dans le code conforme, cela rend les membres base inaccessibles ; topun objet de type top ne peut pas être construit ou détruit par défaut. Pour résoudre ce problème dans le code qui s’appuyait sur l’ancien comportement du compilateur, modifiez la classe intermédiaire pour utiliser protected virtual la dérivation ou modifiez la top classe pour utiliser la dérivation directe :

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