EDIT: Following a comment by dribeas, I did some further research and it turns out that my main conclusion was incorrect. It turns out that the standard states in 5.4.7 that C-style casts can actually do more than any sequence of new-style casts can do -- specifically including casting from a pointer-to-derived to pointer-to-base even when the base class is inaccessible, which is precisely what happens here with private inheritance. (Why this should be allowed, and in particular why it should be allowed only for C-style casts, is utterly beyond me; but it's undeniably allowed.)
So dribeas is right, compilers are obliged to handle the OP's C-style pointer conversion correctly, even when B
inherits from multiple base classes. My own testing with MSVC++8 and MinGW confirms his results in practice -- when B
inherits from multiple base classes, the compiler will adjust pointers when converting a B*
to an A*
or vice versa so that the correct object or subobject is identified.
I stand by my assertion that you ought to derive B
publicly from A
if you ever intend to treat a B
as an A
, since using private inheritance instead necessitates using C-style casts.
The original (somewhat incorrect) answer appears below.
Ultimately, if you want to be able to treat a B
as an A
, you need to derive B
publicly from A
. Using C-style casts may work sometimes on some architectures and with some compiler versions, but it's simply an unportable hack that's liable to break at any time (e.g. when turning on compiler optimisations).
As an example of a case that will definitely break on all compilers I know of, if B
was actually specified as follows:
class B : public X, private A { ... }; // X is any other class
Then the following code:
A* aPtr3 = (A*)bPtr1;
Will point aPtr3
at the wrong subobject of bPtr1
, leading to crashes as soon as a member is accessed or a virtual method is called. (The C-style cast will be converted to a reinterpret_cast
because no valid conversion using static_cast
or dynamic_cast
is available, meaning that aPtr3
will be assigned the same memory address held in bPtr1
-- but because multiple inheritance is in effect, the A
subobject contained in *bPtr1
is not located at the same memory adress as bPtr1
.)
The moral of the story is that deriving a class privately from another class does not specify an is-a relationship. It's probably best not to think of it as inheritance at all.