Por que uma função virtual pura é inicializada por 0?

147

Sempre declaramos uma função virtual pura como:

virtual void fun () = 0 ;

Ou seja, é sempre atribuído a 0.

O que eu entendo é que isso é para inicializar a entrada vtable para esta função como NULL e qualquer outro valor aqui resulta em um erro de tempo de compilação. Esse entendimento está correto ou não?

mukeshkumar
fonte
12
Observe que o vtable não é um requisito de idioma, mas apenas uma opção de implementação para métodos virtuais. Um compilador poderia criar o mesmo abstração com uma implementação diferente (isto é, sem vtable, e sem qualquer elemento que haja 0)
David Rodríguez - dribeas
@ hype Re sua pergunta complementar - é o que diz minha resposta (e várias outras).
Estou curioso para virtual void func() = 100;
saber o

Respostas:

161

O motivo =0é usado porque Bjarne Stroustrup não achou que poderia obter outra palavra-chave, como "puro" após a comunidade C ++ no momento em que o recurso estava sendo implementado. Isso é descrito em seu livro The Design & Evolution of C ++ , seção 13.2.3:

A sintaxe curiosa = 0 foi escolhida ... porque na época eu não via chance de obter uma nova palavra-chave aceita.

Ele também afirma explicitamente que isso não precisa definir a entrada vtable como NULL e que isso não é a melhor maneira de implementar funções virtuais puras.


fonte
4
Sim, é apenas sintaxe. Eu já vi muitos projetos que # definem PURE = 0 e eles dizem virtual void Foo () PURE;
precisa saber é o seguinte
79
Por favor, Deus, me manter longe desses projectos :-)
27
É muito menos pior do que #define BEGIN {#define END} ;-) e já vi isso algumas vezes.
precisa saber é o seguinte
5
Esse tipo de coisa bacana me faz pensar que o C ++ não é muito polido. É estranho, considerando que é muito usado. Espero que o idioma melhore com o passar dos dias.
jokoon
19
Então, em outras palavras, Bjarne foi "confrontado com um prazo" e "usou um truque" para passar uma "falha de design";) (Apenas sendo jocoso)
Carl
78

Como na maioria das perguntas "Por que" sobre o design do C ++, o primeiro lugar para procurar é O design e a evolução do C ++ , de Bjarne Stroustrup 1 :

A =0sintaxe curiosa foi escolhida em detrimento da alternativa óbvia de introduzir uma nova palavra pure- chave ou abstractporque, na época, não havia chance de aceitar uma nova palavra-chave. Se eu sugerisse pure, o Release 2.0 seria enviado sem classes abstratas. Dada a escolha entre uma sintaxe mais agradável e as classes abstratas, escolhi as classes abstratas. Em vez de arriscar atrasar e incorrer em certas brigas pure, usei a tradição C e C ++ de usar 0 para representar "não existe". A =0sintaxe se ajusta à minha visão de que um corpo de função é o inicializador de uma função também com a visão (simplista, mas geralmente adequada) do conjunto de funções virtuais sendo implementadas como um vetor de ponteiros de função. [...]

1 §13.2.3 Sintaxe

Jerry Coffin
fonte
29

A seção 9.2 do padrão C ++ fornece a sintaxe para os alunos. Inclui esta produção:

pure-specifier:
    = 0

Não há nada de especial no valor. "= 0" é apenas a sintaxe para dizer "esta função é pura virtual". Não tem nada a ver com inicialização ou ponteiros nulos ou com o valor numérico zero, embora a semelhança com essas coisas possa ter valor mnemônico.

Kristopher Johnson
fonte
5
+1 por se referir ao padrão C ++. É um pouco surpreendente que uma das melhores respostas possíveis e tenha recebido apenas 1 voto até agora. A leitura do padrão deve ser o primeiro passo para resolver questões de C ++.
mloskot
7
@mloskot: talvez porque não responda à pergunta do OP, apenas reafirme a situação?
apenas alguém
6
@just alguém - Inclui a citação padrão que declara qual é a sintaxe da declaração pura de função virtual e que a sintaxe usa puro especificador = 0O que mais você gostaria de saber? Seria o mesmo que perguntar por que o corpo da função está envolvido com {} A resposta seria, porque é isso que a sintaxe C ++ define.
mloskot
19

Não tenho certeza se há algum significado por trás disso. É apenas a sintaxe do idioma.

cquillen
fonte
16

O C ++ sempre evitou a introdução de novas palavras-chave, pois novas palavras reservadas quebram programas antigos que usam essas palavras para identificadores. É frequentemente visto como um dos pontos fortes da linguagem que respeita o código antigo, tanto quanto possível.

