Topic: casting and virtual inheritence


Author: cardboard.mti.sgi.com!box.mti.sgi.com!sgi.sgi.com!ncar.UCAR.EDU!uunet!chatz!chatz (David Chatterton)
Date: 1996/02/08
Raw View
Hi,

There is very little on virtual inheritence in the draft. I cannot find nay
statement saying that you cannot do this:

class A {};
class B : public virtual A {};

int main()
{
    A* a1 = new A;
    A* a2 = new B;
    B* b1 = (B *)A; // Illegal due to virtual inheritence
    return 0;
}

Yet g++ and cfront won't let you. However, g++ (2.7.0) will let you do this:

    B* b1 = dynamic_cast<B*>(A);

Why can't you force the cast to a B (I guess it has to do with the virtual
tables)? And is g++ correct in allowing dynamic_cast to do it?

Thanks,

David
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy is
  in http://reality.sgi.com/employees/austern_mti/std-c++/policy.html. ]





Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1996/02/09
Raw View
In article 9ej@fido.asd.sgi.com, cardboard.mti.sgi.com!box.mti.sgi.com!sgi.sgi.
com!ncar.UCAR.EDU!uunet!chatz!chatz (David Chatterton) writes:
>
>There is very little on virtual inheritence in the draft. I cannot find nay
>statement saying that you cannot do this:
>
>class A {};
>class B : public virtual A {};
>
>int main()
>{
>    A* a1 = new A;
>    A* a2 = new B;
>    B* b1 = (B *)A; // Illegal due to virtual inheritence
>    return 0;
>}

In the current draft standard, section 5.4 "Explicit type conversion (cast
notation)" lists exactly those conversions which may be performed, and
down-casting from a virtual base class is not among them.

In the ARM, section 5.4 "Explicit Type Conversion" says about the same
thing, the difference being that the four new cast keywords were not
in the language at that time.

In other words, the cast noted above has never been allowed in C++, and
still is not.

>Yet g++ and cfront won't let you. However, g++ (2.7.0) will let you do this:
>
>    B* b1 = dynamic_cast<B*>(A);

>Why can't you force the cast to a B (I guess it has to do with the virtual
>tables)? And is g++ correct in allowing dynamic_cast to do it?

Dynamic_cast was created specifically to allow safe down-casting, and in
particular allows you to down-cast pointers or references from a virtual
base class to a derived class. The only requirement is that the base class
have one or more virtual functions. See section 5.2.6 "Dynamic cast" in the
current draft.

---
Steve Clamage, stephen.clamage@eng.sun.com
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  Moderation policy:
  http://reality.sgi.com/employees/austern_mti/std-c++/policy.html. ]





Author: jodle@bix.com (jodle)
Date: 1996/02/09
Raw View
David Sachs (b91926@fsgm01.fnal.gov) wrote:
: First of all, I think (B*A) or dynamic_cast<B*>(A) is not a valid
: expression, because A is a type name rather than a variable name. I
: assume you meant dynamic_cast<B*>(a1)... In this case the semantics
: are:

: class A {};
: class B : public virtual A {};

: int main()
: {
:     A* a1 = new A;
:     A* a2 = new B;
:     B* b1 = dynamic_cast<B*>(a1);  // b1 == NULL, because there is no B
:     B* b2 = dynamic_cast<B*>(a2);  // points to a2 as a B
:     return 0;
: }

I think the question "why?" remains unanswered.  The answer itself is
quite simple.  If B virtually inherits A, each object instantiated from
class B contains (or acts as if it contains) a pointer to the base class A
part of itself.  It is not possible to downcast from an A to a B because
we have no way of knowing for sure where the supposed B associated with A
really is.  To illustrate, the data parts of our B might looks something
like this:

class B
  {
  A *virtualBaseClassA;
  };

In contrast, if we have nonvirtual inheritance we (may, depending on the
compiler) know that A and B both have the same address (but different
sizes) in memory.  This looks something more like:

class B
  {
  A nonvirtualBaseClassA;
  };

I don't view downcasting as the best thing to do, generally.  I have to
say that the cast operators at least give us a way to do it that allows us
to detect when the cast didn't work.  Without them, downcasting just gives
you a pointer to some stuff that may or may not be what you think it
should be.
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  Moderation policy:
  http://reality.sgi.com/employees/austern_mti/std-c++/policy.html. ]