Re: Problem with multiple inheritance
In article news:<fm68q4lm5d13p4id9gi75u5iucv72me112@4ax.com>, Joseph M.
Newcomer wrote:
{
mySecondObject = (C *)myObject;
mySecondObject->I_Am_From_C();
}
}
****
This cannot possibly work, and I'm surprised that you think it would.
You have a pointer to a possible ABC, then you tell it to interpret
that as a pointer to a C object. That is complete nonsense. If you
look at an A object, I can show all the methods of A as [A]
[A]
an AB has additional information
[A][B]
an ABC has yet more
[A][B][C]
so what you said was "I have a pointer to the collection of
information laid out as [A][B][C] now please interpret that pointer
as being a pointer to [C]" so what you get is the structure of a C
object imposed upon the structure [A][B][C], so OF COURSE you get
nonsense. In multiple inheritance, you cannot do this kind of cast
because it makes no sense at all.
I'm sure you didn't mean that quite as it came out ... there's a real
risk of confusing the OP even further than he clearly already is.
Yes, as you say, an ABC has information laid out as [A][B][C] in memory,
while an A object has just [A] and a C object has just [C].
If you have a pointer to an ABC object and you cast that to a pointer to
a C object the compiler does behind-the scenes magic to obtain the
address of the [C] data within the [A][B][C], and returns that as a
useful C* pointer. This is not nonsense, it does work, and is part of
the language -- I'm sure you know this, Joe, but your post seemed to me
to be saying that it was not so.
What the OP is doing that is wrong is to try to cast an A* pointer (NOT
an ABC*) to be a pointer to a C object, and he compounds this sin by
using a C-style cast. Because there is no inheritance relationship
between A and C the compiler treats this as a C++ reinterpret_cast so
the resulting code has the effect of addressing the [A] data in memory
as though it were a [C] -- this IS nonsense, and can only fail.
Note that if the OP had used a C++ dynamic_cast<C*> rather than a
C-style cast the compiler would have reported an error rather than
generating nonsense code -- a good example of the reasons to prefer C++
casts. In fact, in this simple conversion of a pointer-to-full-class to
a pointer-to-subclass you don't even need the cast.
ABC * pointer_to_ABC = new ABC( ... );
C * pointer_to_C = pointer_to_ABC;
compiles (with the correct meaning) without a cast.
Imagine that A held three variables all of which were 1, B held
three variables, all of which were 2, and C held three variables,
all of which were 3.
In memory you would have
[1 1 1][2 2 2][3 3 3]
in an ABC object, that is. Yes.
what your cast tells the compiler to do is to assume that the
structure is a C, so if you look at the fields of C, which you expect
to see as [3 3 3] you instead see [1 1 1].
No, it's a little more complicated than you put it ... because he starts
with an A* pointer (although it points to an ABC object) what his code
does is first to tell the compiler that the pointer points only to [1 1
1]. He then tries to cast that to a C* -- gets reinterpret_cast
behaviour because he's casting between unrelated types (A* and C*) --
and ends up trying to read the fields of the A part of the ABC structure
as though they were the fields of the C part.
Yes, as you say, the end result is that the [1 1 1] of the A part of the
structure is seen where the [3 3 3] of the C part is expected.
What the OP seems to me not to understand is that if you declare a
pointer as an A* the compiler will always treat it as a pointer to an A
object. The compiler cannot know that in this case it actually points to
the A object within an ABC object.
If you cast the object as an ABC*, THEN you would see the expected
layout, and your code would work.
Yes ... the OP's problem seems to be that he has some objects that are
ABs and some that are ABCs and wants to handle them polymorphically
through A* pointers. The OP needs a (typesafe) way to find out whether
his A* actually points to an AB or an ABC object.
RTTI is the answer to that, as others have said.
Cheers,
Daniel.