Veamos el diseño de clase de los dos casos.
Sin lo virtual, tiene dos clases base ("X" y "Y") con un entero cada una, y cada una de esas clases ha integrado en ellas una clase base "Base" que también tiene un número entero. Eso es 4 enteros, 32 bits cada uno, totalizando sus 16 bytes.
Offset Size Type Scope Name
0 4 int Base a
4 4 int X x
8 4 int Base a
12 4 int Y y
16 size (Z members would come at the end)
(Editar:. He escrito un programa en DJGPP para obtener el diseño y ajustado la mesa para dar cuenta de ello)
Ahora vamos a hablar de las clases base virtuales: los que sustituyen la instancia actual de la clase con un puntero a una instancia compartida. Su clase "Z" tiene solo una clase "Base", y ambas instancias de "X" e "Y" apuntan a ella. Por lo tanto, tiene números enteros en X, Y y Z, pero solo tiene la Z. Eso significa que tiene tres enteros o 12 bytes. Pero X e Y también tienen un puntero a la Z compartida (de lo contrario, no sabrían dónde encontrarla). En una máquina de 32 bits, dos punteros agregarán 8 bytes adicionales. Esto suma los 20 que ves. El diseño de memoria podría ser algo como esto (no he verificado que ... El brazo tiene un ejemplo donde el orden es X, Y, Z, entonces Base):
Offset Size Type Scope Name Value (sort of)
0 4 Base offset X ? 16 (or ptr to vtable)
4 4 int X x
8 4 Base offset Y ? 16 (or ptr to vtable)
12 4 int Y y
16 4 int Base a
20 size (Z members would come before the Base)
Así que la diferencia de memoria es una combinación de dos cosas: un entero menos y dos punteros más. Al contrario de otra respuesta, no creo que los vtables paguen ninguna (edición) directa (/ edición) en esto, ya que no hay funciones virtuales.
Editar: ppinsider ha proporcionado más información sobre el caso gcc, en el que demuestra que gcc implementa el puntero a la clase base virtual haciendo uso de un vtable vacío (es decir, sin funciones virtuales). De esa forma, si hubiera funciones virtuales, no requeriría un puntero adicional en la instancia de la clase, lo que requeriría más memoria. Sospecho que la desventaja es una indirección adicional para llegar a la clase base.
Podríamos esperar que todos los compiladores hicieran esto, pero quizás no. La ARM página 225 discute clases base virtuales sin mencionar vtables. La página 235 aborda específicamente "clases base virtuales con funciones virtuales" y tiene un diagrama que indica un diseño de memoria donde hay punteros de las partes X e Y que están separadas de los punteros a la tabla virtual. Aconsejaría a cualquiera que no dé por sentado que el puntero a Base se implementará en términos de una tabla.
Mark, ¿cómo generó ese diseño? –
Si se refiere al formato de tabla, es solo código. Solo adiviné el contenido. Editaré mi respuesta con más detalles y una referencia a la respuesta de ppinsider. – markets
disfruté leyéndolo. gracias +1 –