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 ; top
un 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
}