Why does upcasting a child pointer to a base class sometimes change the pointer value?
<p>I found a few other questions that seem to implicate my question, but none directly answered it (even <a href="https://stackoverflow.com/questions/37548982/c-pointer-value-changes-with-static-cast">the one</a> with almost the same name).</p>

<p>I have a C++ child class derived from two parents. I create an object of that class, then cast its reference to each of its two parents. The cast values are not the same, though one remains the value of the child reference. Here's the code:</p>

<pre class="lang-cpp prettyprint-override"><code>class Mom
{
public:
    int a = 1;
};

class Dad
{
public:
    int b = 2;
};

class Child : public Mom, public Dad
{
public:
    int c = 3;
};

int main()
{
    Child* c = new Child; // 0x00C5A618

    Mom* m = c; // 0x00C5A618
    Dad* d = c; // 0x00C5A61C

    return 0;
}
</code></pre>

<p>Now, I am guessing that the addresses obtained by applying static_cast&lt;> are those of the actual subobjects. As it happens, <code>Mom</code> is the first subobject, so it actually has the same address as <code>Child</code>. <code>Dad</code> is the second subobject, so it resides at a different address.</p>

<p>As I understand it, C-style casts, like this</p>

<pre class="lang-cpp prettyprint-override"><code>Mom* m = (Mom*)c;
Dad* d = (Dad*)c;
</code></pre>

<p>will apply a static_cast&lt;> when it would be legal to do so. Indeed, when I actually compile and execute that version, I see the same behavior as before.</p>

<p>Continuing this scintillating saga, using implicit casts, like this</p>

<pre class="lang-cpp prettyprint-override"><code>Mom* m = c;
Dad* d = c;
</code></pre>

<p>exhibit the same behavior as well, from which I infer that implicit casts also apply static_cast&lt;> when the equivalent explicit cast would be legal.</p>

<p>Downcasting back to <code>Child</code> does the same thing:</p>

<pre><code>Child* k = static_cast&lt;Child*&gt;(d); // 0x00C5A618
</code></pre>

<p>The value in <code>k</code> is different from the value in <code>d</code>, having been set back to the value originally in <code>c</code>.</p>

<p>I am guessing that, in this case, there is a run-time check to see if, indeed, <code>d</code> points to a <code>Dad</code> subobject of a <code>Child</code> object.</p>

<p>So far, this all makes sense, but I'm surprised that there is no such address adjustment (if that's the right thing to call it) for singly derived hierarchies. That is, if my hierarchy is simply <code>Mom</code>-><code>Dad</code>-><code>Child</code>, casting a reference to a <code>Child</code> into a pointer to either a <code>Mom</code> or a <code>Dad</code> never changes the value:</p>

<pre><code>class Mom
{
public:
    int a = 1;
};

class Dad : public Mom
{
public:
    int b = 2;
};

class Child : public Dad
{
public:
    int c = 3;
};

int main()
{
    Child* c = new Child; // 0x00C5A618

    Mom* m = c; // 0x00C5A618
    Dad* d = c; // 0x00C5A618

    Child* k = static_cast&lt;Child*&gt;(d); // 0x00C5A618

    return 0;
}
</code></pre>

<p>I'd have expected it to change by the size of the the storage needed for each additional subclass, or four bytes (the size of an int). But, they don't. All of the pointers in the above example, <code>c</code>, <code>m</code>, <code>d</code>, and <code>k</code>, have the same value.</p>

<p>So, now I am guessing that the objects were laid out in memory with the <code>Mom</code> object at the lowest address, the <em>additional</em> space needed for the <code>Dad</code> object coming next, and the <em>additional</em> space needed for the <code>Child</code> coming last. Since a <code>Dad</code> is-a <code>Mom</code>, the <code>Dad</code> address would be the same as the <code>Mom</code> address, wouldn't it?</p>

<p>Likewise, a <code>Child</code> is-a <code>Mom</code> too, so its address would also be the same as its own <code>Mom</code> subobject's address.</p>

<p>So...</p>

<p>I think it is working like this: in memory, the objects follow each other such that, in purely singly derived hierarchy, upcasting and downcasting always yields the same address, while in a multiply derived hierarchy, some upcasts yield a different address, because not all subobjects will start at the same address as the derived object. Like this:</p>

<pre><code>Possible Memory Layout for a Singly Derived Hierarchy

+-------+-----+-----+---+
| Child : Dad : Mom : a |
|       |     +-----+---+
|       |           : b |
|       +-----------+---+
|                   : c |
+-----------------------+


Possible Memory Layout for a Multiply Derived Hierarchy

+-------+-----+---+
| Child : Mom : a |
|       +-----+---+
|       : Dad : b |
|       +-----+---+
|             : c |
+-----------------+
</code></pre>

<p>Sorry that I've rambled a bit, but my question is this: is the fact that an upcast to some base classes of a multiply derived object changes the value of the reference a result of the fact that the post-cast value is the address of the base object in memory?</p>