Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Why I cann't use dynamic_cast to convert from a non-polymorphic class

162 views
Skip to first unread message

wuguan...@hotmail.com

unread,
Mar 9, 2009, 3:03:24 AM3/9/09
to
Here is the class hierarchy:
class A{};
class B:public A {};
class C:public A{};
class D:public B, public C{};

Then, I compiled the following code,
B* pb = new D;
D* pd = dynamic_cast<D*>(pb);

and got the compiler error C2683: 'cast' : 'type' is not a polymorphic
type.

While I changed the definition of class B as:
class B:public A {void virtual f(){}};

the compiler didn't complain any more.

What is the difference? Why the compiler insist on requiring the the
being casted type polymorphic? Dose the existence of multiple
inheritance make difference in this question?

Martin T.

unread,
Mar 9, 2009, 3:45:41 AM3/9/09
to

It's got nothing to do with multiple inheritance.
As MSDN states: "C2683 ... You cannot use dynamic_cast to convert from a
non-polymorphic class (a class with no virtual functions)."

The reason is that only if an object has a virtual function (and thus a
virtual function table) is the compiler able to generate code to
determine the actual type of the object at runtime. You will also need
to compile with RTTI (run time type information) setting:on (which is
now on by default I think).

br,
Martin

Doug Harrison [MVP]

unread,
Mar 9, 2009, 3:47:22 AM3/9/09
to
On Mon, 9 Mar 2009 00:03:24 -0700 (PDT), wuguan...@hotmail.com wrote:

>Here is the class hierarchy:
>class A{};
>class B:public A {};
>class C:public A{};
>class D:public B, public C{};
>
>Then, I compiled the following code,
>B* pb = new D;
>D* pd = dynamic_cast<D*>(pb);
>
>and got the compiler error C2683: 'cast' : 'type' is not a polymorphic
>type.
>
>While I changed the definition of class B as:
>class B:public A {void virtual f(){}};
>
>the compiler didn't complain any more.
>
>What is the difference? Why the compiler insist on requiring the the
>being casted type polymorphic?

Because them's the rules.

>Dose the existence of multiple
>inheritance make difference in this question?

No.

For this dynamic_cast usage, the type of the source pointer or reference
must be of a class that has at least one virtual function. If it does not
have a virtual function, it is not a polymorphic type, and within the
conceptual model of C++, using dynamic_cast to query the type doesn't make
sense. Practically speaking, it is common for a compiler to attach a
pointer to RTTI data structures to a class's vtbl, and since only classes
that have at least one virtual function have a vtbl, i.e. polymorphic
classes, that's sort of a trivial reason for the requirement.

To understand this more completely, consider what is known in the
statement:

>D* pd = dynamic_cast<D*>(pb);

The compiler knows that pb has the type B* and that B is not polymorphic.
In order to determine if pb points to a base class subobject of a D object,
it has to look up that information somehow. In C++, there is no general
.NET style reflection capability, and objects of non-polymorphic types are
just the bits specified in the class definition. Thus, for the dynamic_cast
to be possible when B isn't polymorphic, the program would have to track
all objects of that type in some sort of registry that maps object
addresses to type information. That's totally against the spirit of C++,
and it isn't done. OTOH, when you give B a virtual function and make it
polymorphic, you're giving the compiler the latitude to do whatever it
needs to enable the behavior expected of polymorphic types. In particular,
the layout of B objects can have extra data to support polymorphism, and
that usually comes in the form of a vptr, or a pointer to the vtbl or
virtual function table for the class. The vtbl is obviously a good place to
add on a pointer to RTTI data structures, and that's what Stroustrup
described in his early writing on the subject. So, when B is polymorphic,
dynamic_cast can get at B's vtbl when passed a B* or B&, thanks to the B
object's vptr, and it can use the RTTI structures pointed to by the vtbl to
determine if the B is part of a D object.

--
Doug Harrison
Visual C++ MVP

Bo Persson

unread,
Mar 9, 2009, 1:10:30 PM3/9/09
to

Adding to this - if the classes have no virtual functions, what is the
use of having a B* point to a derived class anyway?

B* pb = new D; // Doesn't make much sense without virtual functions

Bo Persson


0 new messages