2013-07-10 24 views
7

Ich habe ein Problem mit dem folgenden Code. Wie wir sehen können, habe ich bereits die Exception behandelt, die von As Konstruktor in Cs Konstruktor geworfen wurde. Warum sollte ich mich darum kümmern, die Exception in der Hauptfunktion wieder zu erfassen und zu behandeln?C++ - Konstruktor Initialisierungsliste werfen Ausnahmen

#include <iostream> 

class WException : public std::exception 
{ 
public: 
    WException(const char* info) : std::exception(info){} 
}; 

class A 
{ 
public: 
    A(int a) : a(a) 
    { 
     std::cout << "A's constructor run." << std::endl; 
     throw WException("A constructor throw exception."); 
    } 

private: 
    int a; 
}; 

class B 
{ 
public: 
    B(int b) : b(b) 
    { 
     std::cout << "B's constructor body run." << std::endl; 
     throw WException("B constructor throw exception"); 
    } 

private: 
    int b; 
}; 

class C : public A, public B 
{ 
public: 
    C(int a, int b) try : A(a), B(b) 
    { 
     std::cout << "C's constructor run." << std::endl; 
    } 
    catch(const WException& e) 
    { 
     std::cerr << "In C's constructor" << e.what() << std::endl; 
    } 
}; 

int main(int argc, char* argv[]) 
{ 
    try 
    { 
     C c(10, 100); 
    } 
    catch(const WException& e) 
    { 
     std::cerr << "In the main: " << e.what() << std::endl; 
    } 

    return 0; 
} 
+2

Hat eigentlich die Ausnahme von 'C' Konstruktor propagieren? Wenn nicht, warum fangen Sie es wieder? – arne

+1

Wer hat vorgeschlagen, die Ausnahme in 'main()' auch zu fangen? Stellen Sie ihm diese Frage! – Nawaz

+1

@Nawaz, Oder sie, meine Güte. Es ist kein Wunder, dass es in diesem Beruf keine Frauen gibt: p – chris

Antwort

16

Sie können nicht wirklich fangen eine Ausnahme in einem Konstruktor. Sie können damit umgehen, aber Sie müssen es oder eine andere Ausnahme erneut auslösen. Der Grund ist, über das Objekt Integrität und Objektlebensdauern:

Wenn der Bau von a wirft, ein Teil von c wurde nicht initialisiert und ist völlig fehlt - Lebensdauer von a nie beginnt. a ist kein optionaler Teil von C, sonst musste es ein Zeiger sein oder ein std::optional (seit C++ 14 - boost::optional davor).

Wie also bauen Sie ein C zusammen, wenn eines seiner wichtigsten Teile nicht gebaut werden kann? Du kannst nicht. c kann nie als vollständiges Objekt beginnen, daher gibt es keine Möglichkeit, den Konstruktor normal zu verlassen. Das ist der Grund, warum, wenn die Konstruktion eines Mitgliedsobjekts fehlschlägt, die Konstruktion des gesamten Objekts fehlschlagen muss, d. H. muss eine Ausnahme auslösen.

Wenn Sie keine Ausnahme in C::C 's catch block werfen, wird der Compiler dies für Sie tun.

C++ Standard §15.3,15:

Die aktuell behandelte Ausnahme erneut ausgelöst wird, wenn die Steuerung das Ende einer Prozedur der Funktion-try-Block eines Konstruktor oder Destruktor erreicht.

Für eine breitere Behandlung zu diesem Thema finden Sie http://www.gotw.ca/gotw/066.htm

+0

Danke euch allen, besonders @Arne Mertz. Und der C++ Standard erklärt alles, :-) – JavaBeta

Verwandte Themen