views:

93

answers:

3

In C struct's, I'm guaranteed that:

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

Now, in C++, if I have:

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

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

If so, can you give me a reference (like "The C++ Programming Language, page xyz")?

Thanks!

+7  A: 

There is no guarantee. From the C++03 standard (10/3, class.derived):

The order in which the base class subobjects are allocated in the most derived object (1.8) is unspecified.

James McNellis
Noted; thanks. :-) g++ almost made me believe that was guaranteed.
anon
As a side note, the standard promises very little about the layout of non-POD types - basically only that the address order of non-static data members not separated by an intervening access-specifier will match the order of declaration (but only within the same 'access-specifier section').
Michael Burr
A: 

I don't imagine it would be, I don't know why it would need to be.

I have a related question.

if you have diamond inheritance:

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

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

class Test:A,B{};


Base * b = (Base*)new Test;

b->AFunc();

lets assume that memory structure is Base:A:B:Test,

note at the point of calling, all the compiler knows is the address of the beginning of the object, and AFunc is expecting to be relative to the beginning of the B object, these two addresses won't be the same! so how does it work?

like if b was of type B, the two addresses would be the same...

matt
@matt: Please ask a new question.
KennyTM
This is exactly the example in 5.4/5 (but with additional accessibility issues) and is ill-formed (a diagnostic is required from the compiler).
Roger Pate
+4  A: 

Even though layout for base classes is not guaranteed in the way you seem to have been thinking (and even though there are more guarantees for members), this is guaranteed:

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

Because the cast uses a static_cast (per 5.4) which will convert &bar correctly, and the comparison between pointer-to-base and pointer-to-derived will convert similarly.

This, however, would not be guaranteed:

Bar bar;
void* p1 = &bar;
void* p2 = (Foo*)&bar;
assert(p1 == p2); // not guaranteed
Roger Pate
@Roger: A very good point about the `static_cast` conversions.
James McNellis