Pertanyaan Bagaimana cara menangani eksepsi dalam konstruktor dengan benar? [duplikat]


Kemungkinan Duplikat:
Cara membersihkan sumber yang diinisialisasi jika pengecualian dilemparkan dari konstruktor di c ++ 

Bagaimana cara menangani pengecualian dalam konstruktor jika saya membuat 6 objek dan objek-objek tersebut membuat 5 objek dan gagal saat membuat yang ke-6?

Terima kasih.


6
2017-10-04 09:12


asal


Jawaban:


Perilaku biasa adalah hanya membiarkan perkecualian menyebar. Destruktor untuk kelas dasar dan anggota yang benar-benar dibangun akan dipanggil; jika lima objek pertama adalah anggota, mereka akan benar dirusak.

Satu-satunya kasus di mana masalah mungkin terjadi adalah jika objek Anda berbicara tentang telah dialokasikan secara dinamis (menggunakan new). Jika itu benar kasus: hal pertama yang harus ditanyakan pada diri sendiri adalah mengapa? Kenapa kamu mengalokasikan secara dinamis, dan tidak menjadikan objek sebagai anggota konkrit? Di pengalaman saya, kebutuhan seperti itu sangat, sangat jarang, kecuali dalam beberapa hal khusus kasus (misalnya idiom kompilasi firewall), dalam hal ini, akan ada biasanya tepat satu objek di kelas (misalnya penunjuk ke objek implementasi). Dalam kasus seperti itu, tidak ada masalah, karena jika itu new dari objek itu gagal, tidak ada lagi yang telah dilakukan yang perlu kehancuran.

Jika Anda menemukan diri Anda dalam kasus yang sangat jarang di mana Anda benar-benar memang harus menggunakan alokasi dinamis dan memiliki lebih dari satu objek semacam itu (mis. karena Anda memiliki dua subobjek yang polimorfik), lalu Anda harus memastikan bahwa setiap alokasi terbungkus dalam beberapa semacam sub-objek (penunjuk pintar akan melakukan trik); dulu yang pertama sub-objek telah berhasil dibangun, destruktornya akan disebut jika konstruktor gagal di beberapa titik kemudian.


3
2017-10-04 09:43



Ketika pengecualian dilemparkan dalam konstruktor, semua subobjek yang sepenuhnya terkonstruksi dihancurkan. Karena itu adalah praktik yang baik untuk memiliki destruktor dari benda-benda yang dibangun untuk menjaga resoyrces mereka, tidak ada yang perlu dilakukan untuk subobjects ini. Yang tersisa adalah pembersihan di dalam tubuh konstruktor yang sedang dieksekusi saat pengecualian dilemparkan. Namun, ini tidak berbeda dengan pembersihan dalam fungsi lain apa pun.

Perhatikan bahwa perintah pemusnahan adalah kebalikan dari konstruksi. Artinya, bersih-bersih di dalam tubuh dimulai pertama ketika semua subobject tidak, namun, dihancurkan. Kemudian para anggota dihancurkan, kemudian kelas dasar non-virtual, dan akhirnya kelas dasar virtual.


1
2017-10-04 09:40



Pada "inti" dari berurusan dengan pengecualian adalah bahwa hampir semuanya harus dibersihkan melalui destruktor. Misalnya, jika Anda "baru" sebuah objek, Anda mendapatkan pointer "mentah"; jika pengecualian dibuang di suatu tempat Anda harus memastikan bahwa pointer mentah ini benar "hapus" d - tetapi pastikan Anda tidak menghapus penunjuk mentah yang belum diinisialisasi.

Di sisi lain, jika Anda menyimpan pointer ke std :: unique_ptr Anda tidak perlu melakukan apa-apa; ketika unique_ptr dihancurkan, objek dihapus, dan penghancuran objek terjadi secara otomatis: ketika unique_ptr keluar dari ruang lingkup, compiler memanggil cleanup, benar-benar tidak terlihat (jadi tidak ada lagi kode-cluttering dengan banyak sekali panggilan pembersihan) dan secara otomatis (jadi tidak ada lagi 'aduh, ketika dibutuhkan jalan langka yang tidak ada yang benar-benar diuji lupa untuk membersihkan').

Hal yang sama dapat diterapkan pada hampir semua sumber daya; ada "auto pointer" untuk COM-objek (seperti yang digunakan dalam DirectX, misalnya), sebagian besar kerangka kerja harus memberikan Anda "scoped lock" -tipe objek untuk membungkus mutexes (sehingga mengunci mutex ketika objek dibuat, dan buka kunci ketika sudah dirusak), dan Anda dapat menulis bungkus kecil untuk menangani berbagai pegangan Windows.

Pada dasarnya, jika Anda menempatkan semua pembersihan Anda ke dalam perusak, Anda tidak akan pernah harus "mencoba ... menangkap ... rethrow" hanya untuk membersihkan. Dan perusak benda-benda "lebih besar" sering kali sangat sederhana, karena hampir semua benda "berisi" dibersihkan secara otomatis oleh perusaknya.


1
2017-10-04 10:57