2012-02-27 16 views
25

Questa potrebbe essere una specie di domanda stupida, ma in C++, quando voglio lanciare un'eccezione .. cosa butto?Cosa lanciare quando si lanciano eccezioni C++?

Devo eseguire std :: exception oppure è riservato dalla libreria standard? O dovrei lanciare una stringa o int? O dovrei semplicemente buttare tutto ciò che ritengo sia appropriato?

+3

Non lanciare stringhe o stringhe! Se si lanciano sempre sottoclassi di 'std :: exception', è possibile inserire una clausola catch-all in' main' che gestisce tutte le eccezioni non gestite altrove e stampa il 'what()' dell'eccezione. –

risposta

31

Lancia una classe derivata da std::exception; se si è #include <stdexcept>, è possibile scegliere tra un numero di classi derivate ready-made, useful.

Derivando da std::exception consente ai gestori di seguire uno stile riconoscibile, poiché è sempre possibile utilizzare .what() per ottenere un messaggio di testo. Non lanciare tipi primitivi, poiché non portano informazioni semantiche.

+10

Vorrei contrastare (anche se praticamente lo stesso) che nella maggior parte dei casi le persone dovrebbero derivare le loro eccezioni da std :: runtime_error (che a sua volta è derivato da std :: exception) –

8

Generalmente le persone non rilasciano std :: exception direttamente per il semplice motivo che non memorizza alcun messaggio di errore. Non ci sarebbe nulla per il metodo che restituire. A volte mi confondo perché MSVC fornisce un'estensione non standard a questo costruttore di parametri in std :: exception che accetta una stringa.

È possibile scegliere tra le classi di eccezioni esistenti come std :: runtime_exception o definirne di proprie. Questo è piuttosto soggettivo, ma consiglio di mantenere il numero di classi di eccezioni al minimo, in quanto RAII può eliminare molte delle necessità di avere più rami di codice e catturare blocchi per diversi tipi di eccezioni. Spesso il messaggio combinato con il codice conforme a RAII è sufficiente per recuperare con garbo da qualsiasi eccezione.

E infine, raccomando tutte le eccezioni che si ereditano da std :: exception per motivi simili. Se non riesci a evitarlo, non vorrai dover sparpagliare il tuo codice con molti blocchi di cattura diversi per diversi tipi di eccezione. Risolvi il problema il più generalmente possibile.

+1

Non intendi 'std :: runtime_error'? –

1

A differenza di java, è possibile lanciare qualsiasi cosa (int, string, MyClass, ...) desiderata. Ma ascolta Kerrek. :)

0

Generalmente, è consigliabile lanciare una delle eccezioni derivate da std::exception come altri hanno già detto.

Occasionalmente ho lanciato altri tipi, ma solo se sono catturati nello stesso blocco e il valore è qualcosa di utile in quel contesto.

+0

Se stai catturando "nello stesso blocco", probabilmente non dovresti lanciare un'eccezione in primo luogo. Le eccezioni sono per condizioni eccezionali, ma se riesci a gestire la condizione proprio lì, sembra che sia solo una parte del normale flusso del programma. (E non dimenticare che * lanciare * un'eccezione può essere molto più costosa di un semplice controllo di uno stato locale.) –

+0

@KerrekSB, non ricordo le circostanze esatte in cui l'ho fatto, ma sono sicuro che era una condizione eccezionale che non faceva parte del flusso * normale *. Probabilmente anche profondamente annidato dove approcci alternativi sarebbero stati più brutti. –

+2

Abbastanza giusto. Ci sono * situazioni in cui un'eccezione può rendere un algoritmo complicato più chiaro e più facile da capire ... –

2

L'eccezione principale al lancio di qualcosa derivata da std::exception sarebbe se si utilizza un framework (ad es. MFC) con una propria gerarchia di eccezioni. In tal caso, in genere si desidera derivare da un punto appropriato nella loro gerarchia.

Nota che non sto tentando in particolare di tenere premuto MFC come esempio di gestione delle eccezioni pulita (o di una progettazione pulita in generale), solo un esempio di un framework che include una gerarchia di eccezioni. Quando si utilizza un framework che definisce già una gerarchia di eccezioni, è generalmente meglio usarlo.

In altre parole, diversamente dalle preferenze in C++, è generalmente accettato che le eccezioni dovrebbero essere una singola gerarchia monolitica con una singola radice. Per la libreria standard, quella singola radice è std::exception, ma altri framework hanno alternative e, se ne forniscono una, generalmente la si vuole inserire nella propria.

Problemi correlati