19-ma’ruza. Istisnoli holatlar spesifikasiyasi. Istisnoli holatlar sinflari. exception sinf interfeysi. C++ standart kutubxonasidagi ko'plab sinflar va operatorlar muvaffaqiyatsizlikka uchragan holda istisno sinflarini chiqaradilar. Masalan, new operatori va string xotirasi tugashi bilan bad_alloc ni tashlashi mumkin. dynamic_cast operatori yordamida bajarilmagan dinamik translatsiya bad_cast istisno va hokazolarni chiqaradi. C++14 dan beri 20 dan ortiq istisno sinflari mavjud va C++17 da bundan ham ko'proq.
Yaxshi xabar shundaki, ushbu istisno sinflarining barchasi exception sinfining avlodlari. exception – bu C++ standart kutubxonasiga tashlangan har qanday istisno uchun ajdod-sinf sifatida ishlatiladigan kichik oldingi sinf.
Ko'pincha, agar istisno C ++ standart kutubxonasi tomonidan tashlangan bo'lsa, bu noto'g'ri taqsimlash, konvertatsiya yoki boshqa biror narsa bo'lganiga ahamiyat bermaymiz. Bizning dasturimiz ishdan chiqishiga sabab bo'lgan halokatli voqea sodir bo'lganligini bilish kifoya. exception tufayli biz exception kabi istisno ishlovchisini o‘rnatishimiz mumkin, u ikkala exception va barcha (20 dan ortiq) avlod istisno sinflarini ushlab turadi va boshqaradi!
#include
#include #include using namespace std;
int main()
{
try
{
// C ++ standart kutubxonasidan foydalanadigan kod shu yerda bo'lishi kerak.
// Endi biz ataylab tashlanadigan istisnolardan birini ishga tushiramiz
string s;
s.resize(-1); // bad_alloc istisnosini generatsiyalash
}
// Ushbu ishlov beruvchi exception va uning barcha avlod istisno sinflarini ushlaydi
catch (exception &exception)
{
cerr << "Standard exception: " << exception.what() << '\n';
}
return 0;
}
Dasturni bajarish natijasi:
Standart istisno: qator juda uzun
Bu misol juda oddiy. exception tavsiflovchi C uslubidagi qatorni qaytaruvchi virtual what() metodiga ega. Ko'pgina avlod sinflari ushbu xabarni o'zgartirish orqali what() funksiyasini bekor qiladi. E'tibor bering, ushbu C uslubidagi satr faqat tavsiflash uchun mo'ljallangan.
Ba'zan biz istisnolarning ma'lum bir turini boshqa turdagi istisnolardan biroz boshqacha tarzda hal qilishimiz kerak bo'ladi. Bunday holda, biz ushbu maxsus tur uchun istisno ishlovchisini qo'shishimiz mumkin va boshqa barcha istisnolar ajdod ishlov beruvchisiga "qayta yo'naltirish" mumkin. Masalan:
try
{
// C ++ standart kutubxonasidan foydalanadigan kod bu yerga kirishi kerak
}
// Ushbu ishlov beruvchi bad_alloc va uning barcha avlod istisno sinflarini ushlaydi
catch (bad_alloc &exception)
{
cerr << "You ran out of memory!" << '\n';
}
// Ushbu ishlov beruvchi istisno va uning barcha avlod istisno sinflarini ushlaydi
catch (exception &exception)
{
cerr << "Standard exception: " << exception.what() << '\n';
}
Ushbu misolda bad_alloc turidagi istisnolar birinchi ishlov beruvchi tomonidan ushlanadi va boshqariladi. exception tipidagi istisnolar va boshqa barcha avlod istisno sinflari ikkinchi ishlov beruvchi tomonidan boshqariladi.
Bunday meros iyerarxiyasi muayyan turdagi istisnolarni qo'lga olish uchun maxsus ishlov beruvchilardan yoki butun istisnolar ierarxiyasini ushlab turish uchun bitta (ajdod) ishlov beruvchidan foydalanish imkonini beradi.
#include
#include int main()
{
try
{
throw runtime_error("Yomon narsalar sodir bo'ldi");
}
// Ushbu ishlov beruvchi exception va uning barcha avlod sinflari-istisnolarini ushlaydi
catch (exception &exception)
{
cerr << "Standard exception: " << exception.what() << '\n';
}
return 0;
}