Kembali ke sekolah sekitar 10+ tahun yang lalu, mereka mengajari Anda untuk menggunakan penentu pengecualian. Karena latar belakang saya adalah sebagai salah satu dari mereka programmer Torvaldish C yang dengan keras kepala menghindari C ++ kecuali dipaksa, saya hanya berakhir di C ++ secara sporadis, dan ketika saya melakukannya saya masih menggunakan penentu pengecualian karena itulah yang saya ajarkan.
Namun, sebagian besar programmer C ++ tampaknya tidak menyukai penentu pengecualian. Saya telah membaca debat dan argumen dari berbagai guru C ++, seperti ini . Sejauh yang saya mengerti, itu bermuara pada tiga hal:
- Penentu pengecualian menggunakan sistem tipe yang tidak konsisten dengan bagian bahasa lainnya ("sistem tipe bayangan").
- Jika fungsi Anda dengan specifier pengecualian melempar apa pun selain apa yang telah Anda tentukan, program akan dihentikan dengan cara yang buruk dan tidak terduga.
- Penentu pengecualian akan dihapus dalam standar C ++ yang akan datang.
Apakah saya kehilangan sesuatu di sini atau ini semua alasannya?
Pendapat saya sendiri:
Mengenai 1): Jadi apa. C ++ mungkin adalah bahasa pemrograman yang paling tidak konsisten yang pernah dibuat, sintaksis. Kami memiliki makro, goto / label, gerombolan (menimbun?) Perilaku tidak terdefinisi- / tidak ditentukan / implementasi, tipe integer yang tidak terdefinisi dengan baik, semua aturan promosi tipe implisit, kata kunci kasus khusus seperti teman, otomatis , daftar, eksplisit ... Dan seterusnya. Seseorang mungkin bisa menulis beberapa buku tebal tentang semua keanehan dalam C / C ++. Jadi mengapa orang bereaksi terhadap ketidakkonsistenan khusus ini, yang merupakan kelemahan kecil dibandingkan dengan banyak fitur lain dari bahasa yang jauh lebih berbahaya?
Mengenai 2): Bukankah itu tanggung jawab saya sendiri? Ada begitu banyak cara saya bisa menulis bug yang fatal di C ++, mengapa kasus khusus ini lebih buruk Alih-alih menulis throw(int)
dan kemudian melempar Crash_t, saya mungkin juga mengklaim bahwa fungsi saya mengembalikan pointer ke int, kemudian membuat typecast liar, eksplisit dan mengembalikan pointer ke Crash_t. Semangat C / C ++ selalu meninggalkan sebagian besar tanggung jawab kepada programmer.
Lalu bagaimana dengan keuntungannya? Yang paling jelas adalah bahwa jika fungsi Anda mencoba untuk secara eksplisit melemparkan jenis apa pun selain apa yang Anda tentukan, kompiler akan memberi Anda kesalahan. Saya percaya bahwa standarnya jelas mengenai hal ini (?). Bug hanya akan terjadi ketika fungsi Anda memanggil fungsi lain yang pada gilirannya melemparkan tipe yang salah.
Berasal dari dunia yang penuh deterministik, program-program C yang tertanam, saya pasti akan lebih suka untuk mengetahui dengan tepat fungsi apa yang akan dilemparkan kepada saya. Jika ada sesuatu dalam bahasa yang mendukung itu, mengapa tidak menggunakannya? Alternatifnya tampaknya:
void func() throw(Egg_t);
dan
void func(); // This function throws an Egg_t
Saya pikir ada kemungkinan besar bahwa penelepon mengabaikan / lupa untuk menerapkan try-catch dalam kasus kedua, kurang begitu dalam kasus pertama.
Seperti yang saya pahami, jika salah satu dari kedua bentuk ini memutuskan untuk tiba-tiba melempar pengecualian lain, program akan macet. Dalam kasus pertama karena tidak diperbolehkan untuk melempar pengecualian lain, dalam kasus kedua karena tidak ada yang berharap untuk melempar SpanishInquisition_t dan oleh karena itu ekspresi itu tidak tertangkap di tempat seharusnya.
Dalam kasus yang terakhir, untuk mendapatkan tangkapan terakhir (...) pada tingkat tertinggi dari program tidak benar-benar tampak lebih baik daripada crash program: "Hei, di suatu tempat di program Anda ada sesuatu yang melempar pengecualian aneh, tidak tertangani . " Anda tidak dapat memulihkan program begitu Anda berada jauh dari tempat pengecualian itu dilemparkan, satu-satunya hal yang dapat Anda lakukan adalah keluar dari program.
Dan dari sudut pandang pengguna, mereka tidak peduli jika mereka mendapatkan kotak pesan jahat dari OS yang mengatakan "Program dihentikan. Blablabla di alamat 0x12345" atau kotak pesan jahat dari program Anda yang mengatakan "Pengecualian tidak tertangani: myclass. func.something ". Bugnya masih ada.
Dengan standar C ++ yang akan datang saya tidak akan memiliki pilihan lain selain mengabaikan penentu pengecualian. Tetapi saya lebih suka mendengar beberapa argumen yang kuat mengapa mereka buruk, daripada "Yang Mulia telah menyatakannya dan karena itu begitu". Mungkin ada lebih banyak argumen terhadap mereka daripada yang saya sebutkan, atau mungkin ada lebih banyak daripada yang saya sadari?
Jawaban:
Spesifikasi pengecualian buruk karena mereka ditegakkan dengan lemah, dan karena itu tidak benar-benar menghasilkan banyak, dan mereka juga buruk karena memaksa run-time untuk memeriksa pengecualian yang tidak terduga sehingga mereka dapat berakhir (), bukannya meminta UB , ini dapat membuang banyak kinerja.
Jadi, secara ringkas, spesifikasi pengecualian tidak ditegakkan cukup kuat dalam bahasa untuk benar-benar membuat kode lebih aman, dan menerapkannya seperti yang ditentukan adalah menguras kinerja besar.
sumber
Salah satu alasan tidak ada yang menggunakannya adalah karena asumsi utama Anda salah:
Program ini dikompilasi tanpa kesalahan atau peringatan .
Selain itu, meskipun pengecualian akan ditangkap , program masih berakhir.
Sunting: untuk menjawab suatu titik dalam pertanyaan Anda, tangkap (...) (atau lebih baik, tangkap (std :: pengecualian &) atau kelas dasar lainnya, dan kemudian tangkap (...)) masih berguna bahkan jika Anda tidak tahu persis apa yang salah.
Pertimbangkan bahwa pengguna Anda telah menekan tombol menu untuk "save". Pawang untuk tombol menu mengundang aplikasi untuk menyimpan. Ini bisa gagal karena berbagai alasan: file itu pada sumber daya jaringan yang lenyap, ada file read-only dan tidak dapat disimpan, dll. Tapi pawang tidak benar-benar peduli mengapa sesuatu gagal; hanya peduli apakah itu berhasil atau gagal. Jika berhasil, semuanya baik. Jika gagal, itu dapat memberi tahu pengguna. Sifat eksepsi yang tepat tidak relevan. Selain itu, jika Anda menulis kode yang benar, pengecualian-aman, itu berarti bahwa kesalahan semacam itu dapat menyebar melalui sistem Anda tanpa menjatuhkannya - bahkan untuk kode yang tidak peduli dengan kesalahan tersebut. Ini membuatnya lebih mudah untuk memperluas sistem. Misalnya, Anda sekarang menyimpan melalui koneksi database.
sumber
Wawancara dengan Anders Hejlsberg ini cukup terkenal. Di dalamnya, ia menjelaskan mengapa tim desain C # membuang pengecualian yang diperiksa. Singkatnya, ada dua alasan utama: kemampuan versi dan skalabilitas.
Saya tahu OP berfokus pada C ++ sedangkan Hejlsberg membahas C #, tetapi poin yang Hejlsberg buat juga sangat cocok untuk C ++.
sumber