¿Por qué una función virtual pura se inicializa con 0?

147

Siempre declaramos una función virtual pura como:

virtual void fun () = 0 ;

Es decir, siempre se asigna a 0.

Lo que entiendo es que esto es para inicializar la entrada vtable para esta función a NULL y cualquier otro valor aquí resulta en un error de tiempo de compilación. ¿Es este entendimiento correcto o no?

mukeshkumar
fuente
12
Tenga en cuenta que vtable no es un requisito de idioma, sino solo una opción de implementación para métodos virtuales. Un compilador podría crear la misma abstracción con una implementación diferente (es decir, sin vtable y sin ningún elemento que sea 0)
David Rodríguez - dribeas
@hype Re su pregunta complementaria: eso es lo que dice mi respuesta (y varias otras).
Sólo por curiosidad, ¿qué ocurre si doy, virtual void func() = 100;
krithikaGopalakrisnan

Respuestas:

161

La razón que =0se usa es que Bjarne Stroustrup no creía que pudiera obtener otra palabra clave, como "puro" más allá de la comunidad C ++ en el momento en que se implementó la función. Esto se describe en su libro, The Design & Evolution of C ++ , sección 13.2.3:

Se eligió la sintaxis curiosa = 0 ... porque en ese momento no vi ninguna posibilidad de que se aceptara una nueva palabra clave.

También declara explícitamente que esto no necesita establecer la entrada vtable en NULL, y que hacerlo no es la mejor manera de implementar funciones virtuales puras.


fuente
44
Sí, es solo sintaxis. He visto muchos proyectos que #definen PURE = 0 y dirán virtual void Foo () PURE;
i_am_jorf
79
Por favor, Dios, mantenme alejado de esos proyectos :-)
27
Es mucho menos peor que #define BEGIN {#define END} ;-) y lo he visto a veces.
Toon Krijthe
55
Este tipo de cosas ingeniosas me hacen pensar que C ++ no está muy pulido. Es extraño teniendo en cuenta que se usa mucho. Espero que el idioma sea mejor con el paso de los días.
jokoon 01 de
19
Entonces, en otras palabras, Bjarne "se enfrentó a una fecha límite" y "usó un truco" para superar un "defecto de diseño";) (Solo siendo gracioso)
Carl
78

Al igual que con la mayoría de las preguntas "Por qué" sobre el diseño de C ++, el primer lugar para buscar es El diseño y la evolución de C ++ , de Bjarne Stroustrup 1 :

La =0sintaxis curiosa se eligió sobre la alternativa obvia de introducir una nueva palabra clave pureo abstractporque en ese momento no vi ninguna posibilidad de que se aceptara una nueva palabra clave. Si hubiera sugerido pure, la versión 2.0 se habría enviado sin clases abstractas. Dada la posibilidad de elegir entre una sintaxis más agradable y clases abstractas, elegí clases abstractas. En lugar de arriesgarse a retrasar e incurrir en ciertas peleas pure, usé la convención tradicional C y C ++ de usar 0 para representar "no está allí". La =0sintaxis se ajusta a mi punto de vista de que un cuerpo de función es el inicializador de una función también con la vista (simplista, pero generalmente adecuada) del conjunto de funciones virtuales que se implementan como un vector de punteros de función. [...]

1 §13.2.3 Sintaxis

Jerry Coffin
fuente
29

La sección 9.2 del estándar C ++ proporciona la sintaxis para los miembros de la clase. Incluye esta producción:

pure-specifier:
    = 0

No hay nada especial sobre el valor. "= 0" es solo la sintaxis para decir "esta función es puramente virtual". No tiene nada que ver con la inicialización o los punteros nulos o el valor numérico cero, aunque la similitud con esas cosas puede tener un valor mnemónico.

Kristopher Johnson
fuente
55
+1 para referirse al estándar C ++. Es sorprendente que sea una de las mejores respuestas posibles y que solo haya obtenido 1 voto hasta ahora. Leer el estándar debería ser el primer paso para resolver las preguntas de C ++.
mloskot
77
@mloskot: ¿tal vez porque no responde la pregunta del OP, solo reafirma la situación?
solo alguien
66
@just alguien - Incluye la cita estándar que establece cuál es la sintaxis de la declaración de función virtual pura y que la sintaxis usa un especificador puro = 0¿Qué más le gustaría saber? Sería lo mismo que preguntar por qué el cuerpo de la función está envuelto con {} La respuesta sería, porque eso es lo que define la sintaxis de C ++.
mloskot
19

No estoy seguro de si hay algún significado detrás de esto. Es solo la sintaxis del lenguaje.

Cquillen
fuente
16

C ++ siempre ha evitado introducir nuevas palabras clave, ya que las nuevas palabras reservadas rompen los viejos programas que usan estas palabras para identificadores. A menudo se ve como una de las fortalezas del lenguaje que respeta el código antiguo en la medida de lo posible.