A = 0sintaxe pode realmente ter sido escolhida, pois se assemelha a definir uma entrada de tabela 0, mas isso é puramente simbólico. (A maioria dos compiladores atribui essas entradas do vtable a um esboço que emite um erro antes de interromper o programa.) A sintaxe foi escolhida principalmente porque não havia sido usada antes e economizou a introdução de uma nova palavra-chave.

sbi
fonte
3
+1 por explicar a desvantagem de introduzir uma nova palavra-chave. Isso é útil para entender o raciocínio, mas a sintaxe do C ++ parece absurdamente complicada para mim e eu gostaria que eles o tornassem mais legível para humanos - uma purepalavra - chave teria sido ótima em meu livro. Enfim, é bom entender a lógica.
Keith Pinson
@ KeithPinson Se você quiser uma palavra-chave pura, pode #define pure = 0.
Jdh8 26/03
@ jdh8: Ugh. Apenas ... Ugh.
SBI
Como observação, em uma aula com Bjarne, ele disse que realmente queria inserir a palavra-chave "pura" no C ++ ... mas tentou inseri-la muito tarde no ciclo antes do envio do compilador C ++ (IIRC menos de duas semanas). Aparentemente, ele não chegou.
ThePhD 27/03
@ ThePhD: ISTR ele também diz isso em algum lugar de D&E. (Eu sou muito preguiçoso para procurá-lo, no entanto.)
SBI
11

O C ++ deve ter uma maneira de distinguir uma função virtual pura de uma declaração de uma função virtual normal. Eles escolheram usar a = 0sintaxe. Eles poderiam facilmente fazer o mesmo adicionando uma palavra-chave pura. Mas o C ++ é bastante relutante em adicionar novas palavras-chave e prefere usar outros mecanismos para introduzir recursos.

JaredPar
fonte
2
-0: quando você não tem nada substancial para dizer por si mesmo, use uma citação extensa (veja a resposta de Jerry Coffin em +1;)
alguém alguém
7

Nada é "inicializado" ou "atribuído" zero neste caso. = 0em apenas uma construção sintática que consiste em =e0 tokens, que não tem absolutamente nenhuma relação com a inicialização ou a atribuição.

Não tem relação com nenhum valor real em "vtable". A linguagem C ++ não tem noção de "vtable" ou algo assim. Várias "vtables" nada mais são do que apenas detalhes de implementações específicas.

Formiga
fonte
3

Lembro-me de ler que a justificativa para a sintaxe engraçada era que era mais fácil (em termos de aceitação de padrões) do que introduzir outra palavra-chave que faria a mesma coisa.

Acredito que isso foi mencionado em The Design and Evolution of C ++ por Bjarne Stroustrup.

Lucas
fonte
2

Eu diria que isso é apenas parte da gramática C ++. Eu não acho que haja restrições sobre como os compiladores realmente implementam isso para um determinado formato binário específico. Sua suposição provavelmente estava certa para os compiladores C ++ do início do dia.

rui
fonte
2

O = 0declara uma função virtual pura .

O que se entende é que isso é para inicializar a entrada vtable desta função para NULL e qualquer outro valor aqui resulta em erro de tempo de compilação

Eu não acho que seja verdade. É apenas uma sintaxe especial. A vtable é definida pela implementação. Ninguém diz que uma entrada vtable para um membro puro deve ser zerada na construção (embora a maioria dos compiladores manipule vtables semelhantes).

Alexander Gessler
fonte
4
Na verdade, isso não é verdade. Não há nada de errado em fornecer uma definição para uma função virtual pura. A única coisa que = 0faz é tornar toda a classe abstrata e proibir chamadas virtuais para funções puras. As chamadas não virtuais ainda estão perfeitamente bem, ou seja, quando a definição (se você forneceu uma) for usada.
AnT
Basta olhar para a saída godbolt. Não há espaço para ambiguidade ou especulação. Vou me dar uma olhada mais tarde
Lewis Kelsey
Parece que substitui a entrada por __cxa_pure_virtual arobenko.gitbooks.io/bare_metal_cpp/content/compiler_output/… em vez de Base :: f ()
Lewis Kelsey
1

Bem, você também pode inicializar a entrada vtable para apontar para uma função real "

 virtual void fun()
 {
     //dostuff()
 }

Parece intuitivo que a entrada vtable possa ser definida para apontar para lugar nenhum (0) ou para uma função. Permitir que você especifique seu próprio valor para ele provavelmente resultaria em apontar para lixo em vez de para uma função. Mas é por isso que "= 0" é permitido e "= 1" não é. Eu suspeito que Neil Butterworth esteja certo sobre o porquê de "= 0" ser usado

Brian
fonte
1
Mesmo que eu tinha opinião semelhante, mas uma vez que muitas normas citei e os comentários feitos por Bjarne na mesma, temos chances mínimas de argumento :)
mukeshkumar