2013-06-16 10 views
8

Ich lerne Ausnahmebehandlung in C++ und lief auf ein Problem. Hier ist der Code:Fehler: kann nicht dynamic_cast ... (Ziel ist nicht Zeiger oder Verweis)

#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; 
} 

Also dachte ich, die versuchen, fangen die Funktion ermöglicht die Ausführung und zeigen Sie mir den Inhalt der Ausnahme, aber mein Compiler es nicht kompilieren. Ich verwende Codeblock mit GNU GCC. Bitte helfen Sie mir und zeigen Sie mir, was ich tun muss, damit der Code wie gewünscht ausgeführt wird. Danke vielmals.

+0

Sie erhalten einen Compilerfehler. Es ist wichtig, dass Sie diesen Fehler in Ihrer Frage teilen, damit Sie sie lesen und verstehen lernen können. –

+0

sicher. "kann nicht dynamic_cast 'a' (vom Typ 'Klasse A'), um 'Klasse AA' (Ziel ist nicht Zeiger oder Referenz) – focusHard

+1

Das ist das Hauptproblem hier.' dynamic_cast' funktioniert auf Zeiger oder Referenztypen. 'AA' ist kein Zeiger oder Referenztyp – Chad

Antwort

3

Sie erhalten einen Compilerfehler, weil dynamic_cast nicht auf Zeiger oder Verweis ist.
Ändern Sie es an:

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

... und Sie die richtige Ausnahme geworfen bekommen.

Auf Seite Anmerkung: Smart-Compiler wie g ++ würde auch warnen:
Warnung: dynamic_cast auf ein Objekt (hier a) kann nie gelingen.

Also ist es besser, diesen Code für herumspielen zu begrenzen. Im Produktionsqualitätscode sollte dynamic_cast nur auf Zeiger/Referenz ausgeführt werden.

18

dynamic_cast kann nur auf einen Zeigerwert oder eine Referenz umgewandelt werden, was genau der Fehler ist, der Ihnen angezeigt wird.

Von $ 5.2.7/1 des C++ Standards.

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.”

Damit dynamic_cast eine Ausnahme ausgelöst, wenn das Objekt nicht konvertiert werden können Sie auf eine Referenz werfen müssen. Ändern Sie es auf die folgenden:

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

Wie Johnsyweb wies darauf hin, dynamic_cast immer std::bad_cast werfen, wenn die Konvertierung fehlschlägt. Obwohl std::bad_cast von std::exception abgeleitet ist, ist es immer eine gute Idee, die Ausnahme zu verwenden, die am besten zum erwarteten Fehlerzustand passt. Dies verhindert, dass versehentlich andere Fehler als fehlgeschlagene Cast interpretiert werden.

Um dies auf Ihr Beispiel anzuwenden, könnte es wie der folgende Code aussehen.

#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; 
} 

[Anmerkung, Dinge zu tun, wie using namespace std; wird dringend abgeraten, da es Konflikte mit Identifikatoren im globalen Namensraum führen kann. Ich habe es in dem obigen Beispiel removed]

+0

danke, Ihre Erklärung ist sehr klar – focusHard

+0

nach Wenn ich meinen Code zu ändere, gibt das Programm [std :: exception] aus, wie komme ich zu std :: bad_cast? Kannst du bitte illustrieren "es ist immer eine gute Idee, die Exception zu verwenden, die der erwarteten Fehlerbedingung am besten entspricht" Codebeispiel? Danke – focusHard

+0

@focusHard, setzen Sie einen 'catch (std :: bad_cast & e)' über den vorhandenen 'catch()' Block. Und '#include '. – iammilind

5

Ihr Problem ist nicht mit Ausnahmebehandlung, aber mit Ihrer dynamischen Umwandlung.

'AA' is not a reference or pointer 

dynamic_cast wandelt sicher Zeiger und Referenzen zu class es und nicht Instanzen.

So könnten Sie tun:

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

... das wird immer scheitern und eine std::bad_cast Ausnahme auslösen.

Sie sollten die meisten spezifische Art von exception fangen, die Sie erwarten und da the recommended way to catch is by reference, sollten Sie bevorzugen:

catch (std::bad_cast const& ex) 

Weiterführende Literatur:dynamic_cast conversion auf cppreference.com.

+0

Ich versuchte catch (std :: bad_cast const & ex) wie Sie vorgeschlagen, aber mehrere Fehlermeldungen erhalten. "expected type-specifier", "erwartete unqualifizierte-id vor 'const'" – focusHard

+1

'std :: bad_cast' ist im Header' 'definiert. Sie müssen dies "einschließen". – Johnsyweb

0

Ich habe gerade mit dem gleichen Fehler behandelt, aber in meinem Fall ging ich von einem Zeiger zu einem Zeiger, so dass die anderen Antworten hier nicht zutreffen. Meine Fehlermeldung war jedoch etwas anders: error: cannot dynamic_cast 'f()' (of type 'class B*') to type 'class A*' (target is not pointer or reference to complete type).

Die Ursache in meinem Fall war viel einfacher und banal.

Beachten Sie die Zugabe von zu Art vervollständigen am Ende. Dies veranlasste mich zu erinnern, dass ich die Header-Datei für meine Klasse, die ich verwendete, nicht einschloss. Es war kein unbekanntes Symbol, weil A* vorwärts mit class A; in der Header-Datei deklariert wurde, wodurch es zwar existiert, aber nicht vollständig ist, daher der Fehler.

Die Lösung in meinem Fall war, die Header-Datei für die Klasse, die ich warf, zu enthalten.

Dies ist nicht das Frage Fragesteller-Problem oben, aber wie aus meinem Fall ersichtlich, kann die gleiche Art von Fehler erzeugen.