Favqulotda holatni ilib olish
throw yordamida favqulotda holat hosil qilinganda C++ bajaruvchi kutubxona funksiyasi quyidagi amallarni bajaradi:
favqulotda holat qayta ishlamaguncha mavjud bo’ladigan statik obyekt ko’rinishida throw parametri nusxasini yaratadi;
tegishli qayta ishlovchini izlash jarayonida amal qilish sohasidan chiquvchi lokal obyektlar destruktorlarini chaqirib stekka yoyadi;
bu obyekt bilan tip bo’yicha muvofiq parametrga ega qayta ishlovchiga obyekt va boshqaruvni beradi.
Stekni yoyishda barcha qayta ishlovchilar har bir saviyada ketma-ket, ichki blokdan tashqarisiga tegishli qayta ishlovchi topilmaguncha qarab chiqiladi.
Qayta ishlovchi topilgan deb hisoblanadi, agar throw dan keyin ko’rsatilgan obyekt tipi:
catch parametrida ko’rsatilgan bilan bir xil bo’lsa (parametr T, const T, &T yoki const T& shaklida yozilishi mumkin, bu yerda T favqulotda holat tipi);
catch parametrida ko’rsatilgandagining hosilasi bo’lsa (agar vorislik public kirish kaliti bilan amalga oshirilgan bo’lsa);
ko’rsatgichlarni almashtirish standart qoidalari bo’yicha catch parametridagi ko’rsatgich tipiga almashtirish mumkin bo’lgan ko’rsatgichdan iborat bo’lsa.
Yuqoridagilardan, hosila sinflar qayta ishlovchilarini bazaviy qayta ishlovchilargacha joylashtirish lozim, chunki aks holda hech qachon ularga boshqaruv berilmaydi. void tipidagi ko’rsatgich qayta ishlovchisini avtomatik ravishda ixtiyoriy boshqa tipdagi ko’rsatgichini yashiradi, shuning uchun uni ham konkret tipdagi ko’rsatgichlar qayta ishlovchilaridan keyin joylashtirish lozim.
Misol qaraymiz:
#include
class Hello{
// O’zining yaratilish va yo’qotilish haqida ma’lumot beruvchi sinf
public:
Hello(){cout << "Hello!" << endl;}
~Hello(){cout << "Bye!" << endl;}
};
void fl(){
ifstream ifs("\\INVALID\\FILE\\NAME"); // Faylni ochamiz
if (!ifs){
cout << "Favqulotda holatni hosil qilamiz" « endl;
throw "Faylni ochishda xato";}
}
void f2(){
Hello Н; // Lokal obyekt yaratamiz
f l(); // Favqulotda holatni hosil qiluvchi funksiyani chaqiramiz
}
int main(){
try{
cout << "try-blokka kiramiz" << endl;
f2();
cout << "try-blokdan chiqamiz" << endl;
}
catch(int i){
cout << "int qayta ishlovchi chaqirilgan favqulotda holat -" << i <return -1;
}
catch(const char * p){
cout << "const char* qayta ishlovchi chaqirilgan favqulotda holat - "
<< p << endl;
return -1;
}
catch(…){
cout << "Barcha favqulotda holatlar qayta ishlovchisi chaqirilgan" << endl;
return -1;
}
return 0; // Barchasi muvaffaqiyatli tugadi
}
Dasturni bajarish natijalari
try-blokka kiramiz
Hello!
Favqulotda holatni hosil qilamiz
Bye!
const char * qayta ishlovchi chaqirilgan. Favqulotda holat fayli ochishda xato.
E’tibor qiling, favqulotda holat hosil bo’lgandan so’ng lokal obyekt destruktori chaqrildi, vaholangki f1 funksiyadagi boshqaruv main funksiyasida joylashgan qayta ishlovchiga uzatilgan edi. “try-blokdan chiqamiz” xabari chiqarilmadi. Fayl bilan ishlash uchun dasturda oqimlardan foydalanildi.
Shunday qilib, favqulotda holatlar mexanizmi xato vaziyatlar paydo bo’lganda obyektlarni to’g’ri yo’qotishga imkon beradi. Shuning uchun zahiralarni ajratish va tozalashni konstruktori zahira ajratuvchi, destruktori tozalaydigan sinflar ko’rinishida rasmiylashtirish foydali. Misol uchun fayl bilan ishlash sinfini keltirish mumkin. Sinf konstruktori faylni ochadi, destruktori yopadi. Bu holda xato paydo bo’lganda fayl to’g’ri yopilishi va ma’lumot yo’qolmasligi kafolati mavjud.
Favqulotda holat standart tipda hamda foydalanuvchi aniqlagan tipda bo’lishi mumkin. Bunda bu tipni global aniqlash zarurati yo’q, u favqulotda holat paydo bo’lish nuqtasida va uni qayta ishlash nuqtasida ma’lum bo’lishi yetarli. Fayqulotda holatni taqdim etish uchun sinfni u bilan ishlashda paydo bo’lishi mumkin bo’lgan sinf ichida tavsiflash mumkin. Bu sinfning nusxalash konstruktori public kabi e’lon qilinishi lozim, chunki aks holda favqulotda holatni hosil qilishda obyekt nusxasini yaratish mumkin bo’lmaydi (jimlik bo’yicha yaratiladigan nusxalash konstruktori public spitsifikatorga ega).
Do'stlaringiz bilan baham: |