La optimización de la base vacía es excelente. Sin embargo, viene con la siguiente restricción:
La optimización de base vacía está prohibida si una de las clases base vacías es también el tipo o la base del tipo del primer miembro de datos no estático, ya que los dos subobjetos base del mismo tipo deben tener direcciones diferentes dentro de la representación del objeto del tipo más derivado.
Para explicar esta restricción, considere el siguiente código. El static_assert
fallará. Mientras que cambiar Foo
o Bar
heredar de en su lugar Base2
evitará el error:
#include <cstddef>
struct Base {};
struct Base2 {};
struct Foo : Base {};
struct Bar : Base {
Foo foo;
};
static_assert(offsetof(Bar,foo)==0,"Error!");
Entiendo este comportamiento completamente. Lo que no entiendo es por qué existe este comportamiento particular . Obviamente se agregó por una razón, ya que es una adición explícita, no un descuido. ¿Cuál es la razón de esto?
En particular, ¿por qué los dos subobjetos básicos deben tener direcciones diferentes? En lo anterior, Bar
es un tipo y foo
es una variable miembro de ese tipo. No veo por qué la clase base de Bar
asuntos importa a la clase base del tipo de foo
, o viceversa.
De hecho, yo, en todo caso, esperaría que &foo
sea la misma que la dirección de la Bar
instancia que lo contiene, como se requiere en otras situaciones (1) . Después de todo, no estoy haciendo nada elegante con la virtual
herencia, las clases base están vacías de todos modos, y la compilación con Base2
muestra que nada se rompe en este caso particular.
Pero claramente este razonamiento es incorrecto de alguna manera, y hay otras situaciones en las que se requeriría esta limitación.
Digamos que las respuestas deberían ser para C ++ 11 o más reciente (actualmente estoy usando C ++ 17).
(1) Nota: EBO se actualizó en C ++ 11, y en particular se convirtió en obligatorio para StandardLayoutType
s (aunque Bar
, arriba, no es a StandardLayoutType
).
Base *a = new Bar(); Base *b = a->foo;
cona==b
, peroa
yb
son objetos claramente diferentes (quizás con anulaciones de métodos virtuales diferentes).