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 base
inacessí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
}