สิ่งที่คุณดูเหมือนจะติดอยู่คือนรกที่เฉพาะเจาะจงของคนที่พยายามมีเค้กและกินมันด้วย
RAII และข้อยกเว้นถูกออกแบบมาเพื่อไปจับมือ RAII เป็นวิธีการที่คุณไม่ต้องเขียนcatch(...)
คำสั่งจำนวนมากเพื่อล้างข้อมูล มันจะเกิดขึ้นโดยอัตโนมัติตามความเป็นจริง และข้อยกเว้นเป็นวิธีเดียวที่จะทำงานกับวัตถุ RAII ได้เพราะผู้สร้างสามารถประสบความสำเร็จหรือโยน (หรือทำให้วัตถุอยู่ในสถานะข้อผิดพลาด แต่ใครต้องการมัน?)
catch
คำสั่งสามารถทำหนึ่งในสองสิ่ง: การจัดการข้อผิดพลาดหรือกรณีพิเศษหรือทำผลงานทำความสะอาด บางครั้งมันทำทั้งสองอย่าง แต่ทุก ๆcatch
ประโยคมีอยู่ให้ทำอย่างน้อยหนึ่งอย่าง
catch(...)
ไม่สามารถจัดการข้อยกเว้นที่เหมาะสมได้ คุณไม่รู้ว่าข้อยกเว้นคืออะไร; คุณไม่สามารถรับข้อมูลเกี่ยวกับข้อยกเว้น คุณไม่มีข้อมูลอื่นใดนอกจากความจริงที่ว่ามีข้อผิดพลาดเกิดขึ้นจากบางสิ่งในบล็อกโค้ดบางอัน สิ่งเดียวที่ถูกต้องตามกฎหมายที่คุณสามารถทำได้ในบล็อกนั้นคือทำการล้างข้อมูล และนั่นหมายถึงการโยนข้อยกเว้นอีกครั้งเมื่อสิ้นสุดการล้างข้อมูล
สิ่งที่ RAII ให้คุณเกี่ยวกับการจัดการข้อยกเว้นคือการล้างข้อมูลฟรี หากทุกอย่าง RAII ถูกห่อหุ้มอย่างถูกต้องทุกอย่างจะถูกล้างอย่างถูกต้อง คุณไม่จำเป็นต้องมีcatch
งบทำความสะอาดอีกต่อไป ในกรณีนี้ไม่มีเหตุผลที่จะเขียนcatch(...)
คำสั่ง
ดังนั้นผมจะยอมรับว่าcatch(...)
เป็นความชั่วร้ายส่วนใหญ่ ... ชั่วคราว
บทบัญญัติดังกล่าวเป็นการใช้งานที่เหมาะสมของ RAII เพราะไม่ว่าคุณต้องการที่จะสามารถทำล้างบาง ไม่มีการรับรอบ; คุณต้องสามารถทำความสะอาดได้ คุณต้องสามารถมั่นใจได้ว่าการโยนข้อยกเว้นจะทำให้รหัสอยู่ในสถานะที่เหมาะสม และcatch(...)
เป็นเครื่องมือสำคัญในการทำเช่นนั้น
คุณไม่สามารถมีหนึ่งโดยไม่มีอื่น ๆ คุณไม่สามารถพูดได้ว่าทั้ง RAII และ catch(...)
ไม่ดี คุณต้องการอย่างน้อยหนึ่งอย่าง มิฉะนั้นคุณจะไม่ได้รับการยกเว้นอย่างปลอดภัย
แน่นอนว่ามีการใช้งานที่ถูกต้อง แต่หายากcatch(...)
ที่ไม่ใช่แม้แต่ RAII ที่สามารถขับไล่ได้: รับการexception_ptr
ส่งต่อไปยังผู้อื่น โดยทั่วไปผ่านpromise/future
อินเทอร์เฟซหรือคล้ายกัน
เพื่อนร่วมงานของฉันบอกว่าคุณควรรู้อยู่เสมอว่าจะมีข้อยกเว้นอะไรบ้างและคุณสามารถใช้โครงสร้างเช่น:
เพื่อนร่วมงานของคุณเป็นคนงี่เง่า (หรือไม่รู้ตัวมาก) สิ่งนี้ควรจะชัดเจนในทันทีเนื่องจากมีรหัสการคัดลอกและวางที่แนะนำให้คุณเขียน การล้างข้อมูลสำหรับคำสั่งการดักจับแต่ละคำจะเหมือนกันทุกประการ นั่นเป็นฝันร้ายของการบำรุงรักษาไม่พูดถึงความสามารถในการอ่าน
กล่าวโดยย่อ: นี่เป็นปัญหาที่ RAII ถูกสร้างขึ้นเพื่อแก้ไข (ไม่ใช่ว่ามันจะไม่แก้ปัญหาอื่น ๆ )
สิ่งที่ทำให้ฉันสับสนเกี่ยวกับความคิดนี้ก็คือโดยทั่วไปแล้วจะย้อนกลับไปที่คนส่วนใหญ่ให้เหตุผลว่า RAII ไม่ดี โดยทั่วไปแล้วอาร์กิวเมนต์ไปที่ "RAII ไม่ดีเพราะคุณต้องใช้ข้อยกเว้นเพื่อส่งสัญญาณความล้มเหลวของตัวสร้าง แต่คุณไม่สามารถโยนข้อยกเว้นได้เนื่องจากมันไม่ปลอดภัยและคุณจะต้องมีcatch
งบจำนวนมากเพื่อล้างข้อมูลทุกอย่าง" ซึ่งเป็นข้อโต้แย้งที่ขาดหายไปเพราะ RAII แก้ปัญหาที่การขาด RAII สร้างขึ้น
ยิ่งกว่านั้นเขากับ RAII เพราะซ่อนรายละเอียด การเรียก Destructor ไม่สามารถมองเห็นได้ทันทีในตัวแปรอัตโนมัติ ดังนั้นคุณจะได้รับรหัสที่ถูกเรียกโดยปริยาย โปรแกรมเมอร์บางคนเกลียดที่จริง เห็นได้ชัดว่าถึงจุดที่พวกเขาคิดว่ามี 3 catch
คำสั่งทั้งหมดที่ทำในสิ่งเดียวกันกับรหัสคัดลอกและวางเป็นความคิดที่ดีกว่า
...
" ในขณะที่คำถามของฉันมุ่งเน้นไปที่ "ฉันควรจะจับดีขึ้น...
หรือ<specific exception>
ก่อนที่จะกลับมาใหม่"