2013-07-10 4 views
7

Ho un problema con il seguente codice. Come possiamo vedere ho già gestito l'eccezione lanciata dal costruttore di A nel costruttore di C, perché dovrei preoccuparmi di catturare e gestire nuovamente l'eccezione nella funzione principale?Elenco di inizializzazione costruttore C++ eccezioni di lancio

#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

Fa eccezione in realtà propagano dal costruttore 'C' di? Se no, perché riprenderlo? – arne

+1

Chi ti ha suggerito di rilevare l'eccezione anche in 'main()'? Fagli questa domanda! – Nawaz

+1

@Nawaz, o lei, ciao. Non c'è da meravigliarsi che non ci siano donne in questa professione: p – chris

risposta

16

Non si può in realtà cattura un'eccezione in un costruttore. Puoi gestirlo, ma devi ricrearlo o un'altra eccezione. Il motivo è di circa oggetto di integrità e di oggetti vite:

Se la costruzione di a getta, una parte di c non è stata inizializzata ed è completamente mancante - vita di a non parte mai. a non è una parte facoltativa di C, altrimenti doveva essere un puntatore o (dal momento che C++ 14 - boost::optional prima di quello).

Quindi come si monta un C se una delle sue parti vitali non può essere costruita? Non puoi c non può mai iniziare ad esistere come oggetto completo, quindi non è possibile uscire normalmente dal costruttore. Questo è il motivo per cui se la costruzione di un oggetto membro fallisce, la costruzione dell'intero oggetto deve fallire, ovvero deve fare un'eccezione a.

Se non si genera un'eccezione nel blocco catch di C::C, il compilatore lo farà per voi.

C++ standard, §15.3,15:

L'eccezione attualmente gestita viene rilanciati se il controllo raggiunge la fine di un gestore della funzione-provare-a blocchi di un costruttore o distruttore.

Per un trattamento più ampio su questo argomento, vedere http://www.gotw.ca/gotw/066.htm

+0

Grazie a tutti voi, in particolare @Arne Mertz. E lo standard C++ spiega tutto, :-) – JavaBeta