2010-01-31 4 views
8

In C-Struktur ist, bin ich, dass garantiert:Garantien für die Adresse der Basisklasse in C++?

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

nun in C++, wenn ich:

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

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

Wenn ja, können Sie mir einen Hinweis geben (wie „The C++ Programming Sprache, Seite xyz ")?

Danke!

Antwort

10

Es gibt keine Garantie. Aus dem C++ 03-Standard (10/3, class.ederiviert):

Die Reihenfolge, in der die Basisklassenunterobjekte im abgeleiteten Objekt (1.8) zugeordnet sind, ist nicht angegeben.

+1

Noted;:

Dies würde jedoch nicht garantiert werden, Vielen Dank. :-) g ++ hat mich fast glauben lassen, dass das garantiert war. – anon

+0

Als eine Randnotiz verspricht der Standard nur sehr wenig über das Layout von Nicht-POD-Typen - im Grunde nur, dass die Adressreihenfolge von nicht statischen Datenelementen, die nicht durch einen dazwischenliegenden Zugriffsspezifizierer getrennt sind, der Deklarationsreihenfolge entspricht (aber nur innerhalb von der gleiche "Access-Specifier-Abschnitt"). –

1

Ich kann mir nicht vorstellen, es wäre, ich weiß nicht, warum es sein müsste.

Ich habe eine verwandte Frage.

wenn Sie Diamant-Vererbung:

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

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

class Test:A,B{}; 


Base * b = (Base*)new Test; 

b->AFunc(); 

lässt, dass die Speicherstruktur annehmen, ist Basis: A: B: Test,

Notiz an der Stelle der Aufruf, alle der Compiler weiß, ist die Adresse Der Anfang des Objekts, und AFunc erwartet, relativ zum Anfang des B-Objekts zu sein, diese beiden Adressen werden nicht die gleichen sein! Wie funktioniert es?

wie wenn b vom Typ B ist, die beiden Adressen gleich sein würden ...

+0

@matt: Bitte stellen Sie eine neue Frage. – kennytm

+0

Dies ist genau das Beispiel in 5.4/5 (aber mit zusätzlichen Zugänglichkeitsproblemen) und ist schlecht gebildet (eine Diagnose wird vom Compiler benötigt). –

6

Auch wenn das Layout für Basisklassen not guaranteed in der Art und Weise ist, dass Sie scheinen gedacht zu haben (und auch wenn es mehr Garantien für Mitglieder), ist dies gewährleistet:

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

Da die Besetzung ein static_cast verwendet (je 5,4), die &bar korrekt konvertiert werden, und der Vergleich zwischen pointer-to-Base und pointer-to-derived konvertiert ähnlich .

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

@Roger: Ein sehr guter Punkt über die 'static_cast' Konvertierungen. –