อยากจะเพิ่มคำตอบอื่น ๆ ที่อธิบายที่นี่ทราบเพิ่มเติมในกรณีของข้อยกเว้นที่กำหนดเอง
ในกรณีที่คุณสร้างข้อยกเว้นที่กำหนดเองของคุณเองซึ่งเกิดขึ้นจากstd::exception
เมื่อคุณตรวจสอบประเภทข้อยกเว้น "ที่เป็นไปได้ทั้งหมด" คุณควรเริ่มต้นส่วนcatch
คำสั่งด้วยประเภทข้อยกเว้น ดูตัวอย่าง (สิ่งที่ไม่ต้องทำ):
#include <iostream>
#include <string>
using namespace std;
class MyException : public exception
{
public:
MyException(const string& msg) : m_msg(msg)
{
cout << "MyException::MyException - set m_msg to:" << m_msg << endl;
}
~MyException()
{
cout << "MyException::~MyException" << endl;
}
virtual const char* what() const throw ()
{
cout << "MyException - what" << endl;
return m_msg.c_str();
}
const string m_msg;
};
void throwDerivedException()
{
cout << "throwDerivedException - thrown a derived exception" << endl;
string execptionMessage("MyException thrown");
throw (MyException(execptionMessage));
}
void illustrateDerivedExceptionCatch()
{
cout << "illustrateDerivedExceptionsCatch - start" << endl;
try
{
throwDerivedException();
}
catch (const exception& e)
{
cout << "illustrateDerivedExceptionsCatch - caught an std::exception, e.what:" << e.what() << endl;
// some additional code due to the fact that std::exception was thrown...
}
catch(const MyException& e)
{
cout << "illustrateDerivedExceptionsCatch - caught an MyException, e.what::" << e.what() << endl;
// some additional code due to the fact that MyException was thrown...
}
cout << "illustrateDerivedExceptionsCatch - end" << endl;
}
int main(int argc, char** argv)
{
cout << "main - start" << endl;
illustrateDerivedExceptionCatch();
cout << "main - end" << endl;
return 0;
}
บันทึก:
0) ลำดับที่ถูกต้องควรเป็นในทางกลับกันคือ - อันดับแรกคุณcatch (const MyException& e)
ตามมาด้วยcatch (const std::exception& e)
ซึ่งตามมาด้วย
1) อย่างที่คุณเห็นเมื่อคุณรันโปรแกรมตามที่เป็นอยู่ประโยคแรกที่จับจะถูกดำเนินการ (ซึ่งอาจเป็นสิ่งที่คุณไม่ต้องการในตอนแรก)
2) แม้ว่าประเภทที่จับในประโยคแรกที่จับได้เป็นประเภทstd::exception
รุ่น "เหมาะสม" ของwhat()
จะถูกเรียก - เพราะมันถูกจับได้โดยอ้างอิง (เปลี่ยนอย่างน้อยstd::exception
ประเภทอาร์กิวเมนต์ที่ถูกจับจะเป็นค่า - และคุณจะได้สัมผัส ปรากฏการณ์ "การแบ่งวัตถุ" ในการทำงาน)
3) ในกรณีที่ "บางรหัสเนื่องจากความจริงที่ว่ามีข้อยกเว้น XXX ถูกโยน ... " ทำสิ่งที่สำคัญด้วยความเคารพต่อประเภทข้อยกเว้นมีการประพฤติผิดของรหัสของคุณที่นี่
4) สิ่งนี้ก็มีความเกี่ยวข้องเช่นกันหากวัตถุที่จับได้นั้นเป็นวัตถุ "ปกติ" เช่น: class Base{};
และclass Derived : public Base {}
...
5) g++ 7.3.0
บน Ubuntu 18.04.1 สร้างคำเตือนที่บ่งบอกถึงปัญหาที่กล่าวถึง:
ในฟังก์ชั่น 'void illustrateDerivedExceptionCatch ()': item12Linux.cpp: 48: 2: คำเตือน: ข้อยกเว้นประเภท 'MyException'จะถูกตรวจจับ (const MyException & e) ^ ~~~~
item12Linux.cpp: 43: 2: คำเตือน: โดยตัวจัดการก่อนหน้านี้สำหรับการจับ 'std :: exception'
(ข้อยกเว้น const & e) ^ ~~~~
อีกครั้งฉันจะบอกว่าคำตอบนี้เป็นเพียงการเพิ่มไปยังคำตอบอื่น ๆ ที่อธิบายไว้ที่นี่ (ฉันคิดว่าประเด็นนี้มีมูลค่าการกล่าวถึง แต่ยังไม่สามารถอธิบายได้ภายในความคิดเห็น)