یکی از مواردی که برنامه‌نویسان ++C بخصوص برنامه‌نویسانی که تازه به این زبان روی آورده‌اند با آن مواجه هستند این است که به هنگام کار کردن با کتابخانه iostream نمیتوانند به درستی خطاها (Exception) را پوشش دهند. بطور مثال در کد زیر قصد داریم فایلی که وجود ندارد را باز کنیم و با استفاده از بلاک Try...Catch خطاهای احتمالی را پوشش دهیم:

#include <iostream>
#include <fstream>
using namespace std;

int main() {
ifstream file;
try {
file.open("IceCat.ir");
while (!file.eof()) {
cout << file.get();
}
}
catch (...) {
cout << "Error openning file..." << endl;
return 1;
}
file.close();
return 0;
}

اما با اجرای کد بالا با اینکه از بلاک Try...Catch برای هندل کردن Exceptionهای احتمالی استفاده کرده‌ایم،  مشاهده میکنیم که در صورت بوجود آمدن خطا (مانند وجود نداشتن فایل) بطور پی در پی عدد 1- در کنسول چاپ خواهد شد.

در این پست به علت بروز این امر و نحوه حل آن خواهیم پرداخت.

علت:

حقیقت این است که زبان ++C از روز اول برای کار با Exceptionها ساخته نشده بود (چرا که در اون موقع چیزی به اسم Exception Handeling وجود نداشت).  ساخت زبان "C with classes" در سال 1979 میلادی آغاز و Expectionها حدوداً 10 سال بعد یعنی در سال 1989 به آن اضافه شدند. در این بین کتابخانه streams در سال 1984 به این زبان اضافه شد، یعنی 6 سال قبل از افزوده شدن اکسپشن‌ها به ++C. به همین جهت کار کردن با اکسپشن‌ها در این کتابخانه نیازمند کمی تجربه و مهارت است.

 منابع:

        * کتاب A History of C++: 1979−1991، نوشته بی‌یارنه استراس‌تروپ (خالق زبان ++C)

        * کتابخانه‌های ++C

راه حل:

همانطور که گفته شد هندل کردن اکسپشن‌های ایجاد شده در کتابخانه iostream نیازمند اندکی مهارت است. برای اینکار باید با استفاده از متد exceptions و تعیین Bit Mask مورد نظر خودمون، قابلیت Throw کردن اکسپشن را برای استریم خود فعال کنیم.

به مثال زیر توجه کنید:

#include <iostream>
#include <fstream>
using namespace std;

int main() {
ifstream file;
file.exceptions (ifstream::failbit | ifstream::badbit);
try {
file.open("IceCat.ir");
while (!file.eof()) {
cout << file.get();
}
}
catch (ifstream::failure& e) {
cout << "Error opening file..." << endl;
return 1;
}
file.close();
return 0;
}

همانطور که ملاحظه میکنید تغییرات ما در خط 7 و 14 این کد اعمال شده اند. در خط 7 با استفاده از متد exceptions و تعیین Bit Mask های مربوطه امکان دریافت خطاهای ایجاد شده را فراهم کرده‌ایم. سپس در خط 14 مشخص کرده‌ایم که میخواهیم خطاهایی از نوع ifstream::failure را دریافت کنیم.

نکته‌ای که باقی میماند این است که در اکسپشن ایجاد شده (شی e در خط 14) قادر نیستم با فراخوانی متد ()what علت دقیق خطا را مشاهده کنیم. به همین دلیل بجای استفاده از دستور

e.what();

بطور مستقیم اقدام به چاپ پیام مورد نظر خودمان تحت عنوان Error opening file کرده‌ایم.

پی‌نوشت: در استاندارد ++C واژه‌ای به نام متد مفهومی ندارد. در متن بالا علت استفاده از واژه «متد» تنها برای درک ساده‌تر منظور ما بوده است. واژه صحیح، تابع (Function) میباشد.