2010-01-31 14 views
8

En struct de C, que es garantizado que:¿Garantías en la dirección de la clase base en C++?

struct Foo { ... }; 
struct Bar { 
    Foo foo; 
    ... 
} 
Bar bar; 
assert(&bar == &(bar.foo)); 

Ahora, en C++, si tengo:

class Foo { ... }; 
class Bar: public Foo, public Other crap ... { 
    ... 
} 

Bar bar; 
assert(&bar == (Foo*) (&bar)); // is this guaranteed? 

Si es así, ¿me puede dar una referencia (como "La programación C++ Idioma, página xyz ")?

Gracias!

Respuesta

10

No hay garantía. Del estándar C++ 03 (10/3, class.derived):

El orden en el que se asignan los subobjetos de clase base en el objeto más derivado (1.8) no está especificado.

+1

anotada; Gracias. :-) g ++ casi me hizo creer que estaba garantizado. – anon

+0

Como nota al margen, la norma promete muy poco sobre el diseño de tipos no POD; básicamente, solo que el orden de direcciones de los miembros de datos no estáticos no separados por un especificador de acceso intermedio coincidirá con el orden de declaración (pero solo dentro de la misma 'sección de especificador de acceso'). –

1

No me lo imagino, no sé por qué tendría que ser así.

Tengo una pregunta relacionada.

si tiene la herencia de diamantes:

class Base(){ virtual void AFunc(){} }; 

class A:Base{}; 
class B:Base{void AFunc(){} } 

class Test:A,B{}; 


Base * b = (Base*)new Test; 

b->AFunc(); 

vamos a suponer que la estructura de memoria es la base de: A: B: Prueba,

nota al punto de llamar, todo el compilador sabe es la dirección del el comienzo del objeto, y AFunc espera estar relacionado con el comienzo del objeto B, ¡estas dos direcciones no serán las mismas! ¿Entonces, cómo funciona?

como si b fue de tipo B, las dos direcciones serían los mismos ...

+0

@matt: Por favor, haga una nueva pregunta. – kennytm

+0

Este es exactamente el ejemplo en 5.4/5 (pero con problemas de accesibilidad adicionales) y está mal formado (se requiere un diagnóstico del compilador). –

6

A pesar de que el diseño de las clases base es not guaranteed en la forma en que parece que ha estado pensando (ya pesar de que hay más garantías para los miembros), esto está garantizado:

Bar bar; 
assert(&bar == (Foo*) (&bar)); 

Debido a que el elenco utiliza un static_cast (por 5,4) que convertirá &bar correctamente, y la comparación entre puntero a la base y triple-a derivados convertirá de manera similar .

Esto, sin embargo, no estaría garantizada:

Bar bar; 
void* p1 = &bar; 
void* p2 = (Foo*)&bar; 
assert(p1 == p2); // not guaranteed 
+0

@Roger: un muy buen punto acerca de las conversiones 'static_cast'. –

Cuestiones relacionadas