Dengan asumsi saya punya pseudo-code ini:
bool conditionA = executeStepA();
if (conditionA){
bool conditionB = executeStepB();
if (conditionB){
bool conditionC = executeStepC();
if (conditionC){
...
}
}
}
executeThisFunctionInAnyCase();
Fungsi executeStepX
harus dijalankan jika dan hanya jika sebelumnya berhasil. Bagaimanapun, executeThisFunctionInAnyCase
fungsi tersebut harus dipanggil di bagian akhir. Saya seorang pemula dalam pemrograman, sangat menyesal untuk pertanyaan yang sangat mendasar: apakah ada cara (dalam C / C ++ misalnya) untuk menghindari if
rantai panjang yang menghasilkan semacam "piramida kode", dengan mengorbankan keterbacaan kode ?
Saya tahu bahwa jika kita dapat melewati executeThisFunctionInAnyCase
pemanggilan fungsi, kode dapat disederhanakan sebagai:
bool conditionA = executeStepA();
if (!conditionA) return;
bool conditionB = executeStepB();
if (!conditionB) return;
bool conditionC = executeStepC();
if (!conditionC) return;
Tetapi kendala adalah executeThisFunctionInAnyCase
pemanggilan fungsi. Bisakah break
pernyataan itu digunakan dengan cara tertentu?
c++
c
if-statement
control-flow
ABCplus
sumber
sumber
false
dianggap sebagai situasi yang luar biasa?false
kembali dapat cukup normal.Jawaban:
Anda dapat menggunakan
&&
(logika AND):ini akan memenuhi kedua kebutuhan Anda:
executeStep<X>()
harus mengevaluasi hanya jika yang sebelumnya berhasil (ini disebut evaluasi hubung singkat )executeThisFunctionInAnyCase()
akan dieksekusi dalam hal apa punsumber
&&
dan||
) sehingga tidak ada cara Anda ingin bergabung dengan mereka menjadi satuif
pernyataan tanpa merusak keterbacaan. Dan tidak selalu mudah untuk memindahkan kondisi tersebut ke fungsi luar, karena mereka mungkin bergantung pada banyak variabel lokal yang sebelumnya dihitung, yang akan membuat kekacauan yang mengerikan jika Anda mencoba untuk melewati masing-masing sebagai argumen individu.Cukup gunakan fungsi tambahan untuk membuat versi kedua Anda berfungsi:
Menggunakan ifs yang sangat bersarang (varian pertama Anda) atau keinginan untuk keluar dari "bagian dari fungsi" biasanya berarti Anda memang membutuhkan fungsi tambahan.
sumber
foo
bekerja melalui serangkaian kondisi dan tindakan terkait. Fungsibar
dipisahkan dengan bersih dari keputusan. Jika kita melihat detail dari kondisi dan tindakan, mungkin ternyatafoo
masih melakukan terlalu banyak, tetapi untuk sekarang ini adalah solusi yang baik.bar
Anda harus secara manual meneruskannya kefoo
sebagai parameter. Jika itu yang terjadi dan jikafoo
hanya dipanggil sekali saya akan melakukan kesalahan terhadap menggunakan versi goto untuk menghindari mendefinisikan dua fungsi yang digabungkan secara ketat yang pada akhirnya tidak menjadi sangat dapat digunakan kembali.if (!executeStepA() || !executeStepB() || !executeStepC()) return
Pemrogram C sekolah lama menggunakan
goto
dalam kasus ini. Ini adalah salah satu penggunaangoto
yang sebenarnya didorong oleh styleguide Linux, itu disebut fungsi keluar terpusat:Beberapa orang bekerja menggunakan
goto
dengan membungkus tubuh menjadi satu lingkaran dan melepaskannya, tetapi secara efektif kedua pendekatan melakukan hal yang sama. Thegoto
pendekatan yang lebih baik jika Anda membutuhkan beberapa pembersihan lainnya hanya jikaexecuteStepA()
itu sukses:Dengan pendekatan loop Anda akan berakhir dengan dua tingkat loop dalam kasus itu.
sumber
goto
dan langsung berpikir "Ini kode yang mengerikan" tetapi memang memiliki kegunaan yang valid.goto
dan saya bahkan tidak perlu berpikir untuk melihat bahwa ini adalah kode yang mengerikan. Saya pernah harus memelihara itu, itu sangat jahat. OP menyarankan alternatif bahasa C yang masuk akal di akhir pertanyaan, dan saya memasukkannya dalam jawaban saya.throw
dalam banyak hal lebih buruk daripadagoto
karena denganthrow
itu bahkan tidak jelas dari konteks lokal di mana Anda akan berakhir! Gunakan pertimbangan desain yang sama untuk aliran kontrol gaya-goto seperti halnya pengecualian.Ini adalah situasi yang umum dan ada banyak cara umum untuk menghadapinya. Inilah upaya saya untuk jawaban kanonik. Beri komentar jika saya melewatkan sesuatu dan saya akan terus memperbarui postingan ini.
Ini adalah Panah
Apa yang Anda diskusikan dikenal sebagai panah anti-pola . Disebut panah karena rantai ifs bersarang membentuk blok kode yang meluas lebih jauh ke kanan dan kemudian kembali ke kiri, membentuk panah visual yang "menunjuk" ke sisi kanan panel editor kode.
Ratakan Panah dengan Penjaga
Beberapa cara umum untuk menghindari Panah dibahas di sini . Metode yang paling umum adalah dengan menggunakan pola penjaga , di mana kode menangani aliran pengecualian pertama dan kemudian menangani aliran dasar, misalnya alih-alih
... Anda akan menggunakan ....
Ketika ada serangkaian panjang penjaga, ini meratakan kode karena semua penjaga muncul jauh ke kiri dan jika Anda tidak bersarang. Selain itu, Anda secara visual memasangkan kondisi logika dengan kesalahan yang terkait, yang membuatnya jauh lebih mudah untuk mengetahui apa yang sedang terjadi:
Panah:
Menjaga:
Ini secara obyektif dan kuantitatif lebih mudah dibaca karena
Cara menambahkan kode umum di akhir
Masalah dengan pola penjaga adalah bahwa ia bergantung pada apa yang disebut "pengembalian oportunistik" atau "keluar oportunistik." Dengan kata lain, itu memecah pola bahwa setiap fungsi harus memiliki tepat satu titik keluar. Ini masalah karena dua alasan:
Di bawah ini saya telah menyediakan beberapa opsi untuk mengatasi keterbatasan ini baik dengan menggunakan fitur bahasa atau dengan menghindari masalah sama sekali.
Opsi 1. Anda tidak dapat melakukan ini: gunakan
finally
Sayangnya, sebagai pengembang c ++, Anda tidak dapat melakukan ini. Tetapi ini adalah jawaban nomor satu untuk bahasa-bahasa yang mengandung kata kunci terakhir, karena inilah yang tepat untuk itu.
Opsi 2. Hindari masalah: Merestrukturisasi fungsi Anda
Anda dapat menghindari masalah dengan memecah kode menjadi dua fungsi. Solusi ini memiliki manfaat bekerja untuk bahasa apa pun, dan selain itu dapat mengurangi kompleksitas siklomatik , yang merupakan cara yang terbukti untuk mengurangi tingkat cacat Anda, dan meningkatkan kekhususan setiap tes unit otomatis.
Ini sebuah contoh:
Opsi 3. Trik bahasa: Gunakan loop palsu
Trik umum lainnya yang saya lihat adalah menggunakan while (true) dan break, seperti yang ditunjukkan pada jawaban lain.
Meskipun ini kurang "jujur" daripada menggunakan
goto
, itu kurang cenderung kacau ketika refactoring, karena jelas menandai batas-batas ruang lingkup logika. Seorang programmer naif yang memotong dan menempelkan label Anda ataugoto
pernyataan Anda dapat menyebabkan masalah besar! (Dan terus terang polanya sangat umum sekarang saya pikir itu jelas mengomunikasikan maksud, dan karena itu tidak "tidak jujur" sama sekali).Ada varian lain dari opsi ini. Sebagai contoh, seseorang bisa menggunakan
switch
bukanwhile
. Konstruk bahasa apa pun denganbreak
kata kunci mungkin akan berfungsi.Opsi 4. Memanfaatkan siklus hidup objek
Satu pendekatan lain memanfaatkan siklus hidup objek. Gunakan objek konteks untuk membawa parameter Anda (sesuatu yang kurang naif dari contoh mencurigakan kami) dan buang ketika Anda selesai.
Catatan: Pastikan Anda memahami siklus hidup objek bahasa pilihan Anda. Anda memerlukan semacam pengumpulan sampah deterministik agar ini berfungsi, yaitu Anda harus tahu kapan destruktor akan dipanggil. Dalam beberapa bahasa Anda harus menggunakan
Dispose
alih-alih destruktor.Opsi 4.1. Memanfaatkan siklus hidup objek (pola pembungkus)
Jika Anda akan menggunakan pendekatan berorientasi objek, sebaiknya lakukan dengan benar. Opsi ini menggunakan kelas untuk "membungkus" sumber daya yang memerlukan pembersihan, serta operasi lainnya.
Sekali lagi, pastikan Anda memahami siklus hidup objek Anda.
Opsi 5. Trik bahasa: Gunakan evaluasi hubung singkat
Teknik lain adalah memanfaatkan evaluasi hubung singkat .
Solusi ini memanfaatkan cara kerja operator &&. Ketika sisi kiri && dievaluasi salah, sisi kanan tidak pernah dievaluasi.
Trik ini paling berguna ketika kode kompak diperlukan dan ketika kode tidak mungkin melihat banyak pemeliharaan, misalnya Anda menerapkan algoritma yang terkenal. Untuk pengkodean yang lebih umum, struktur kode ini terlalu rapuh; bahkan perubahan kecil pada logika dapat memicu penulisan ulang total.
sumber
Kerjakan saja
Sesederhana itu.
Karena tiga pengeditan yang masing-masing telah secara mendasar mengubah pertanyaan (empat jika seseorang menghitung revisi kembali ke versi # 1), saya menyertakan contoh kode yang saya jawab:
sumber
&&
daftar lebih jelas. Saya biasanya memecah kondisi pada baris yang terpisah dan menambahkan trailing// explanation
ke masing-masing .... Pada akhirnya, itu adalah kode yang lebih sedikit untuk dilihat, dan setelah Anda memahami cara&&
kerjanya tidak ada upaya mental yang berkelanjutan. Kesan saya adalah bahwa sebagian besar programmer C ++ profesional akan terbiasa dengan ini, tetapi seperti yang Anda katakan di industri / proyek yang berbeda fokus dan pengalaman berbeda.Sebenarnya ada cara untuk menunda tindakan dalam C ++: memanfaatkan destruktor objek.
Dengan asumsi bahwa Anda memiliki akses ke C ++ 11:
Dan kemudian menggunakan utilitas itu:
sumber
executeThisFunctionInAnyCase();
akan mengeksekusi bahkan jikafoo();
melempar pengecualian. Saat menulis kode pengecualian-aman, praktik yang baik untuk meletakkan semua fungsi pembersihan seperti itu di destruktor.foo()
. Dan jika Anda melakukannya, tangkap. Masalah terpecahkan. Perbaiki bug dengan memperbaikinya, bukan dengan menulis cara mengatasi.Defer
kelas adalah sepotong kecil kode yang dapat digunakan kembali yang memungkinkan Anda melakukan pembersihan di akhir blok, dengan pengecualian cara yang aman. itu lebih dikenal sebagai pelindung lingkup . ya, setiap penggunaan pelindung ruang lingkup dapat diekspresikan dengan cara manual lainnya, seperti halnya setiapfor
loop dapat dinyatakan sebagai blok danwhile
loop, yang pada gilirannya dapat diekspresikan denganif
dangoto
, yang dapat diekspresikan dalam bahasa assembly jika Anda mau, atau bagi mereka yang benar-benar tuan, dengan mengubah bit dalam ingatan melalui sinar kosmik yang diarahkan oleh efek kupu-kupu dari dengungan dan nyanyian pendek khusus. tapi, mengapa melakukan itu.Ada teknik bagus yang tidak memerlukan fungsi pembungkus tambahan dengan pernyataan pengembalian (metode yang ditentukan oleh Itjax). Itu menggunakan do
while(0)
pseudo-loop. Ituwhile (0)
memastikan bahwa itu sebenarnya bukan loop tetapi dieksekusi hanya sekali. Namun, sintaks loop memungkinkan penggunaan pernyataan break.sumber
inline
. Bagaimanapun, ini adalah teknik yang bagus untuk diketahui, karena ini membantu lebih dari masalah ini.Anda juga bisa melakukan ini:
Dengan cara ini Anda memiliki ukuran pertumbuhan linier minimal, +1 saluran per panggilan, dan mudah dikelola.
EDIT : (Terima kasih @Unda) Bukan penggemar besar karena Anda kehilangan visibilitas IMO:
sumber
Apakah ini akan berhasil? Saya pikir ini setara dengan kode Anda.
sumber
ok
ketika menggunakan variabel yang sama seperti ini.Dengan asumsi kode yang diinginkan adalah seperti yang saya lihat saat ini:
Saya akan mengatakan bahwa pendekatan yang benar, dalam hal ini adalah yang paling sederhana untuk dibaca dan paling mudah dipertahankan, akan memiliki tingkat lekukan yang lebih sedikit, yang (saat ini) merupakan tujuan dari pertanyaan yang dinyatakan.
Ini menghindari apa pun kebutuhan
goto
s, pengecualian, bonekawhile
loop, atau konstruksi sulit lainnya dan hanya mendapat di dengan pekerjaan sederhana di tangan.sumber
return
danbreak
melompat keluar dari loop tanpa perlu memperkenalkan variabel "flag" tambahan. Dalam hal ini, menggunakan goto akan sama innocuou - ingat bahwa Anda berdagang kompleksitas goto ekstra untuk kompleksitas variabel ekstra yang bisa berubah.newbie
, ia memberikan solusi yang lebih bersih tanpa kekurangan. Saya perhatikan juga tidak tidak bergantung padasteps
memiliki tanda tangan yang sama atau bahkan menjadi fungsi daripada blok. Saya bisa melihat ini digunakan sebagai refactor lulus pertama bahkan di mana pendekatan yang lebih canggih valid.Mungkin bukan solusi terbaik tetapi Anda bisa membuat pernyataan dalam satu
do .. while (0)
lingkaran dan menggunakanbreak
pernyataanreturn
.sumber
do .. while (0)
untuk definisi makro juga menyalahgunakan loop tetapi dianggap OK.Anda bisa meletakkan semua
if
kondisi, diformat seperti yang Anda inginkan dalam fungsi mereka sendiri, yang kembali menjalankanexecuteThisFunctionInAnyCase()
fungsi.Dari contoh dasar dalam OP, pengujian dan eksekusi kondisi dapat dipisahkan seperti itu;
Dan kemudian disebut seperti itu;
Jika C ++ 11 lambdas tersedia (tidak ada tag C ++ 11 di OP, tetapi mereka masih bisa menjadi pilihan), maka kita bisa melupakan fungsi terpisah dan membungkusnya menjadi lambda.
sumber
Jika Anda tidak suka
goto
dan tidak sukado { } while (0);
loop dan suka menggunakan C ++ Anda juga dapat menggunakan lambda sementara untuk memiliki efek yang sama.sumber
if
Anda tidak menyukai goto,&&
Anda tidak suka melakukan {} sementara (0)&&
Anda menyukai C ++ ... Maaf, tidak bisa menolak, tetapi kondisi terakhir itu gagal karena pertanyaannya ditandai c serta c ++Rantai IF / ELSE dalam kode Anda bukan masalah bahasa, tetapi desain program Anda. Jika Anda dapat menentukan ulang faktor atau menulis ulang program Anda, saya ingin menyarankan agar Anda mencari di Design Patterns ( http://sourcemaking.com/design_patterns ) untuk menemukan solusi yang lebih baik.
Biasanya, ketika Anda melihat banyak IF & lain dalam kode Anda, itu adalah kesempatan untuk menerapkan Pola Desain Strategi ( http://sourcemaking.com/design_patterns/strategy/c-sharp-dot-net ) atau mungkin kombinasi dari pola lain.
Saya yakin ada alternatif untuk menulis daftar panjang jika / yang lain, tapi saya ragu mereka akan mengubah apa pun kecuali bahwa rantai tersebut akan terlihat cantik untuk Anda (Namun, keindahan yang ada di mata yang melihatnya masih berlaku untuk kode juga :-)). Anda harus khawatir tentang hal-hal seperti (dalam 6 bulan ketika saya memiliki kondisi baru dan saya tidak ingat apa-apa tentang kode ini, apakah saya dapat menambahkannya dengan mudah? Atau bagaimana jika rantai berubah, seberapa cepat dan bebas dari kesalahan akankah saya menerapkannya)
sumber
Anda hanya melakukan ini ..
99 kali dari 100, ini adalah satu-satunya cara untuk melakukannya.
Tidak pernah, pernah, mencoba melakukan sesuatu yang "rumit" dalam kode komputer.
Ngomong - ngomong, aku cukup yakin yang berikut ini adalah solusi aktual yang ada dalam pikiran Anda ...
The melanjutkan pernyataan sangat penting dalam pemrograman algoritmik. (Seperti halnya, pernyataan goto sangat penting dalam pemrograman algoritmik.)
Dalam banyak bahasa pemrograman Anda dapat melakukan ini:
(Catatan pertama-tama: blok telanjang seperti contoh itu adalah bagian penting dan penting dari penulisan kode yang indah, terutama jika Anda berurusan dengan pemrograman "algoritmik".)
Sekali lagi, itulah tepatnya yang ada di kepala Anda, bukan?Dan itulah cara yang indah untuk menulisnya, sehingga Anda memiliki naluri yang baik.
Namun, tragisnya, dalam versi obyektif-c saat ini (Selain - Saya tidak tahu tentang Swift, maaf) ada fitur yang dapat dilihat di mana ia memeriksa apakah blok penutup adalah sebuah loop.
Inilah cara Anda menyiasatinya ...
Jadi jangan lupakan itu ..
do {} while (false);
hanya berarti "lakukan blokir ini sekali".
yaitu, sama sekali tidak ada perbedaan antara menulis
do{}while(false);
dan hanya menulis{}
.Ini sekarang berfungsi sempurna seperti yang Anda inginkan ... inilah hasilnya ...
Jadi, mungkin saja itulah cara Anda melihat algoritme di kepala Anda. Anda harus selalu mencoba menulis apa yang ada di kepala Anda. (Terutama jika Anda tidak sadar, karena saat itulah yang cantik keluar! :))
Dalam proyek "algoritmik" di mana ini sering terjadi, dalam objektif-c, kami selalu memiliki makro seperti ...
... jadi kamu bisa melakukan ini ...
Ada dua poin:
a, meskipun itu bodoh bahwa tujuan-c memeriksa jenis blok melanjutkan pernyataan, sulit untuk "melawan itu". Jadi ini keputusan yang sulit.
b, ada pertanyaan yang harus Anda indentasi, dalam contoh, blok itu? Saya kurang tidur karena pertanyaan seperti itu, jadi saya tidak bisa memberi saran.
Semoga ini bisa membantu.
sumber
if
, Anda juga bisa menggunakan nama fungsi yang lebih deskriptif dan meletakkan komentar di fungsi.Minta fungsi eksekusi Anda melempar pengecualian jika gagal alih-alih salah. Maka kode panggilan Anda dapat terlihat seperti ini:
Tentu saja saya berasumsi bahwa dalam contoh asli Anda langkah eksekusi hanya akan mengembalikan false jika terjadi kesalahan dalam langkah tersebut?
sumber
Sudah banyak jawaban yang bagus, tetapi sebagian besar dari mereka tampaknya mengimbangi beberapa (diakui sangat sedikit) dari fleksibilitas. Pendekatan umum yang tidak memerlukan tradeoff ini adalah menambahkan variabel status / terus-menerus . Harga tentu saja merupakan satu nilai ekstra untuk melacak:
sumber
ok &= conditionX;
dan tidak sederhanaok = conditionX;
?Di C ++ (pertanyaannya ditandai C dan C ++), jika Anda tidak dapat mengubah fungsi untuk menggunakan pengecualian, Anda masih dapat menggunakan mekanisme pengecualian jika Anda menulis fungsi pembantu kecil seperti
Maka kode Anda dapat dibaca sebagai berikut:
Jika Anda menyukai sintaksis mewah, Anda bisa membuatnya bekerja melalui pemeran eksplisit:
Kemudian Anda dapat menulis kode Anda sebagai
sumber
Jika kode Anda sesederhana contoh Anda dan bahasa Anda mendukung evaluasi hubung singkat, Anda dapat mencoba ini:
Jika Anda meneruskan argumen ke fungsi Anda dan mendapatkan kembali hasil lainnya sehingga kode Anda tidak dapat ditulis dengan cara sebelumnya, banyak dari jawaban lain akan lebih cocok untuk masalah tersebut.
sumber
Untuk C ++ 11 dan seterusnya, pendekatan yang bagus mungkin untuk mengimplementasikan sistem exit scope mirip dengan mekanisme scope (exit) D.
Salah satu cara yang mungkin untuk mengimplementasikannya adalah menggunakan C ++ 11 lambdas dan beberapa makro pembantu:
Ini akan memungkinkan Anda untuk kembali lebih awal dari fungsi dan memastikan kode pembersihan apa pun yang Anda tetapkan selalu dijalankan saat ruang lingkup keluar:
Makro benar-benar hanya hiasan.
MakeScopeExit()
dapat digunakan secara langsung.sumber
[=]
biasanya salah untuk lambda yang dicakup.[&]
: itu aman, dan sedikit mengejutkan. Tangkap dengan nilai hanya ketika lambda (atau salinan) dapat bertahan lebih lama dari ruang lingkup pada titik deklarasi ...Mengapa tidak ada yang memberikan solusi paling sederhana? : D
Jika semua fungsi Anda memiliki tanda tangan yang sama maka Anda dapat melakukannya dengan cara ini (untuk bahasa C):
Untuk solusi C ++ yang bersih, Anda harus membuat kelas antarmuka yang berisi metode eksekusi dan membungkus langkah-langkah Anda dalam objek.
Maka, solusi di atas akan terlihat seperti ini:
sumber
Dengan asumsi Anda tidak memerlukan variabel kondisi individual, membalikkan tes dan menggunakan else-falthrough sebagai jalur "ok" akan memungkinkan Anda mendapatkan set pernyataan if / else yang lebih vertikal:
Menghilangkan variabel yang gagal membuat kode IMO agak terlalu kabur.
Mendeklarasikan variabel di dalamnya baik-baik saja, tidak perlu khawatir tentang = vs ==.
Ini tidak jelas, tetapi kompak:
sumber
Ini terlihat seperti mesin keadaan, yang berguna karena Anda dapat dengan mudah menerapkannya dengan pola-negara .
Di Jawa akan terlihat seperti ini:
Suatu implementasi akan bekerja sebagai berikut:
Dan seterusnya. Maka Anda dapat mengganti yang besar jika kondisinya dengan:
sumber
Seperti yang disebutkan Rommik, Anda bisa menerapkan pola desain untuk ini, tapi saya akan menggunakan pola Dekorator daripada Strategi karena Anda ingin membuat panggilan. Jika kodenya sederhana, maka saya akan pergi dengan salah satu jawaban terstruktur dengan baik untuk mencegah bersarang. Namun, jika rumit atau memerlukan perangkaian dinamis, maka pola Penghias adalah pilihan yang baik. Berikut adalah diagram kelas yUML :
Berikut ini contoh program LinqPad C #:
Buku terbaik untuk membaca tentang pola desain, IMHO, adalah Pola Desain Kepala Pertama .
sumber
Beberapa jawaban mengisyaratkan pola yang saya lihat dan gunakan berkali-kali, terutama dalam pemrograman jaringan. Dalam tumpukan jaringan sering kali ada urutan permintaan yang panjang, yang salah satunya dapat gagal dan akan menghentikan proses.
Pola umum yang digunakan
do { } while (false);
Saya menggunakan makro untuk
while(false)
membuatnyado { } once;
Pola umum adalah:Pola ini relatif mudah dibaca, dan memungkinkan objek untuk digunakan yang akan merusak dengan baik dan juga menghindari beberapa pengembalian membuat langkah dan debug sedikit lebih mudah.
sumber
Untuk meningkatkan jawaban Mathieu C ++ 11 dan menghindari biaya runtime yang timbul karena penggunaan
std::function
, saya akan menyarankan untuk menggunakan yang berikut iniKelas template sederhana ini akan menerima functor yang dapat dipanggil tanpa parameter apa pun, dan melakukannya tanpa alokasi memori dinamis dan karenanya lebih sesuai dengan tujuan abstraksi C ++ tanpa overhead yang tidak perlu. Template fungsi tambahan ada untuk menyederhanakan penggunaan dengan pengurangan parameter template (yang tidak tersedia untuk parameter template kelas)
Contoh penggunaan:
Sama seperti jawaban Mathieu, solusi ini sepenuhnya pengecualian aman, dan
executeThisFunctionInAnyCase
akan dipanggil dalam semua kasus. JikaexecuteThisFunctionInAnyCase
itu sendiri melempar, destruktor secara implisit ditandainoexcept
dan oleh karena itu panggilan untukstd::terminate
akan dikeluarkan alih-alih menyebabkan pengecualian untuk dilemparkan selama tumpukan dibuka.sumber
functor
dideferred
konstruktor, tidak perlu memaksa amove
.Sepertinya Anda ingin melakukan semua panggilan Anda dari satu blok. Seperti yang telah diusulkan orang lain, Anda harus menggunakan
while
perulangan dan menggunakanbreak
atau fungsi baru yang dapat Anda tinggalkanreturn
(mungkin lebih bersih).Saya pribadi mengusir
goto
, bahkan untuk keluar fungsi. Mereka lebih sulit dikenali saat debugging.Alternatif elegan yang harus bekerja untuk alur kerja Anda adalah membangun sebuah array fungsi dan beralih pada yang satu ini.
sumber
Karena Anda juga memiliki [... blok kode ...] antara eksekusi, saya kira Anda memiliki alokasi memori atau inisialisasi objek. Dengan cara ini Anda harus peduli membersihkan semua yang sudah Anda inisialisasi saat keluar, dan juga membersihkannya jika Anda akan menemui masalah dan salah satu fungsi akan kembali salah.
Dalam hal ini, yang terbaik yang saya miliki dalam pengalaman saya (ketika saya bekerja dengan CryptoAPI) adalah membuat kelas kecil, di konstruktor Anda menginisialisasi data Anda, di destructor Anda uninitialize itu. Setiap kelas fungsi berikutnya harus merupakan anak dari kelas fungsi sebelumnya. Jika ada yang salah - lempar pengecualian.
Dan kemudian dalam kode Anda, Anda hanya perlu menelepon:
Saya kira itu adalah solusi terbaik jika setiap panggilan dari ConditionX menginisialisasi sesuatu, memori allocs dan lain-lain. Terbaik untuk memastikan semuanya akan dibersihkan.
sumber
cara yang menarik adalah bekerja dengan pengecualian.
Jika Anda menulis kode seperti itu, Anda akan pergi ke arah yang salah. Saya tidak akan melihatnya sebagai "masalah" untuk memiliki kode seperti itu, tetapi memiliki "arsitektur" yang berantakan.
Kiat: diskusikan kasus-kasus tersebut dengan pengembang berpengalaman yang Anda percayai ;-)
sumber
Pendekatan lain -
do - while
loop, meskipun telah disebutkan sebelumnya tidak ada contoh yang akan menunjukkan tampilannya:(Yah sudah ada jawaban dengan
while
loop tetapido - while
loop tidak secara berlebihan memeriksa benar (pada awalnya) tetapi sebaliknya pada akhir xD (ini dapat dilewati, meskipun)).sumber