Guarantees on address of baseclass in C++?
Asked Answered
C

3

8

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!

Competence answered 31/1, 2010 at 6:16 Comment(0)
A
10

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.

Assimilable answered 31/1, 2010 at 6:28 Comment(2)
Noted; thanks. :-) g++ almost made me believe that was guaranteed.Competence
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').Pliers
M
6

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
Morrissey answered 31/1, 2010 at 6:37 Comment(1)
@Roger: A very good point about the static_cast conversions.Assimilable
M
1

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...

Mouthwash answered 31/1, 2010 at 6:33 Comment(2)
@matt: Please ask a new question.Andersonandert
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).Morrissey

© 2022 - 2024 — McMap. All rights reserved.