Compartir a través de


Error del compilador C2280

'declaración': se está intentando hacer referencia a una función eliminada

El compilador ha detectado un intento de hacer referencia a una función deleted. Este error puede deberse a una llamada a una función miembro que se ha marcado explícitamente como = deleted en el código fuente. Este error también puede deberse a una llamada a una función miembro especial implícita de una estructura o una clase que el compilador declara y marca automáticamente como deleted. Para obtener más información sobre cuándo el compilador genera automáticamente funciones miembro especiales default o deleted, consulte Funciones miembro especiales.

Ejemplo: Funciones eliminadas explícitamente

Una llamada a una función deleted explícita provoca este error. Una función miembro deleted explícita implica que la clase o la estructura está diseñada intencionadamente para evitar su uso; por tanto, para corregir este problema, debe cambiar el código para 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)
}

Ejemplo: Miembros de datos no inicializados

Un miembro de datos de tipo de referencia no inicializado o const hace que el compilador declare implícitamente un constructor predeterminado deleted. Para corregir este problema, inicialice el miembro de datos cuando se declare.

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

Ejemplo: Miembros de datos de referencia y const

Un miembro de datos de tipo const o de referencia o hace que el compilador declare un operador de asignación de copia deleted. Una vez inicializados, estos miembros no pueden ser objeto de una asignación, por lo que una simple copia o un movimiento no pueden funcionar. Para corregir este problema, se recomienda cambiar la lógica para quitar las operaciones de asignación que provocan el error.

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

Ejemplo: Copia implícita eliminada ante una operación de movimiento

Si una clase declara un constructor de movimiento o un operador de asignación de movimiento, pero no declara explícitamente un constructor de copia, el compilador declara implícitamente un constructor de copia y lo define como deleted. De forma similar, si una clase declara un constructor de movimiento o un operador de asignación de movimiento, pero no declara explícitamente un operador de asignación de copia, el compilador declara implícitamente un operador de asignación de copia y lo define como deleted. Para corregir este problema, debe declarar explícitamente estos miembros.

Cuando aparezca el error C2280 en relación con unique_ptr, es casi seguro que está intentando invocar su constructor de copia, que es una función deleted. Por diseño, unique_ptr no se puede copiar. Use un constructor de movimiento para transferir la propiedad.

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

Ejemplo: Miembros variant y volatile

Las versiones del compilador anteriores a Visual Studio 2015 Update 2 no eran conformes y generaban constructores y destructores predeterminados para uniones anónimas. Ahora se declaran implícitamente como deleted. Esas versiones también permitían la definición implícita no conforme de constructores de copia y movimiento default y operadores de asignación de copia y movimiento default en las clases y estructuras que tienen variables miembro volatile. El compilador ahora considera que estos elementos tienen constructores y operadores de asignación no triviales y no genera implementaciones default. Cuando esta clase es miembro de una unión, o una unión anónima dentro de una clase, los constructores de copia y movimiento, y los operadores de asignación de copia y movimiento de la unión o clase se definen de forma implícita como deleted. Para corregir este problema, debe declarar explícitamente las funciones miembro especiales necesarias.

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

Ejemplo: Miembros base indirectos eliminados

Las versiones del compilador anteriores a Visual Studio 2015 Update 2 no eran conformes y permitían que una clase derivada llamara a funciones miembro especiales de clases base private virtual derivadas indirectamente. El compilador ahora emite el error C2280 cuando se realiza esa llamada.

En este ejemplo, la clase top se deriva indirectamente de la clase base virtual privada. En el código conforme, esto hace que los miembros de base no sean accesibles para top. Un objeto de tipo top no se puede construir ni destruir de forma predeterminada. Para corregir este problema en el código que se basaba en el comportamiento anterior del compilador, cambie la clase intermedia para usar la derivación protected virtual o cambie la clase top para que use la derivación directa:

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