Rakstot dažus RAII prototipus nonācu konfliktā ar aizliegumu lietot izņēmumus destruktorā. Googlē atradās pāris raksti par to, kāpēc tas ir slikti un nepabeigts raksts par to, ka tas nav nemaz tik slikti.
Es nepārstāstīšu visu, ko var atrast sekojot saitēm, tādēļ mans konspekts par problēmu ir apmēram šāds:
- destruktoram nevajag darīt pārāk daudz, tikai pašu minimumu
- ļaunums: ja destruktors rada izņēmumu brīdī, kad tiek apstrādāts kāds cits izņēmums, programma beigs darbu ar
std::terminate - hipotēze: jebkurš ne-triviāls destruktors potenciāli var radīt izņēmumu
- viens risinājums: aizliedzot izņēmumu radīšanu destruktorā par kļūdu nākas ziņot globālajā mainīgajā (piemēram,
errno), tādā veidā atgriežoties gadus 30 senā pagātnē - otrs risinājums: rakstot metodi, kas veic destruktora pienākumus un var radīt izņēmumus, zūd destruktora jēga
Izlasot visus “par” un “pret”, tomēr sliecos atbalstīt šādu variantu:
T::~T() {
// ... do cleanup
if (error) {
if (!std::uncaught_exception()) {
throw Something();
} else {
fprintf(stderr, "Something happened\n");
}
}
}
Ja jau notiek izņēmuma apstrāde (std::uncaught_exception), tad pietiks ar kļūdas izdruku destruktorā vai klusēšanu, jo īstais programmas kļūdas cēlonis ir cits izņēmums. Ja izņēmumu apstrāde nenotiek, tad var radīt izņēmumu un ziņot par kļūdu. Š āds destruktors zemāk redzamajā kodā neradīs izņēmumu, lai gan to drīkstētu darīt, tomēr hei – arī daudzām citām klasēm ir nosacījumi, kad tās strādā un kad tās nedrīkst lietot, kaut vai std::auto_ptr.
U::~U() {
try {
T t;
// do work
} catch( ... ) {
// clean up
}
}
Pārējie argumenti pret šo variantu ir pārāk līdzīgi “neveikt aritmētiskas operācijas ar rādītājiem”, “neoptimizēt (pagaidām)”, utml. Jāņem vērā, jāuzmanās, nav jālieto vienmēr, nav pilnīgi viss darbs jādara destruktorā, bet izņēmumu radīšana destruktorā nav nāves grēks vai kaut kas amorāls.
Padomāšu par to W:O:A viskija sapņos.




