Compartilhar via


Erro do compilador C2280

'declaration': tentativa de fazer referência a uma função excluída

O compilador detectou uma tentativa de fazer referência a uma função deleted. Esse erro pode ser causado por uma chamada para uma função membro que foi explicitamente marcada como = deleted no código-fonte. Esse erro também pode ser causado por uma chamada para uma função membro especial implícita de um struct ou classe que é declarada automaticamente e marcada como deleted pelo compilador. Para obter mais informações sobre quando o compilador gera automaticamente funções de membro especiais default ou deleted, consulte funções de membro especiais.

Exemplo: funções explicitamente excluídas

Uma chamada para uma função explicitamente deleted causa esse erro. Uma função de membro explicitamente deleted implica que a classe ou struct foi intencionalmente projetado para impedir seu uso; portanto, para corrigir esse problema, você deve alterar o código para evitá-lo.

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

Exemplo: membros de dados não inicializados

Um membro de dados de tipo de referência não inicializado, ou um membro de dados const, faz com que o compilador declare implicitamente um construtor padrão deleted. Para corrigir esse problema, inicialize o membro de dados quando ele for declarado.

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

Exemplo: membros de dados de referência e const

Um const ou membro de dados de tipo ou referência faz com que o compilador declare um operador de atribuição de cópia deleted. Depois de inicializados, esses membros não podem ser atribuídos, portanto, uma cópia ou movimentação simples não pode funcionar. Para corrigir esse problema, recomendamos que você altere sua lógica para remover as operações de atribuição que causam o erro.

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

Exemplo: item a ser movido exclui cópia implícita

Se uma classe declarar um construtor de movimentação ou um operador de atribuição de movimentação, mas não declarar explicitamente um construtor de cópia, o compilador declara implicitamente um construtor de cópia e o define como deleted. De forma análoga, se uma classe declarar um construtor de movimentação ou um operador de atribuição de movimentação, mas não declarar explicitamente um operador de atribuição de cópia, o compilador declara implicitamente um operador de atribuição de cópia, e o define como deleted. Para corrigir esse problema, você deve declarar explicitamente esses membros.

Quando você vir o erro C2280 em conexão com um unique_ptr, muito provavelmente é porque você está tentando invocar o construtor de cópia, que é uma função deleted. Por padrão, um unique_ptr não pode ser copiado. Em vez disso, use um construtor de movimentação para transferir a propriedade.

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

Exemplo: membros variantes e voláteis

As versões do compilador anteriores ao Visual Studio 2015 Atualização 2 não estavam em conformidade, e geravam construtores e destruidores padrão para uniões anônimas. Agora eles são declarados implicitamente como deleted. Essas versões também permitiram a definição implícita não conforme de construtores de cópia e movimentação default e operadores de atribuição de cópia e movimentação default em classes e structs que têm variáveis de membro volatile. O compilador agora considera que eles têm construtores e operadores de atribuição não triviais, e não gera implementações default. Quando uma classe como essa for um membro de uma união (ou uma união anônima dentro de uma classe), os construtores de cópia e movimentação e os operadores de atribuição de cópia e movimentação da união ou classe serão implicitamente definidos como deleted. Para corrigir esse problema, você deve declarar explicitamente as funções de membro especiais necessárias.

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

Exemplo: membros indiretos da base excluídos

As versões do compilador antes do Visual Studio 2015 Atualização 2 não estavam em conformidade, e permitiam que uma classe derivada chamasse funções de membro especiais de classes base derivadas indiretamente private virtual. O compilador agora emite o erro do compilador C2280 quando essa chamada é feita.

Neste exemplo, a classe top deriva indiretamente do base virtual privado. No código de conformidade, isso torna os membros de baseinacessíveis a top; um objeto de tipo top não pode ser construído ou destruído por padrão. Para corrigir esse problema no código que se baseava no antigo comportamento do compilador, altere a classe intermediária para usar a derivação protected virtual, ou altere a classe top para usar a derivação direta:

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