1

Possible Duplicate:
C++ pointer multi-inheritance fun.

(Follow up on: C++ pointer multi-inheritance fun )

I'm writing some code involving inheritance from a basic ref-counting pointer class; and some intricacies of C++ popped up. I've reduced it as follows:

Suppose I have:

class A{int x, y;};
class B{int xx, yy;};
class C: public A, public B {int z;};

C c;
C* pc = &c;
B* pb = &c;
A* pa = &c;

// does pa point to a valid A object?
// does pb point to a valid B object?

// does pa == pb ?

Furthermore, does:

// pc == (C*) pa ?
// pc == (C*) pb ?

Thanks!

Here, "==" means points at the same value.

Community
  • 1
  • 1
anon
  • 41,035
  • 53
  • 197
  • 293
  • The answer is still "not necsarrily." What are you *really* trying to achieve? – John Dibling Jan 28 '10 at 22:37
  • duplicate: http://stackoverflow.com/questions/2157104/c-pointer-multi-inheritance-fun – Bill Jan 28 '10 at 22:39
  • Not quite a duplicate, in this question the classes have members so the answer is different. – Skizz Jan 28 '10 at 23:07
  • @Skizz, as far as the language standard is concerned, the answers are the same. – avakar Jan 28 '10 at 23:13
  • No, according to the standard, the answer to the question `does pa==pb` here is no whereas in the other question the answer is yes. The reason for the answer is the same for both questions - it is what the standard defines. But the questions are (as I read them) about specific cases, not the general rule. Knowing all the rules, the answer to both questions wouldn't be too hard to work out. The rules, however, are not straightforward. Perhaps the questions aren't particularly well thought out. – Skizz Jan 29 '10 at 01:08
  • @Skizz, `pa==pb` is ill-formed in both cases, `(C*)pa==(C*)pb` is `true` in both cases. `(int)pa==(int)pb` is implementation-defined (in both cases). – avakar Jan 29 '10 at 22:18

1 Answers1

3
  • Yes
  • Yes
  • No
  • Yes
  • No*

But you need to know how C++ organises memory. The layout of a class, CClass, is as follows:

offset
0                              First base class in list of base classes
sizeof first base class        Next base class
sizeof first N-1 base classes  Nth base class
sizeof all base classes        CClass

OK, it's a bit more complex than that if there is an inheritance tree, but you should get the basic idea. Assuming an int is four bytes then class C is laid out like:

offset
0             A::x
4             A::y
8             B::xx
12            B::yy
16            C:z

But the an object of type C is all of the above, so a pointer to a C is pointing to offset 0. However, C++ allows implicit downcasting, so a pointer to a C can be converted to a pointer to an A or a pointer to a B. But if you look at the above, a pointer to a B is at offset 8 rather than 0 (a pointer to a C) and that a pointer to an A is at offset 0. So, casting a pointer to a C to a pointer to a B adds 8 to the pointer value. This is because the methods of B assume the 'this' pointer points to B's first member (B::xx), but a pointer to a C if reinterpreted as a pointer to a B (i.e. the value is the same) would be pointer to an address eight bytes before where B actually is, so that all of B's methods would be using, in this instance, A's members.

Upcasting (the final two conversions) is different kettle of fish. Going from a pointer to a B to a pointer to a C is really hard because you don't know if the pointer to a B is just pointing to an instance of B or at an instance of C plus eight. This is where RTTI and the dynamic cast comes in. With RTTI (Run Time Type Information) enabled, the pointer to B contains additional information that describes what B really is - a simple B or a B as part of a C. This does have additional cost, both execution time and memory usage.

Finally, this does highlight the ambiguity of the C style cast. You really should use the C++ style casts (static_cast <>, etc) as this clarifies the way the conversion should be done.

*This could also be a yes, I guess it depends on the compiler and if RTTI is on or off. You would need to get into the details of the standard and the compiler implementation to say for sure.

Skizz
  • 69,698
  • 10
  • 71
  • 108