2013-06-16 11 views
8

Uczę się obsługi wyjątków w C++ i napotykam problem. Oto kod:error: can not dynamic_cast ... (cel nie jest wskaźnikiem ani odniesieniem)

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

Pomyślałem więc haczyk try funkcja pozwoli na wykonanie i pokaż mi zawartość wyjątku, ale mój kompilator nie kompiluje go. Używam codeblock z GNU GCC. Proszę, pomóżcie mi i pokażcie, co muszę zrobić, aby kod działał tak, jak zamierzałem. wielkie dzięki.

+0

Otrzymujesz błąd kompilatora. Ważne jest, abyś podzielił się tym błędem w swoim pytaniu, abyś mógł nauczyć się je czytać i rozumieć. –

+0

pewnie. "nie może dynamic_cast" a "(typu" klasa A ") do typu" klasa AA "(cel nie jest wskaźnikiem lub odniesieniem) – focusHard

+1

Co jest tutaj głównym problemem,' dynamic_cast' działa na wskaźniku lub typach referencyjnych. 'AA' jest nie jest wskaźnikiem ani typem referencji – Chad

Odpowiedz

3

Otrzymujesz błąd kompilatora, ponieważ twój dynamic_cast nie znajduje się na wskaźniku lub odnośniku.
go zmienić na:

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

... i masz właściwej rzucony wyjątek.

Na marginesie: Inteligentne kompilatory jak g ++ Przestrzega także:
ostrzeżenie: dynamic_cast na obiekcie (tutaj a) nigdy nie uda.

Więc lepiej jest ograniczyć taki kod do bawienia się. W kodzie jakości produkcji, dynamic_cast należy wykonywać tylko na wskaźniku/odnośniku.

18

dynamic_cast może rzutować tylko na wartość wskaźnika lub referencję, co jest dokładnie tym, co mówi błąd.

Od 5,2 USD/1 standardu 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.”

Aby dynamic_cast do wyjątek, gdy obiekt nie może być przekształcony trzeba oddać do odniesienia. Zmień go na następujący:

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

Jak Johnsyweb wskazał dynamic_cast zawsze rzucać std::bad_cast gdy konwersja się nie powiedzie. Chociaż std::bad_cast pochodzi od std::exception, zawsze dobrze jest użyć wyjątku, który najlepiej pasuje do oczekiwanego warunku awarii. Zapobiega to nieumyślnemu interpretowaniu innych błędów jako nieudanej obsady.

Aby zastosować to do twojego przykładu może wyglądać jak poniższy kod.

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

[Uwaga, robiąc rzeczy, jak using namespace std; jest zalecane, ponieważ może to spowodować konflikty z identyfikatorami w globalnej przestrzeni nazw. Usunąłem go w powyższym przykładzie]

+0

dzięki, twoje wyjaśnienie jest bardzo jasne – focusHard

+0

po modyfikując mój kod na , program wyświetla [std :: exception]. jak mogę dostać się do std :: bad_cast? czy możesz zilustrować "zawsze dobrze jest użyć wyjątku, który najlepiej pasuje do oczekiwanego warunku awarii" używając przykład kodu? dzięki – focusHard

+0

@focusHard, umieść 'catch (std :: bad_cast & e)' powyżej istniejącego bloku 'catch()' i '#include '. – iammilind

5

Twój problem nie jest z obsługą wyjątek, ale z dynamicznego obsady.

'AA' is not a reference or pointer 

dynamic_cast bezpiecznie konwertuje wskazówek i referencje do class es, a nie wystąpień.

Więc można zrobić:

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

... który będzie zawsze zawieść i rzucać std::bad_cast wyjątek.

Należy złapać najbardziej specyficzny rodzaj exception że spodziewasz, a od the recommended way to catch is by reference powinien wolisz:

catch (std::bad_cast const& ex) 

Dalsze czytanie:dynamic_cast conversion na cppreference.com.

+0

Próbowałem catch (std :: bad_cast const & ex) zgodnie z sugestią, ale otrzymujesz kilka komunikatów o błędach. "oczekiwany specyfikator typu", "oczekiwano niewykwalifikowanego identyfikatora przed" const "" – focusHard

+1

'std :: bad_cast' jest zdefiniowane w nagłówku' '. Musisz "# include" to. – Johnsyweb

0

Po prostu miałem do czynienia z tym samym błędem, ale w moim przypadku przechodziłem od wskaźnika do wskaźnika, więc inne odpowiedzi tutaj nie miały zastosowania. Mój komunikat o błędzie był nieco inny: error: cannot dynamic_cast 'f()' (of type 'class B*') to type 'class A*' (target is not pointer or reference to complete type).

Główna przyczyna w moim przypadku była znacznie prostsza i bardziej przyziemna.

Zauważ dodanie , aby zakończyć typ na końcu. To spowodowało, że zapamiętałem, że nie uwzględniłem pliku nagłówkowego dla mojej klasy, z której korzystałem. Nie był to nieznany symbol, ponieważ A* został zgłoszony do przodu z class A; w pliku nagłówkowym, powodując, że istnieje, ale nie jest kompletny, stąd błąd.

Rozwiązaniem w moim przypadku było dołączenie pliku nagłówkowego dla klasy, do której byłem przesyłany.

To nie jest problem pytającego, ale powyższy przypadek może generować ten sam typ błędu.

Powiązane problemy