La = 0sintaxis podría haber sido elegida, ya que se asemeja a establecer una entrada vtable 0, pero esto es puramente simbólico. (La mayoría de los compiladores asignan tales entradas vtable a un código auxiliar que emite un error antes de abortar el programa). La sintaxis se eligió principalmente porque no se usó para nada antes y se guardó al introducir una nueva palabra clave.

sbi
fuente
3
+1 por explicar la desventaja de introducir una nueva palabra clave. Es útil entender la razón, pero la sintaxis de C ++ me parece absurdamente complicada y me gustaría que la hubieran hecho más legible para los humanos: una purepalabra clave habría sido excelente en mi libro. De todos modos, es bueno entender la lógica.
Keith Pinson
@KeithPinson Si quieres una palabra clave pura, puedes hacerlo #define pure = 0.
jdh8
@ jdh8: Ugh. Solo ... Ugh.
sbi
Como nota al margen, en una clase con Bjarne dijo que realmente quería obtener la palabra clave "pura" en C ++ ... pero trató de obtenerla muy tarde en el ciclo antes de que se enviara el compilador de C ++ (IIRC menos de dos semanas). Aparentemente, no logró entrar.
ThePhD
@ThePhD: ISTR también dice esto en algún lugar de D&E. (Sin embargo, soy demasiado vago para buscarlo).
sbi
11

C ++ debe tener una manera de distinguir una función virtual pura de una declaración de una función virtual normal. Eligieron usar la = 0sintaxis. Podrían haber hecho lo mismo fácilmente agregando una palabra clave pura. Pero C ++ es bastante reacio a agregar nuevas palabras clave y prefiere usar otros mecanismos para introducir características.

JaredPar
fuente
2
-0: cuando no tenga nada sustancial que decir por su cuenta, use una cita extensa (vea la respuesta de Jerry Coffin para +1;)
solo alguien
7

Nada es "inicializado" o "asignado" cero en este caso. = 0en solo una construcción sintáctica que consiste en =y0 tokens, que no tiene absolutamente ninguna relación con la inicialización o la asignación.

No tiene ninguna relación con ningún valor real en "vtable". El lenguaje C ++ no tiene noción de "vtable" o algo así. Varias "vtables" no son más que simples detalles de implementaciones específicas.

Hormiga
fuente
3

Recuerdo haber leído que la justificación de la sintaxis divertida era que era más fácil (en términos de aceptación de estándares) que introducir otra palabra clave que hiciera lo mismo.

Creo que esto fue mencionado en The Design and Evolution of C ++ por Bjarne Stroustrup.

luke
fuente
2

Supongo que esto es solo parte de la gramática de C ++. No creo que haya restricciones sobre cómo los compiladores realmente implementan esto para un formato binario específico dado. Su suposición probablemente era la correcta para los primeros compiladores de C ++.

rui
fuente
2

El = 0declara una función virtual pura .

Lo que se entiende es que esto es para inicializar la entrada vtable para esta función a NULL y cualquier otro valor aquí resulta en un error de tiempo de compilación

No creo que sea verdad. Es solo una sintaxis especial. La vtable está definida por la implementación. Nadie dice que una entrada vtable para un miembro puro se debe poner a cero en la construcción (aunque la mayoría de los compiladores manejan vtables similares).

Alexander Gessler
fuente
44
Eso en realidad no es cierto. No hay nada de malo en proporcionar una definición para una función virtual pura. Lo único que = 0hace es que toda la clase sea abstracta y prohíbe las llamadas virtuales a funciones puras. Las llamadas no virtuales siguen siendo perfectamente correctas, que es cuando se utiliza la definición (si proporcionó una).
ANT
Solo mira la salida de godbolt. No hay lugar para la ambigüedad o la especulación. Lo echaré un vistazo más tarde
Lewis Kelsey
Parece que reemplaza la entrada con __cxa_pure_virtual arobenko.gitbooks.io/bare_metal_cpp/content/compiler_output/… en lugar de Base :: f ()
Lewis Kelsey
1

Bueno, también puede inicializar la entrada vtable para apuntar a una función real "

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

Parece intuitivo que la entrada vtable se puede definir para que no apunte a ninguna parte (0) o a una función. Permitirle especificar su propio valor probablemente resultaría en que apunte a basura en lugar de a una función. Pero es por eso que "= 0" está permitido y "= 1" no. Sospecho que Neil Butterworth tiene razón sobre por qué se usa "= 0"

Brian
fuente
1
Incluso tuve una opinión similar, pero dado que muchos han citado los estándares y los comentarios de Bjarne sobre el mismo, tenemos pocas posibilidades de discusión :)
mukeshkumar 02 de