2013-06-16 20 views
8

Sto imparando la gestione delle eccezioni in C++ e ho riscontrato un problema. Ecco il codice:: impossibile dynamic_cast ... (la destinazione non è un puntatore o riferimento)

#include<iostream> 
#include<exception> 

using namespace std; 

class A 
{ 
public: 
    virtual void f(void){} 
}; 

class AA:public A 
{ 
public: 
    void aa(void){}; 

}; 

int main(void) 
{ 

    A a; 
    try 
    { 
     dynamic_cast<AA>(a).aa(); 
    } 
    catch(exception ex) 
    { 
     cout<<"["<<ex.what()<<"]"<<endl; 
    } 
    return 0; 
} 

Così ho pensato che il tentativo di cattura consentirà la funzione da eseguire e mi mostra il contenuto della deroga, ma il mio compilatore non compilarlo. Sto usando il codeblock con GNU GCC. Per favore aiutami e mostrami cosa devo fare per far funzionare il codice come volevo. molte grazie.

+0

Si sta verificando un errore del compilatore. È importante per te condividere questo errore nella tua domanda in modo che tu possa imparare a leggerli e comprenderli. –

+0

sicuro. "can not dynamic_cast 'a' (di tipo 'class A') per digitare 'class AA' (target non è puntatore o riferimento) – focusHard

+1

Qual è il problema principale qui.' dynamic_cast' funziona su puntatori o tipi di riferimento. 'AA' è non un puntatore o un tipo di riferimento – Chad

risposta

3

Si sta verificando un errore del compilatore perché il dynamic_cast non è sul puntatore o sul riferimento.
modificarla in:

dynamic_cast<AA&>(a).aa(); 

... e si ottiene l'eccezione corretta gettato.

Sul lato nota: compilatori intelligenti like g ++ sarebbe mettere in guardia così:
avvertimento: dynamic_cast su un oggetto (qui a) non potrà mai avere successo.

Quindi è meglio limitare tale codice per giocare in giro. Nel codice di qualità della produzione, lo dynamic_cast deve essere eseguito solo su puntatore/riferimento.

18

dynamic_cast può trasmettere solo a un valore di puntatore o riferimento, che è esattamente ciò che l'errore sta dicendo.

Da $ 5,2,7/1 dello standard C++.

The result of the expression dynamic_cast< T >(v) is the result of converting the expression v to type T. T shall be a pointer or reference to a complete class type, or “pointer to cv void.”

Affinché dynamic_cast un'eccezione quando l'oggetto non può essere convertito è necessario lanciare ad un riferimento. Cambiare al seguente:

dynamic_cast<AA&>(a).aa(); 
//   ^^^ cast to reference. 

Come Johnsyweb sottolineato dynamic_cast sarà sempre buttare std::bad_cast quando la conversione non riesce. Sebbene std::bad_cast sia derivato da std::exception, è sempre consigliabile utilizzare l'eccezione che si adatta meglio alla condizione di errore prevista. Ciò impedisce di interpretare inavvertitamente altri errori come un cast non riuscito.

Per applicare questo al tuo esempio potrebbe sembrare il seguente codice.

#include <iostream> 
#include <typeinfo> // std::bad_cast 

class A 
{ 
public: 
    virtual void f(void){} 
}; 

class AA:public A 
{ 
public: 
    void aa(void){}; 
}; 

int main(void) 
{ 
    A a; 

    try 
    { 
     dynamic_cast<AA&>(a).aa(); 
    } 
    catch(const std::bad_cast& ex) 
    { 
     std::cout << "["<<ex.what()<<"]" << std::endl; 
    } 
    return 0; 
} 

[Nota, facendo le cose come using namespace std; è fortemente sconsigliato in quanto può causare conflitti con identificatori nello spazio dei nomi globale. Ho rimosso che nell'esempio di cui sopra]

+0

grazie, la tua spiegazione è molto chiara – focusHard

+0

dopo modificando il mio codice su , il programma restituisce [std :: exception] .come arrivo a std :: bad_cast? puoi per favore illustrare "è sempre una buona idea usare l'eccezione che si adatta meglio alla condizione di errore prevista" usando esempio di codice? grazie – focusHard

+0

@focusHard, metti un 'catch (std :: bad_cast & e)' sopra il blocco 'catch()' esistente e '#include '. – iammilind

5

Il tuo problema non è con la gestione eccezione, ma con il vostro fusione dinamica:.

'AA' is not a reference or pointer 

dynamic_cast converte in modo sicuro puntatori e riferimenti a class es e non istanze.

Così si potrebbe fare:

dynamic_cast<AA&>(a).aa(); 

... che sarà sempre fallire e un'eccezione std::bad_cast.

Si dovrebbe prendere il tipo più specifico di exception che vi aspettate e dal the recommended way to catch is by reference, si dovrebbe preferire:

catch (std::bad_cast const& ex) 

Ulteriori approfondimenti:dynamic_cast conversion su cppreference.com.

+0

Ho provato a prendere (std :: bad_cast const & ex) come suggerito ma ricevere diversi messaggi di errore. "atteso specificatore di tipo", "atteso id non qualificato prima di 'const'" – focusHard

+1

'std :: bad_cast' è definito nell'intestazione' '. Avrai bisogno di "# include" questo. – Johnsyweb

0

Ho appena trattato lo stesso errore, ma nel mio caso stavo passando da un puntatore a un puntatore, quindi le altre risposte qui non si applicano. Il mio messaggio di errore era leggermente diverso, tuttavia: error: cannot dynamic_cast 'f()' (of type 'class B*') to type 'class A*' (target is not pointer or reference to complete type).

La causa principale nel mio caso era molto più semplice e banale.

Avviso l'aggiunta di per completare il tipo alla fine. Questo mi ha fatto ricordare che non ho incluso il file di intestazione per la mia classe che stavo usando. Non era un simbolo sconosciuto perché A* è stato inoltrato dichiarato con class A; nel file di intestazione, causandone l'esistenza ma non il completamento, quindi l'errore.

La soluzione nel mio caso era quella di includere il file di intestazione per la classe a cui stavo parlando.

Questo non è il problema del richiedente asked sopra, ma come può essere visto dal mio caso può generare lo stesso tipo di errore.