Quello che sembra essere catturato è l'inferno specifico di qualcuno che cerca di avere la sua torta e mangiarla anche lei.
RAII ed eccezioni sono progettate per andare di pari passo. RAII è il mezzo con cui non è necessario scrivere molte catch(...)
istruzioni per eseguire la pulizia. Accadrà automaticamente, ovviamente. E le eccezioni sono l'unico modo per lavorare con oggetti RAII, perché i costruttori possono solo riuscire o lanciare (o mettere l'oggetto in uno stato di errore, ma chi lo vuole?).
Una catch
dichiarazione può fare una delle due cose: gestire un errore o di circostanza eccezionale, o fare il lavoro di pulizia. A volte fa entrambe le cose, ma ogni catch
affermazione esiste per fare almeno una di queste.
catch(...)
non è in grado di gestire correttamente le eccezioni. Non sai quale sia l'eccezione; non è possibile ottenere informazioni sull'eccezione. Non hai assolutamente altre informazioni oltre al fatto che un'eccezione è stata generata da qualcosa all'interno di un determinato blocco di codice. L'unica cosa legittima che puoi fare in un blocco del genere è fare pulizia. E questo significa ripetere l'eccezione alla fine della pulizia.
Ciò che RAII ti offre in merito alla gestione delle eccezioni è la pulizia gratuita. Se tutto è incapsulato correttamente in RAII, allora tutto verrà adeguatamente ripulito. Non è più necessario che le catch
istruzioni eseguano la pulizia. In tal caso, non c'è motivo di scrivere una catch(...)
dichiarazione.
Quindi concordo sul fatto che catch(...)
è per lo più malvagio ... provvisoriamente .
Tale disposizione è l'uso corretto di RAII. Perché senza di essa, è necessario essere in grado di fare certa pulizia. Non c'è modo di aggirarlo; devi essere in grado di fare un lavoro di pulizia. Devi essere in grado di assicurarti che il lancio di un'eccezione lascerà il codice in uno stato ragionevole. Ed catch(...)
è uno strumento vitale per farlo.
Non puoi averne uno senza l'altro. Non si può dire che sia RAII e catch(...)
sono cattivi. Hai bisogno di almeno uno di questi; in caso contrario, non sei sicuro per le eccezioni.
Ovviamente, c'è un uso valido, anche se raro, catch(...)
che nemmeno la RAII può bandire: ottenere un exception_ptr
inoltro a qualcun altro. In genere tramite promise/future
un'interfaccia simile o simile.
I miei colleghi dicono che dovresti sempre sapere quali eccezioni devono essere lanciate e che puoi sempre usare costrutti come:
Il tuo collega è un idiota (o semplicemente terribilmente ignorante). Questo dovrebbe essere immediatamente ovvio a causa della quantità di codice copia e incolla che sta suggerendo di scrivere. La pulizia per ciascuna di queste dichiarazioni di cattura sarà esattamente la stessa . È un incubo per la manutenzione, per non parlare della leggibilità.
In breve: questo è il problema che RAII è stato creato per risolvere (non che non risolve altri problemi).
Ciò che mi confonde di questa nozione è che è generalmente all'indietro rispetto al modo in cui la maggior parte delle persone sostiene che la RAII è cattiva. In generale, l'argomento dice "RAII è un male perché devi usare le eccezioni per segnalare un errore del costruttore. Ma non puoi lanciare eccezioni, perché non è sicuro e dovrai avere un sacco di catch
istruzioni per ripulire tutto". Il che è un argomento rotto perché RAII risolve il problema creato dalla mancanza di RAII.
Molto probabilmente, è contro la RAII perché nasconde i dettagli. Le chiamate ai distruttori non sono immediatamente visibili sulle variabili automatiche. Quindi ottieni codice che viene chiamato in modo implicito. Alcuni programmatori lo odiano davvero. Apparentemente, al punto in cui pensano di avere 3 catch
istruzioni, tutte che fanno la stessa cosa con il codice copia e incolla è un'idea migliore.
...
" mentre la mia domanda si concentra su "Dovrei catturare meglio...
o<specific exception>
prima di ridisegnare"