I was writing an operator== between two kinds of smart pointer and thought I should run a quick sanity check. I’m suprised by the result…
In the snippet below how is it that all variants of f and b end up with the same value?
struct Foo {
int x;
};
struct Bar : public Foo {
int y;
};
#include <iostream>
int main ()
{
Bar bar;
Foo * f = &bar;
Bar * b = &bar;
std :: cout << f << " " << b << " " << (f == b) << "\n";
void * fv = f;
void * bv = b;
std :: cout << fv << " " << bv << " " << (fv == bv) << "\n";
int fi = reinterpret_cast <int> (f);
int bi = reinterpret_cast <int> (b);
std :: cout << fi << " " << bi << " " << (fi == bi) << "\n";
}
About the only time that a base class object won’t have the same address as its subclass object is when multiple inheritance is involved.
In the above example memory probably looks like this:
/ --------- \ / | x | > This is the Foo portion of bar This is the whole Bar object < --------- / \ | y | \ ---------Both views of the object have the same starting point, so a pointer to either view will have the same value.
In multiple inheritance, things get more complicated. Say you have:
Now the memory will have to be laid out something like this:
/ --------- \ / | x | > This is the Foo1 portion of bar / --------- / \ This is the whole Bar object < | y | > This is the Foo2 portion of bar \ --------- / \ | z | \ ---------So
&barand(Foo1*)&barwill have the same value, while(Foo2*)&barwill have a different value, since it theFoo2portion of the object starts at a higher address.