Saya memiliki pemahaman yang sangat buruk tentang penanganan pengecualian (yaitu, bagaimana menyesuaikan lempar, coba, tangkap pernyataan untuk keperluan saya sendiri).
Sebagai contoh, saya telah mendefinisikan fungsi sebagai berikut: int compare(int a, int b){...}
Saya ingin fungsi untuk melempar pengecualian dengan beberapa pesan ketika a atau b negatif.
Bagaimana saya harus mendekati ini dalam definisi fungsi?
c++
exception-handling
Terry Li
sumber
sumber
unsigned int
sebagai parameter dalam tanda tangan fungsi Anda. Kemudian lagi saya dari sekolah bahwa Anda hanya harus membuang dan menangkap pengecualian untuk hal-hal yang sebenarnya luar biasathrow()
spesifikasi pengecualian pada fungsi.Jawaban:
Sederhana:
Perpustakaan Standar dilengkapi dengan koleksi bagus objek pengecualian bawaan yang dapat Anda lemparkan. Ingatlah bahwa Anda harus selalu melempar dengan nilai dan menangkap dengan referensi:
Anda dapat memiliki beberapa pernyataan catch () setelah setiap percobaan, sehingga Anda dapat menangani berbagai jenis pengecualian secara terpisah jika Anda mau.
Anda juga dapat melemparkan kembali pengecualian:
Dan untuk menangkap pengecualian terlepas dari jenisnya:
sumber
throw;
(rethrowing objek asli dan melestarikan tipenya) daripadathrow e;
(melempar salinan objek yang tertangkap, mungkin mengubah tipenya).Tambahkan saja di
throw
tempat yang diperlukan, dantry
blokir ke penelepon yang menangani kesalahan. Dengan konvensi Anda hanya boleh membuang hal-hal yang berasal daristd::exception
, jadi sertakan<stdexcept>
terlebih dahulu.Juga, lihat Boost.Exception .
sumber
Meskipun pertanyaan ini agak lama dan sudah dijawab, saya hanya ingin menambahkan catatan tentang cara melakukan penanganan pengecualian yang benar di C ++ 11:
Gunakan
std::nested_exception
danstd::throw_with_nested
Ini dijelaskan pada StackOverflow di sini dan di sini , bagaimana Anda bisa mendapatkan backtrace pada pengecualian Anda di dalam kode Anda tanpa perlu debugger atau logging yang rumit, dengan hanya menulis handler pengecualian yang tepat yang akan mengumpulkan kembali pengecualian bersarang.
Karena Anda bisa melakukan ini dengan kelas pengecualian apa pun, Anda dapat menambahkan banyak informasi ke backtrace tersebut! Anda juga dapat melihat MWE saya di GitHub , di mana backtrace akan terlihat seperti ini:
sumber
Anda dapat menentukan pesan untuk dilemparkan ketika kesalahan tertentu terjadi:
atau Anda dapat mendefinisikannya seperti ini:
Biasanya, Anda akan memiliki
try ... catch
blok seperti ini:sumber
Ingin ADD untuk jawaban yang lain dijelaskan di sini catatan tambahan, dalam kasus pengecualian kustom .
Dalam kasus di mana Anda membuat pengecualian kustom Anda sendiri, yang berasal dari
std::exception
, ketika Anda menangkap jenis pengecualian "semua mungkin", Anda harus selalu memulaicatch
klausa dengan jenis pengecualian "paling banyak diturunkan" yang mungkin ditangkap. Lihat contoh (apa yang TIDAK harus dilakukan):CATATAN:
0) Urutan yang tepat harus sebaliknya, yaitu- pertama Anda
catch (const MyException& e)
yang diikuti olehcatch (const std::exception& e)
.1) Seperti yang Anda lihat, ketika Anda menjalankan program seperti, menangkap klausa pertama akan dieksekusi (yang mungkin apa yang Anda lakukan tidak ingin di tempat pertama).
2) Meskipun tipe yang ditangkap dalam klausa tangkapan pertama adalah tipe
std::exception
, versi "tepat"what()
akan dipanggil - karena itu ditangkap dengan referensi (ubah setidaknyastd::exception
tipe argumen yang tertangkap menjadi berdasarkan nilai - dan Anda akan mengalami fenomena "mengiris objek" dalam aksi).3) Seandainya "beberapa kode disebabkan oleh fakta bahwa pengecualian XXX dilempar ..." melakukan hal-hal penting DENGAN MENGHORMATI jenis pengecualian, ada kesalahan kode di sini.
4) Ini juga relevan jika objek yang ditangkap adalah objek "normal" seperti:
class Base{};
danclass Derived : public Base {}
...5)
g++ 7.3.0
di Ubuntu 18.04.1 menghasilkan peringatan yang menunjukkan masalah yang disebutkan:Sekali lagi , saya akan mengatakan, bahwa jawaban ini hanya untuk TAMBAH ke jawaban lain yang dijelaskan di sini (saya pikir poin ini layak disebutkan, namun tidak dapat menggambarkannya dalam komentar).
sumber