erro: uso de função excluída


121

Tenho trabalhado em alguns códigos C ++ que um amigo escreveu e recebo o seguinte erro que nunca vi antes ao compilar com gcc4.6:

error: use of deleted function

‘GameFSM_<std::array<C, 2ul> >::hdealt::hdealt()’ is implicitly deleted because the default definition would be ill-formed:
uninitialized non-static const member ‘const h_t FlopPokerGameFSM_<std::array<C, 2ul> >::hdealt::h’

Edit: Isso vem de uma parte do código usando boost MSM: Boost Webpage

Edit2: Não é = delete()usado em nenhum lugar no código-fonte.

De modo geral, o que significa esse erro? O que devo procurar quando esse tipo de erro ocorrer?


4
e o código que você está compilando?
— ColWhi

Eu estava mais apenas me perguntando o que significava o erro? Eu preciso postar o código para isso também?
— translado 87 de

1
gcc.gnu.org/bugzilla/show_bug.cgi?id=47417 pode ajudar, você também está usando boost?
— ColWhi

@Sasquiha, sim, estou usando boost MSM.
— translado 87 de

20
Já que isso surge como a primeira correspondência do Google para esse tipo de erro - não é o caso aqui, mas a causa mais comum para esse tipo de erro é depois que você adicionou algum construtor personalizado a uma classe - como resultado, o compilador para de criar o construtor padrão , e se uma instância da classe for criada por meio do construtor padrão, este erro aparecerá. Basta adicionar o construtor padrão explicitamente.
— SF.

Respostas:


170

A mensagem de erro diz claramente que o construtor padrão foi excluído implicitamente . Ele até diz o porquê: a classe contém uma variável const não estática, que não seria inicializada pelo ctor padrão.

class X {
    const int x;
};

Desde X::xé const, ele deve ser inicializado - mas um ctor padrão normalmente não inicializá-lo (porque é um tipo POD). Portanto, para obter um ctor padrão, você precisa definir um (e ele deve inicializar x). Você pode ter o mesmo tipo de situação com um membro que é uma referência:

class X { 
    whatever &x;
};

Provavelmente, vale a pena notar que ambos também desabilitarão a criação implícita de um operador de atribuição, essencialmente pelo mesmo motivo. O operador de atribuição implícita normalmente faz a atribuição de membros, mas com um membro const ou membro de referência, ele não pode fazer isso porque o membro não pode ser atribuído. Para fazer a atribuição funcionar, você precisa escrever seu próprio operador de atribuição.

É por isso que um constmembro normalmente deve ser estático - quando você faz uma atribuição, você não pode atribuir o membro const de qualquer maneira. Em um caso típico, todas as suas instâncias terão o mesmo valor, então elas também podem compartilhar o acesso a uma única variável em vez de ter muitas cópias de uma variável que terá o mesmo valor.

É possível, claro, criar instâncias com valores diferentes - você (por exemplo) passa um valor ao criar o objeto, então dois objetos diferentes podem ter dois valores diferentes. Se, entretanto, você tentar fazer algo como trocá-los, o membro const manterá seu valor original em vez de ser trocado.


@Jeffry Coffin: A mensagem de erro real foi postada como uma edição, a mensagem de erro inicial postada foi apenasC++ error: use of deleted function
— Alok Save

1
@Als: Desculpe, provavelmente eu deveria ter sido explícito que não pretendia isso como um insulto ou qualquer coisa dessa ordem, apenas que o que estava disponível no momento tornava aparente que essas respostas não estavam certas.
— Jerry Coffin

Sem problemas, eu não queria ser inflexível ... Sua resposta é fantástica e explica melhor a situação. +1 de mim :)
— Alok Save

Suponho que você possa me ajudar com meu problema aqui, por favor: stackoverflow.com/questions/23349524/…
— Saher Ahwal

2
@OllieFord: Depende. O que deve acontecer se (por exemplo) você atribuir um objeto com um valor nesse campo a outro que tem um valor diferente nesse campo? Se for substituído, não pode ser constante. Se isso não deveria ser permitido, então o valor pode realmente ser parte do tipo (por exemplo, um parâmetro de modelo, se conhecido em tempo de compilação).
— Jerry Coffin

11

Você está usando uma função marcada como deleted.
Por exemplo:

int doSomething( int ) = delete;

O = delete é um novo recurso do C ++ 0x. Isso significa que o compilador deve parar imediatamente de compilar e reclamar "esta função foi excluída" assim que o usuário usar essa função.

Se você vir esse erro, deve verificar a declaração da função para =delete.

Para saber mais sobre este novo recurso introduzido em C ++ 0x, verifique isto .


7
Por curiosidade, quando fazer algo assim seria útil?
— Pepe de

@Peter: para evitar conversões implícitas.
— R. Martinho Fernandes

7
Na verdade, diz "excluído implicitamente porque ..." , o exemplo acima seria explícito.
— Georg Fritzsche

@Peter R: parece que este é um exemplo: en.wikipedia.org/wiki/…
— shuttle87

1
@Downvoter: A mensagem de erro real foi postada como uma edição, a mensagem de erro inicial postada era apenasC++ error: use of deleted function
— Alok Save

4

gcc 4.6 suporta um novo recurso de funções excluídas, onde você pode escrever

hdealt() = delete;

para desativar o construtor padrão.

Aqui, o compilador obviamente viu que um construtor padrão não pode ser gerado e =deleteo fez para você.


2

Encontrei esse erro ao herdar de uma classe abstrata e não implementar todos os métodos virtuais puros em minha subclasse.


1
Da mesma forma, obtive o mesmo derivando public virtualde uma classe base de 2º nível, onde a classe base de 1º nível tinha um construtor padrão explicitamente excluído. A remoção virtualcorrigiu o problema sem a necessidade de implementar todos os métodos.
— Maitre Bart

1

No padrão C ++ 0x atual, você pode desabilitar explicitamente os construtores padrão com a sintaxe de exclusão, por exemplo

MyClass() = delete;

Gcc 4.6 é a primeira versão a suportar esta sintaxe, então talvez seja esse o problema ...


Gcc 4.6 is the first version to support this syntaxAcho que isso explicaria por que nunca o vi antes, pois comecei a usar o gcc4.6 recentemente.
— translado 87 de

2
Tenho usado essa sintaxe com o GCC 4.5 há anos. Quero dizer dias.
— R. Martinho Fernandes

Ah, devo ter pensado em ctors delegados que estão no GCC 4.6.
— jarmond de

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.