อะไรคือความแตกต่างระหว่าง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)