TITLE: Casting and memory layout PROBLEM: st@mlc-ratingen.de (Stefan Tilkov) Given the following code: class A { ... }; class B { ... }; class C : public A, public B { ... }; ... C Object; the compiler I use (HP C++/HP 9000) generates code such that &Object == (A*)&Object is true. The memory layout seems to the one described as 'normal' in the ARM. Is the result of the above expression guaranteed to be true? RESPONSE: bs@alice.att.com (Bjarne Stroustrup), AT&T Bell Laboratories Actually, that comparison is guaranteed to be true, but that says nothing about the memory layout. The expression &Object == (A*)&Object is non-zero because to compare a C* (the type of &Object) with an A* you must convert the C* to an A*. Consequently, &Object == (A*)&Object means (A*)&Object == (A*)&Object which it trivially true. I think what was meant was: Is (void*)&Object == (void*)(A*)&Object ? Translated into English ``is the address of an object the same as the address of its first base class? The answer to that question is implementation dependent. In other words: ``maybe.'' Don't depend on that in portable code. An implementation may add data in front of its first base or decide to place the second base before the first. Use a virtual function and you don't have to ask layout questions: class A { public: virtual void f(); void g(); }; class B { public: virtual void h(); void k(); }; class C : public A, public B { public: void f(); void h(); void m(); }; C obj; void x1() { A* p = &obj; // note that you don't have to cast // to get to an accessible base class A* p2 = (A*)&obj; // redundant cast p->f(); // invoke C::f p->m(); // error: A has no m() } void x2() // unwise and non-portable use: { A* p = (A*)(void*)&obj; // brute force: pretend the // beginning of a C is an A // any use of p to access members // is implementation dependent } Usually, the real problem is how to get back to a C* once you have only a void* or an A* that you know points to a C: void x3(void* p) // p points to a C { C* pc = (C*)p; // ok if you are sure that you have a C A* pa = pc; // ok, points to C's A A* pa2 = (A*)p; // non-portable if p points to a C } void x3(A* p) // p points to a C { C* pc = (C*)p; // ok if p points to a C } Another interesting question is what to do if you only know that a void* or an A* might point to a C and want to find out if it really does. For a discussion of this question see sec13.5 and the section on run-time type information in the ANSI/ISO resolution chapter of ``The C++ Programming Language (2nd edition)'' or sec14.2 of ``The Design and Evolution of C++.'' An example: void x4(A* p) // p might point to a C { if (C* pc = dynamic_cast(p)) { // p points to a C // you can use pc here } else { // p didn't point ot a C // you can't use pc here } } ``Coming soon in a compiler near you''