อะไรคือความแตกต่างระหว่างstd::runtime_errorและstd::exception? การใช้งานที่เหมาะสมสำหรับแต่ละคนคืออะไร? ทำไมพวกเขาถึงแตกต่างกันตั้งแต่แรก?
อะไรคือความแตกต่างระหว่างstd::runtime_errorและstd::exception? การใช้งานที่เหมาะสมสำหรับแต่ละคนคืออะไร? ทำไมพวกเขาถึงแตกต่างกันตั้งแต่แรก?
คำตอบ:
std::exceptionเป็นคลาสที่มีจุดประสงค์เดียวเพื่อใช้เป็นคลาสพื้นฐานในลำดับชั้นของข้อยกเว้น มันไม่มีประโยชน์อื่นใด กล่าวอีกนัยหนึ่งแนวคิดมันเป็นคลาสนามธรรม (แม้ว่าจะไม่ได้กำหนดให้เป็นคลาสนามธรรมในความหมาย C ++ ของคำศัพท์ก็ตาม)
std::runtime_errorเป็นคลาสที่มีความเชี่ยวชาญมากขึ้นจากมากไปหาน้อยstd::exceptionโดยมีวัตถุประสงค์เพื่อโยนทิ้งในกรณีที่เกิดข้อผิดพลาดรันไทม์ต่างๆ มีวัตถุประสงค์สองประการ มันสามารถนำมาโยนด้วยตัวเองหรือมันสามารถทำหน้าที่เป็นชั้นฐานประเภทมากยิ่งขึ้นเฉพาะต่างๆของข้อยกเว้นข้อผิดพลาด runtime เช่นstd::range_error, std::overflow_errorฯลฯ คุณสามารถกำหนดระดับชั้นยกเว้นของคุณเองลงมาจากstd::runtime_errorเช่นเดียวกับคุณสามารถกำหนดข้อยกเว้นของคุณเอง std::exceptionลงมาจากชั้นเรียน
เช่นเดียวกับstd::runtime_errorไลบรารีมาตรฐานประกอบด้วยstd::logic_errorจากมากไปหาน้อยstd::exceptionเช่นกัน
จุดสำคัญของการมีลำดับชั้นนี้คือเพื่อให้ผู้ใช้มีโอกาสใช้กลไกการจัดการข้อยกเว้น C ++ อย่างเต็มประสิทธิภาพ เนื่องจากอนุประโยค 'catch' สามารถจับข้อยกเว้นของ polymorphic ได้ผู้ใช้จึงสามารถเขียน clauses 'catch' ที่สามารถตรวจจับชนิดข้อยกเว้นจากแผนผังย่อยเฉพาะของลำดับชั้นของข้อยกเว้น ตัวอย่างเช่นcatch (std::runtime_error& e)จะจับข้อยกเว้นทั้งหมดจากstd::runtime_errorทรีย่อยโดยปล่อยให้คนอื่น ๆ ทั้งหมดผ่านไป (และบินต่อไปใน call stack)
PS การออกแบบลำดับชั้นของข้อยกเว้นที่มีประโยชน์ (ซึ่งจะช่วยให้คุณสามารถจับเฉพาะประเภทข้อยกเว้นที่คุณสนใจในแต่ละจุดของรหัสของคุณ) เป็นงานที่ไม่สำคัญ สิ่งที่คุณเห็นในไลบรารี C ++ มาตรฐานเป็นแนวทางหนึ่งที่เป็นไปได้ซึ่งเสนอให้กับคุณโดยผู้เขียนภาษา ดังที่คุณเห็นพวกเขาตัดสินใจที่จะแยกประเภทข้อยกเว้นทั้งหมดออกเป็น "ข้อผิดพลาดรันไทม์" และ "ข้อผิดพลาดทางตรรกะ" และให้คุณดำเนินการต่อจากที่นั่นด้วยประเภทข้อยกเว้นของคุณเอง แน่นอนว่ามีวิธีอื่นในการจัดโครงสร้างลำดับชั้นดังกล่าวซึ่งอาจเหมาะสมกว่าในการออกแบบของคุณ
อัปเดต: Portability Linux เทียบกับ Windows
ดังที่ Loki Astari และ unixman83 ระบุไว้ในคำตอบและความคิดเห็นด้านล่างตัวสร้างของexceptionคลาสจะไม่ใช้ข้อโต้แย้งใด ๆ ตามมาตรฐาน C ++ Microsoft C ++ มีตัวสร้างที่รับอาร์กิวเมนต์ในexceptionคลาส แต่นี่ไม่ใช่มาตรฐาน runtime_errorชั้นมีตัวสร้างการมีปากเสียง ( char*) บนแพลตฟอร์มทั้ง Windows และ Linux runtime_errorที่จะพกพาใช้งานได้ดียิ่งขึ้น
(และโปรดจำไว้ว่าเพียงเพราะข้อกำหนดของโครงการของคุณบอกว่าโค้ดของคุณไม่จำเป็นต้องทำงานบน Linux แต่ก็ไม่ได้หมายความว่าจะไม่ต้องทำงานบน Linux)
std::exceptionมีกฎที่ทุกกองกำลังที่คุณจะได้รับจาก แน่นอนว่าทุกstdสิ่งล้วนโยนคลาสที่ได้รับจากสิ่งนั้นมา แต่ไม่มีเหตุผลที่จะโยนstd::exceptionวัตถุที่ได้รับเท่านั้น
std::exceptionควรพิจารณา (สังเกตการพิจารณา) ฐานนามธรรมของลำดับชั้นข้อยกเว้นมาตรฐาน เนื่องจากไม่มีกลไกในการส่งผ่านข้อความใดข้อความหนึ่ง (ในการทำเช่นนี้คุณต้องได้รับและเชี่ยวชาญwhat()) ไม่มีอะไรที่จะหยุดคุณจากการใช้ std :: ข้อยกเว้นและสำหรับแอปพลิเคชันง่ายๆอาจเป็นสิ่งที่คุณต้องการ
std::runtime_errorในทางกลับกันมีตัวสร้างที่ถูกต้องซึ่งยอมรับสตริงเป็นข้อความ เมื่อwhat()ใดที่เรียกว่า const char pointer จะถูกส่งกลับจุดที่สตริง C ที่มีสตริงเดียวกันกับที่ถูกส่งไปยังตัวสร้าง
try
{
if (badThingHappened)
{
throw std::runtime_error("Something Bad happened here");
}
}
catch(std::exception const& e)
{
std::cout << "Exception: " << e.what() << "\n";
}
std::exception(std::string)เพราะไมโครซอฟท์ที่ผมได้นำมาใช้เพื่อการขว้างปา ตอนนี้ฉันรู้แล้วว่าฉันต้องโยนstd::runtime_errorถ้าฉันต้องการให้โค้ดของฉันทำงานใน Linux (GCC)