2012-03-05 8 views

Odpowiedz

7

Połów catch-all (...) nie daje dostępu do obiektu wyjątku, więc pytanie jest dyskusyjne. [Poprawione:] Rethrowing z throw; wyrzuca oryginalny obiekt. Jeśli przewodnik przechwytuje wartość, zmiany na kopii lokalnej nie mają wpływu na oryginalny, ponownie zwrócony obiekt. [/] Aby uzyskać szczegółowe informacje, patrz punkt 15.3 (szczególnie punkt 17).

Zobacz niektóre z powiązanych pytań po prawej stronie, takich jak this one lub this one i this one i this one.

+0

Jeśli ktoś pisze 'catch (...) {throw; } ', a następnie w jaki sposób zostałby ponownie rzucony, przez wartość lub przez odniesienie? Zwróć uwagę, że w tym przypadku nie jest przechwytywany oryginalny obiekt. – Nawaz

+0

Według wartości lub przez odniesienie? – Nawaz

+0

Szczególnie odważna część jest myląca z 'catch (...)': * "Rethrowing with throw, wyrzuca oryginalny obiekt ** jeśli oryginalny wyjątek został złapany przez odniesienie ** lub jeśli został wywołany w catch-all, i kopię **, jeśli wyjątek został przechwycony przez wartość **. "* – Nawaz

1

Rzut powoduje skopiowanie wyrzuconej wartości do zdefiniowanej lokalizacji.
Tak więc wartość jest kopiowana przy rzucie (co oznacza, że ​​typ musi być kopiowalny).

Po złapaniu można wybrać odłowu według wartości lub odniesienia.

catch(X val) // Catch by value 
{ 
} 
catch(Y& val) // Catch by reference 
{ 
} 

Idiomatycznym powodem, dla którego należy złapać, jest złapanie przez odniesienie do stałej. Dzieje się tak dlatego, że jeśli złapiesz wartość, istnieje możliwość ukrojenia, gdy wyjątek zostanie skopiowany z zapisanej lokalizacji do wartości catch. Jeśli złapiesz wartość, wartość zostanie zniszczona na końcu bloku catch. Kopia w zapisanej lokalizacji zostanie zniszczona na końcu bloku try/catch, w którym została przechwycona (i nie jest ponownie zgłaszana).

Po złapaniu z catch(...) nic się nie dzieje. Wyjątek pozostaje w nieokreślonej lokalizacji, do której wyjątek został już skopiowany.

Gdy używasz rzutowania, aby ponownie rzucić wyjątek. throw;. Znowu nic się nie dzieje, ponieważ wyjątek znajduje się już w nieokreślonej lokalizacji i nic nie musi się wydarzyć.

Uwaga: wywołanie throw;, gdy nie rozprzestrzenia się żaden wyjątek, jest błędem i spowoduje wywołanie polecenia std :: endate.

+0

co z "catch (...) {throw;}", o które pyta? –

+0

@MooingDuck: Przepraszam, po prostu do tego. Chciałem najpierw wyjaśnić główną część dla kontekstu. –

2

Zawsze łapiesz to, co rzuciłeś. Powiedzmy, że masz klasę wyjątku

class MyException { 
public: 
    int m_data; 
    MyException(int data) 
    { 
     printf("MyException::MyException() ctor\n"); 
     m_data = data; 
    } 

    MyException(const MyException & other) { 
     printf("MyException::MyException() copy ctor\n"); 
    } 

    ~MyException() 
    { 
     printf("MyException::~MyException() dtor\n"); 
    } 
}; 

1) Jeśli rzucony wskaźnik, dostaniesz wskaźnik:

Przykład 1:

void f() 
{ 
    throw new MyException() 
} 

void main() 
{ 
    try{ 
     f(); 
    }  
    catch(MyException * ex) // You WILL catch the pointer 
    { 
     delete ex; // You should delete the exception object 
    } 
    catch(MyException & ex) // You WILL NOT catch the pointer 
    { 
    } 
} 

Przykład 2:

void main() 
{ 
    try{ 
     f(); 
    } 
    catch(...) // You WILL catch the pointer, but will be unable to access it 
    { 
     throw; // You are rethrowing the pointer 
    } 
} 

2) Jeśli rzucony przedmiot, złapiesz odniesienie do niego:

Przykład 1:

void f() 
{ 
    printf("f BEGIN\n"); 
    throw MyException(1); // MyException ctor is called 
    printf("f END\n"); 
} 

void main() 
{ 
    printf("main BEGIN\n"); 

    try 
    { 
     f(); 
    } 
    catch(MyException & ex) // You WILL catch a reference to created object 
    { 
     printf("catch MyException: %d\n", ex.m_data); 
    } // MyException dtor is called here!! 

    printf("main END\n"); 
} 

Poniższy wyjściowa jest wytwarzana :

main BEGIN 
f BEGIN 
MyException::MyException() ctor 
catch MyException: 1 
MyException::~MyException() dtor 
main END 

Przykład 2:

void main() 
{ 
    try 
    { 
     f(); 
    } 
    catch(...) // You WILL catch a reference to created object, 
       //but will be unable to access it 
    { 
     throw; // You throw the reference 
    } 
} 
Powiązane problemy