2010-09-28 14 views
5

Per esempio Ho codice come quelloÈ possibile dynamic_cast da una classe base all'altra?

class Base1 
{ 
    virtual void wonderFULL() = 0; 
}; 

class Base2 
{ 
    // all this weird members 
}; 

class Derived : public Base1, public Base2 
{ 
    // not so weird members 
}; 

int main() 
{ 
    Derived Wonder; 
    magicFunction(&Wonder); 
    return 0; 
} 

void magicFunction(Base2 *ptr) 
{ 
    if (Base1 *b1 = dynamic_cast<Base1 *>(ptr)) 
    b1->wonderFULL(); 
} 

Tuttavia Wonderfull non viene mai eseguito a causa di impossibilità di lanciare ptr a b1. È possibile eseguire una simile conversione?

+1

'-1' per il codice di pubblicazione che presenta un problema che impedisce la compilazione del codice in un'area strettamente correlata al problema. – sbi

+1

Sono d'accordo con sbi. Questo esempio dovrebbe apparire come http://www.ideone.com/dg0gc. 'magicFunction' dovrebbe andare prima di' main', 'wonderFULL' dovrebbe essere definito e pubblico. – Bill

risposta

0

Passando da quello che ho capito del modo in cui alcuni compilatori C++ organizzano la gerarchia di classi in memoria dovrebbe essere possibile eseguire il cast da una classe base all'altra, ma è necessario prima eseguire il cast sulla classe derivata.

Pertanto si avrebbe bisogno di fare qualcosa di simile:

Base1* b1 = dynamic_cast<Derived*>(ptr); 

Questo getta la data puntatore ptr alla classe derivata, e poi viene implicitamente espressi a suo altro puntatore alla classe base.

Tuttavia, un altro modo più semplice per farlo sarebbe semplicemente avere un metodo nella classe Base2 che restituisce un puntatore Base1 e la classe derivata può implementarlo senza alcun codice complicato. (La stessa funzione in Base2 può solo restituire NULL se non vuoi una pura classe virtuale).

7

Questo

#include <iostream> 

class Base1 { 
public: 
    virtual void wonderFULL() = 0; 
}; 

class Base2 { 
public: 
    virtual ~Base2() {}          // added so the code compiles 
}; 

class Derived : public Base1, public Base2 { 
    virtual void wonderFULL() {std::cout << "wonderful\n";} // added so the code compiles 
}; 

void magicFunction(Base2 *ptr) { 
    if (Base1 *b1 = dynamic_cast<Base1 *>(ptr)) 
     b1->wonderFULL(); 
} 

int main() { 
    Derived Wonder; 
    magicFunction(&Wonder); 
    return 0; 
} 

stampe wonderful per me. La mia conclusione è che non stai mostrando il codice necessario per la riproduzione del tuo problema.

Prendere (una copia di) il codice effettivo e rimuovendo il codice non necessario passo dopo passo distillandolo fino a quando non si ottiene un self-contained (non ha bisogno di altre intestazioni tranne dalla lib di std), esempio compilabile che riproduce il problema. Molto probabilmente troverai il problema mentre lo fai. Tuttavia, se non lo fai, hai il perfetto caso di riproduzione per tornare qui e chiedere informazioni.

+0

Questo codice non è quello che l'OP ha pubblicato. (Nota come hai una funzione virtuale in Base2 che consente il dynamic_cast.) – Bill

+0

@Bill: Sì, certo. Altrimenti il ​​compilatore non compilerà nemmeno il codice.Vedi il mio appunto alla fine della mia risposta. – sbi

+0

+1, non è possibile eseguire il cast su un puntatore alla classe A se la classe A non ha funzioni membro virtuali. – sharptooth

2

Si può lanciare in alto nella gerarchia poi di nuovo giù:

void magicFunction(Base2& ptr) 
{ 
    try 
    { 
     Derived& d = dynamic_cast<Derived&>(ptr); 
     Base1& b = dynamic_cast<Base1&>(d); 
     b.wonderFULL(); 
    } 
    catch(const std::bad_cast&) 
    { /* Cast failed */ } 
} 
+0

Questo non dovrebbe essere necessario con 'dynamic_cast'. Vedi la mia risposta. – sbi

+1

Documenta l'intento. Se il compilatore lo ottimizza bene. Ma la documentazione extra umana leggibile di entente è buona per me. –

+0

(dovresti scrivere correttamente @address ...) Se è necessario documentare l'intento in questo modo è aperto il dibattito. La qwuestion originale ("E 'possibile dynamic_cast da una classe base ad un'altra?") Dovrebbe avere una risposta chiara e semplice. – sbi

2

Hai alcuni errori di sintassi, ma il problema reale è dynamic_cast non funziona correttamente se le classi di base non hanno almeno una virtuale funzione.

Se fai sembrare:

class Base2 
{ 
public: 
    virtual ~Base2() {} 
    // all this weird members 
}; 

E poi fissare i tuoi altri errori: wonderFULL è privato, e mai definito. magicFunction viene dichiarato dopo l'uso.

Quindi tutto works.

0

Ho trovato il problema. Non si trattava di dynamic_casts. Stavo controllando oggetti errati che non sono stati ereditati dalla base astratta. Grazie.

Problemi correlati