101
struct A {};

struct B : A {};

int main()
{
    A* a = new B();

    B* b = dynamic_cast<B*>(a);
}

gives:

cannot dynamic_cast 'a' (of type 'struct A*') to type 'struct B*' (source type is not polymorphic)

How can I make A polymorphic? I want to safely cast it to B.

(One way is to add a dummy virtual function, but is there a better way?)

scohe001
  • 15,110
  • 2
  • 31
  • 51
Andrew Tomazos
  • 66,139
  • 40
  • 186
  • 319
  • 5
    If you don't need virtual functions, why do you want polymorphic types? `static_cast` works just fine here. – R. Martinho Fernandes Feb 27 '13 at 14:09
  • 4
    Adding to R. Martinho comment... if you feel that you need to perform casts you might already be in the wrong track. – David Rodríguez - dribeas Feb 27 '13 at 14:12
  • 10
    Virtual destructor for polymorphic type is not dummy - it saves you from UB if you decide to fix your memory leak by writing `delete a;` – Tadeusz Kopec for Ukraine Feb 27 '13 at 14:14
  • @R.MartinhoFernandes: I want it to return `0` if it isnt B. – Andrew Tomazos Feb 27 '13 at 14:15
  • 1
    @user1131467: That is why I said *might already be*... although in general casts tend to indicate flaws in the design. – David Rodríguez - dribeas Feb 27 '13 at 14:39
  • 1
    @TadeuszKopec That's true but the compiler should really complain already at "A* a = new B();" – TamaMcGlinn Aug 03 '18 at 07:54
  • @all above: There are lots of reasons to have polymorphic types without virtual functions. In my case I have a class that returns an event object to a callback handler. This is subclassed depending on what the event is. Some events contain a message (info/warning/error), some events contain a % progress value, and so on. The base class contains a type value so that the handler knows which sub-class to dynamically cast the event to. – AlastairG Jul 07 '23 at 12:26

3 Answers3

146

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.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
16

You need at least a virtual function - typically, if no others are suitable, the destructor:

struct A {
   virtual ~A() {}
}; 
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • I thought I don't need a destructor because the class has no member data. Turns out it needs one, thanks! – Leedehai Jul 20 '18 at 06:50
8

As your compiler says, your type A is not polymorphic. You should add a virtual function to it. For instance, a virtual destructor could be a good choice:

struct A { virtual ~A() { } };
//         ^^^^^^^ This makes A a polymorphic type

struct B : A {};

int main()
{
    A* a = new B();

    B* b = dynamic_cast<B*>(a); // Should work now
}
ChrisF
  • 134,786
  • 31
  • 255
  • 325
Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • I thought I don't need a destructor because the class has no member data. Turns out it needs one, thanks! – Leedehai Jul 20 '18 at 06:50