Getting "Source Type Is Not Polymorphic" When Trying to Use Dynamic_Cast

Getting source type is not polymorphic when trying to use dynamic_cast

You need to make A polymorphic, which you can do by adding a virtual destructor or any virtual function:

struct A {
virtual ~A() = default;
};

or, before C++11,

struct A {
virtual ~A() {}
};

Note that a polymorphic type should have a virtual destructor anyway, if you intend to safely call delete on instances of a derived type via a pointer to the base.

Can't downcast because class is not polymorphic?

Syntax errors non-withstanding, you cannot dynamic_cast a non-polymorphic type. static_cast is the cast you would use in this case, if you know that it is in fact an object of the target type.

The reason why: static_cast basically has the compiler perform a check at compile time "Could the input be cast to the output?" This is can be used for cases where you are casting up or down an inheritance hierarchy of pointers (or references). But the check is only at compile time, and the compiler assumes you know what you are doing.

dynamic_cast can only be used in the case of a pointer or reference cast, and in addition to the compile time check, it does an additional run time check that the cast is legal. It requires that the class in question have at least 1 virtual method, which allows the compiler (if it supports RTTI) to perform this additional check. However, if the type in question does not have any virtual methods, then it cannot be used.

The simplest case, and probably worthwhile if you're passing pointers around like this, is to consider making the base class's destructor virtual. In addition to allowing you to use dynamic cast, it also allows the proper destructors to be called when a base class pointer is deleted.

The reason why dynamic_cast doesn't work with non-polymorphic types

Because there is no way to implement dynamic_cast without some type information stored in the object for run-time use. And there are only two features of the language which need a run-time information on the object's type: virtual functions, and dynamic_cast.

If it was possible to use dynamic_cast to downcast non-polymorphic types, compliers would have to store run-time type information in every class type. This would go directly against the "only pay for what you use" philosophy of C++, and it would utterly break its compatibility with C and many external interfaces, hardware etc. There would be no standard-layout class types, basically. Or, alternatively, no class types where you could have full control of their layout.

Cannot dynamic cast when using dynamic_pointer_cast

The compiler is telling you what is going on at the end of the message:

(source type is not polymorphic)

Your Event base class needs to have at least one virtual member function (i.e. be a polymorphic type) in order to allow dynamic casts. You could make the destructor of Event virtual:

class Event
{
public:
virtual ~Event() { /* whatever goes here, or nothing... */ }
// ...
};

Here is a live example with polymorphic types, showing that the code compiles (removing the virtual destructor would cause a compilation error similar to the one you are seeing).

As correctly mentioned by Luc Danton in the comments, a defaulted version of a virtual destructor can be defined this way (if your compiler is C++11-compliant in this respect):

class Event
{
public:
virtual ~Event() = default;
// ...
};

(C++) should'nt this dynamic_cast retrieve the derived class

For dynamic_cast<> to work, the object needs to have a vtable. Otherwise, there is no indication within the object to which dynamic class it belongs.

A vtable is added to a C++ class if, and only if that class contains at least one virtual function.

So, add at least one virtual function to the class, and the dynamic cast should work.

C++ dynamic_cast - polymorphic requirement and downcasting

From 5.2.7/1 [expr.dynamic.cast] :

The result of the expression dynamic_cast<T>(v) is the result of converting the expression v to type
T.

[...]

If T is "pointer to cv1 B" and v has type "pointer to cv2 D" such that B is a base class of D, the result is a
pointer to the unique B sub-object of the D object pointed to by v.

[...]

Otherwise, v shall be a pointer to or an lvalue of a polymorphic type.

The standard even provides the following example which illustrates that the polymorphic type requirement does not stand for derived to base conversion :

struct B {};
struct D : B {};
void foo(D* dp)
{
B* bp = dynamic_cast<B*>(dp); // equivalent to B* bp = dp;
}

C++: ... is not a polymorphic type while using boost::dynamic_pointer_cast

dynamic_cast works ONLY with polymorphic class. And polymorphic class is that which has atleast one virtual function, even be it the destructor.

//polymorphic classes
struct A
{
virtual ~A(); //even virtual destructor makes a class polymorphic!
};
struct B : A
{
void f();
};

//non-polymorphic classes
struct C
{
~C(); //not virtual
};

struct D : C
{
void f(); //not virtual either
};

In the above code, A and B are polymorphic classes, but C and D are not.

A *pA = new B();
B *pB = dynamic_cast<B*>(pA); //okay

C *pC = new D();
D *pD = dynamic_cast<D*>(pC); //error - not polymorphic class

Note that in dynamic_cast, only the source type need to be polymorphic in order to compile. If the destination isn't polymorphic, then dynamic_cast will return null pointer.

D *pD = dynamic_cast<D*>(pA);  //okay - source (pA) is polymorphic

if ( pD )
cout << "pD is not null" ;
else
cout << "pD is null";

Output:

pD is null

Online demo: https://web.archive.org/web/20000000000000/http://www.ideone.com/Yesxc



Related Topics



Leave a reply



Submit