Ingin ADD untuk jawaban yang lain dijelaskan di sini catatan tambahan, dalam kasus pengecualian kustom .
Dalam kasus di mana Anda membuat pengecualian kustom Anda sendiri, yang berasal dari std::exception
, ketika Anda menangkap jenis pengecualian "semua mungkin", Anda harus selalu memulai catch
klausa dengan jenis pengecualian "paling banyak diturunkan" yang mungkin ditangkap. Lihat contoh (apa yang TIDAK harus dilakukan):
#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;
}
CATATAN:
0) Urutan yang tepat harus sebaliknya, yaitu- pertama Anda catch (const MyException& e)
yang diikuti oleh catch (const std::exception& e)
.
1) Seperti yang Anda lihat, ketika Anda menjalankan program seperti, menangkap klausa pertama akan dieksekusi (yang mungkin apa yang Anda lakukan tidak ingin di tempat pertama).
2) Meskipun tipe yang ditangkap dalam klausa tangkapan pertama adalah tipe std::exception
, versi "tepat" what()
akan dipanggil - karena itu ditangkap dengan referensi (ubah setidaknya std::exception
tipe argumen yang tertangkap menjadi berdasarkan nilai - dan Anda akan mengalami fenomena "mengiris objek" dalam aksi).
3) Seandainya "beberapa kode disebabkan oleh fakta bahwa pengecualian XXX dilempar ..." melakukan hal-hal penting DENGAN MENGHORMATI jenis pengecualian, ada kesalahan kode di sini.
4) Ini juga relevan jika objek yang ditangkap adalah objek "normal" seperti: class Base{};
dan class Derived : public Base {}
...
5) g++ 7.3.0
di Ubuntu 18.04.1 menghasilkan peringatan yang menunjukkan masalah yang disebutkan:
Dalam fungsi 'void illustrateDerivedExceptionCatch ()': item12Linux.cpp: 48: 2: peringatan: pengecualian tipe 'MyException' akan tertangkap basah (const MyException & e) ^ ~~~~
item12Linux.cpp: 43: 2: peringatan: oleh handler sebelumnya untuk
tangkapan 'std :: exception' (exception const & e) ^ ~~~~
Sekali lagi , saya akan mengatakan, bahwa jawaban ini hanya untuk TAMBAH ke jawaban lain yang dijelaskan di sini (saya pikir poin ini layak disebutkan, namun tidak dapat menggambarkannya dalam komentar).