http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53225
--- Comment #7 from Jonathan Wakely <redi at gcc dot gnu.org> 2012-05-04 18:31:31 UTC --- (In reply to comment #6) > So for example, if an parent class has a method, say increment(), that affects > a value to be found in a field at offset, say, 4. and then that parent method > is inherited into the child, but the inherited field has moved, say now found > at offset 8, the method is modified to access offset 8 - or to more > technically accurate its type information is modified, the control flow > remains > identical. No, that's not how it works. If Base::increment() writes to Base::field then it is always at the same offset into the Base object. Whether that Base object is a sub-object of another clas is irrelevant. In your broken example on stackoverflow the "A::operator new" function always wrote to offset 4 into the A object. When that A object is 4 bytes into a B object then it writes 4+4=8, but "A::operator new" knows that A::count is 4 bytes into an A, i.e. this+4 where this has type A* > So yes, inheritance means a lot of copying and modifications are done to > _type_ > at _compile_time_. After all this work is done at compile time, in static > typing, the type is embedded in the generated code, the unresolved part of > type > is embedded as symbols to be linked in the link map, and the rest is thrown > away. For some reason, this embedding for the inherited operator new is > incorrect. No, your understanding of how G++ works is incorrect. That might be a valid C++ implementation, but it's not how G++ works, and it's certainly not required to work like that by the standard. You seem to think that in "A::operator new" the static type of "this" depends on whether the dynamic type of the object being allocated is A or B. That's incorrect. The static type of "*this" in "A::operator new" is always A, and that's why your program doesn't work. When you use "A::operator new" to allocate a B, the member B::count will be 8 bytes into the allocated memory, but you cast the memory to (this_type*) i.e. (A*) and then access A::count, i.e. 4 bytes into the allocated memory. When you later construct a B at that location the B::count member is not at the location you thought it was.