Domande frequenti: perché dynamic_cast funziona solo se una class ha almeno un metodo virtuale?

Questo non si compila in C ++:

class A { }; class B : public A { }; ... A *a = new B(); B *b = dynamic_cast(a); 

Poiché dynamic_cast può solo tipi polimorfi downcast, così dice lo standard.

Puoi rendere la tua class polimorfica aggiungendo un distruttore virtual alla class base. In effetti, probabilmente dovresti comunque (Vedi nota). Altrimenti se si tenta di eliminare un object B attraverso un puntatore A , si evocherà il comportamento non definito .

 class A { public: virtual ~A() {}; }; 

et voilà!

Nota

Esistono eccezioni alla “regola” relativa alla necessità di un distruttore virtuale in tipi polimorfici.
Una tale eccezione è quando si utilizza boost::shared_ptr come indicato da Steve Jessop nei commenti seguenti. Per ulteriori informazioni su quando hai bisogno di un distruttore virtuale, leggi questo articolo di Herb Sutter .

Come diceva l’altro: lo standard dice così.

Quindi, perché lo standard dice così?

Perché se il tipo non è polimorfico può (o è? Domanda ai guru standard) essere un tipo semplice. E per i tipi semplici ci sono molti presupposti derivanti dalla retrocompatibilità C. Uno di questi è che il tipo consiste solo di membri mentre lo sviluppatore dichiara + necessari byte di allineamento. Quindi non ci possono essere campi extra (nascosti). Quindi non c’è modo di memorizzare nello spazio di memoria conservato da A l’informazione che è davvero un B.

Questo è ansible solo quando è polimorfico, poiché è permesso aggiungere cose nascoste. (Nella maggior parte delle implementazioni ciò avviene tramite il vtable).

Da 5.2.7 (fusione dynamic):

Il risultato dell’espressione dynamic_cast(v) è il risultato della conversione dell’espressione v nel tipo T.

[… più righe che si riferiscono ad altri casi …]

Altrimenti v deve essere un puntatore a o un lvalue di un tipo polimorfico (10.3).

Da 10.3 (funzioni virtuali):

Una class che dichiara o eredita una funzione virtuale è chiamata class polimorfica.