C++ معالجة الاستثناءات: حاول، التقط، ارمي مثال

⚡ ملخص ذكي

معالجة الاستثناء في C++ تُمكّن هذه الخاصية البرنامج من اكتشاف أخطاء وقت التشغيل والاستجابة لها باستخدام try وcatch وthrow، مما يمنع تعطل البرنامج. ستتعلم هنا الكلمات المفتاحية، والصيغة، والاستثناءات القياسية، والاستثناءات المُعرّفة من قِبل المستخدم مع أمثلة توضيحية.

  • ⚠️ ما هو : تعالج خاصية معالجة الاستثناءات أخطاء وقت التشغيل حتى يتمكن البرنامج من التعافي.
  • 🔑 : الكلمات المفتاحية يستخدم هذا النظام try لاختبار التعليمات البرمجية، و throw لرفع الأخطاء، و catch للتعامل معها.
  • 🧾 بناء الجملة: ضع التعليمات البرمجية الخطرة في كتلة try وقم بمعالجة الأخطاء في كتل catch.
  • 📚 الاستثناءات القياسية: C++ يوفر استثناءات مدمجة في رأس الاستثناء.
  • 🤖 مساعدة الذكاء الاصطناعي: تضيف أدوات الذكاء الاصطناعي مثل GitHub Copilot كتل try-catch ومعالجة الأخطاء.

C++ معالجة الاستثناء

ما هو التعامل مع الاستثناءات في C++?

معالجة الاستثناء في C++ يوفر لك طريقة للتعامل مع الظروف غير المتوقعة مثل أخطاء وقت التشغيل. ولذلك كلما حدثت ظروف غير متوقعة، يتم نقل التحكم في البرنامج إلى وظائف خاصة تعرف باسم المعالجات.

للتعرف على الاستثناءات، عليك وضع قسم من التعليمات البرمجية تحت فحص الاستثناءات. يتم وضع قسم التعليمات البرمجية داخل كتلة محاولة الالتقاط.

إذا حدث موقف استثنائي داخل هذا القسم من التعليمات البرمجية، فسيتم طرح استثناء. بعد ذلك، سيتولى معالج الاستثناء التحكم في البرنامج.

في حالة عدم حدوث أي ظروف استثنائية، سيتم تنفيذ التعليمات البرمجية بشكل طبيعي. سيتم تجاهل المعالجات.

في هذا C++ البرنامج التعليمي، سوف تتعلم:

لماذا التعامل مع الاستثناءات؟

إليك سبب استخدام معالجة الاستثناءات C++:

  • سوف تقوم بفصل كود معالجة الأخطاء الخاص بك عن الكود العادي. وسوف يكون الكود أكثر قابلية للقراءة وأسهل في الصيانة.
  • يمكن للوظائف التعامل مع الاستثناءات التي تختارها. حتى لو طرحت الدالة العديد من الاستثناءات، فإنها ستتعامل مع بعضها فقط. سيتعامل المتصل مع الاستثناءات التي لم يتم اكتشافها.

معالجة الاستثناءات للكلمات الرئيسية

معالجة الاستثناء في C++ تدور حول هذه الكلمات الرئيسية الثلاث:

  • رمي- عندما يواجه برنامج مشكلة ما، فإنه يطرح استثناء. تساعد الكلمة الأساسية throw البرنامج على تنفيذ الرمي.
  • قبض- يستخدم البرنامج معالج الاستثناء للقبض على الاستثناء. تتم إضافته إلى قسم البرنامج حيث تحتاج إلى معالجة المشكلة. يتم ذلك باستخدام الكلمة الأساسية الجذابة.
  • محاولة- تحدد كتلة المحاولة كتلة التعليمات البرمجية التي سيتم تنشيط استثناءات معينة لها. يجب أن يتبعه كتلة التقاط واحدة/أكثر.

لنفترض أن كتلة التعليمات البرمجية ستثير استثناءً. سيتم اكتشاف الاستثناء من خلال إحدى الطرق التي تستخدم الكلمات الرئيسية المحاولة والالتقاط. يجب أن تحيط كتلة المحاولة/الالتقاط بالتعليمات البرمجية التي قد تؤدي إلى استثناء. يُعرف هذا الرمز بالرمز المحمي.

بناء الجملة

تأخذ المحاولة/الالتقاط بناء الجملة هذا:

try {
   // the protected code
} catch( Exception_Name exception1 ) {
   // catch block
} catch( Exception_Name exception2 ) {
   // catch block
} catch( Exception_Name exceptionN ) {
   // catch block
}
  • على الرغم من أن لدينا عبارة محاولة واحدة، إلا أنه يمكن أن يكون لدينا العديد من عبارات الالتقاط.
  • اسم الاستثناء هو اسم الاستثناء الذي سيتم اكتشافه.
  • الاستثناء 1 والاستثناء 2 والاستثناء N هي الأسماء المحددة للإشارة إلى الاستثناءات.

مثال 1:

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

int main() {
	vector<int> vec;
	vec.push_back(0);	
	vec.push_back(1);	
	// access the third element, which doesn't exist
	try
	{
		vec.at(2);		
	}
	catch (exception& ex)
	{
		cout << "Exception occurred!" << endl;
	}
	return 0;
}

الإخراج:

معالجة الاستثناءات للكلمات الرئيسية

فيما يلي لقطة شاشة للكود:

معالجة الاستثناءات للكلمات الرئيسية

Code التفسير:

  1. قم بتضمين ملف رأس iostream في البرنامج لاستخدامه وظائف.
  2. قم بتضمين ملف رأس المتجه في البرنامج لاستخدام وظائفه.
  3. قم بتضمين مساحة الاسم std في البرنامج إلى فئاته دون استدعائها.
  4. استدعاء الدالة الرئيسية (). يجب إضافة منطق البرنامج داخل جسمه.
  5. قم بإنشاء متجه باسم vec لتخزين البيانات الصحيحة.
  6. أضف العنصر 0 إلى المتجه المسمى vec.
  7. أضف العنصر 1 إلى المتجه المسمى vec.
  8. تعليق. سيتم تخطيه بواسطة C++ مترجم.
  9. استخدم عبارة المحاولة للقبض على استثناء. يمثل { بداية نص كتلة المحاولة/الالتقاط. سيصبح الرمز المضاف داخل النص هو الرمز المحمي.
  10. حاول الوصول إلى العنصر المخزن في الفهرس 2 (العنصر الثالث) للناقل المسمى vec. هذا العنصر غير موجود.
  11. نهاية نص كتلة المحاولة/الالتقاط.
  12. قبض على الاستثناء. سيتم تخزين رسالة الخطأ التي تم إرجاعها في المتغير ex.
  13. اطبع بعض الرسائل على وحدة التحكم إذا تم اكتشاف الاستثناء.
  14. نهاية جسم كتلة الصيد.
  15. يجب أن يقوم البرنامج بإرجاع قيمة عند التنفيذ الناجح.
  16. نهاية نص الوظيفة الرئيسية ().

مثال 2:

#include <iostream>
using namespace std;
double zeroDivision(int x, int y) {

	if (y == 0) {
		throw "Division by Zero!";
	}
	return (x / y);
}

int main() {
	int a = 11;
	int b = 0;
	double c = 0;

	try {
		c = zeroDivision(a, b);
		cout << c << endl;
	}
	catch (const char* message) {
		cerr << message << endl;
	}
	return 0;
}

الإخراج:

معالجة الاستثناءات للكلمات الرئيسية

فيما يلي لقطة شاشة للكود:

معالجة الاستثناءات للكلمات الرئيسية

Code التفسير:

  1. قم بتضمين ملف رأس iostream في البرنامج لاستخدام وظائفه.
  2. قم بتضمين مساحة الاسم std في البرنامج إلى فئاته دون استدعائها.
  3. قم بإنشاء دالة باسم zeroDivision تأخذ وسيطتين صحيحتين، x وy. يجب أن تعيد الدالة نتيجة مزدوجة.
  4. استخدم عبارة if للتحقق مما إذا كانت قيمة وسيطة المتغير y هي 0. يمثل { بداية نص if.
  5. الرسالة التي سيتم إرجاعها/رميها إذا كانت y تساوي 0.
  6. نهاية نص عبارة if.
  7. يجب أن تقوم الدالة ZeroDivision بإرجاع قيمة x/y.
  8. نهاية نص الدالة ZeroDivision.
  9. استدعاء الطريقة الرئيسية (). يمثل { بداية هذه الطريقة.
  10. قم بتعريف متغير صحيح وتخصيص القيمة 11 له.
  11. قم بتعريف متغير عدد صحيح b وتخصيص القيمة 0 له.
  12. إعلان متغير مزدوج c وتعيين القيمة 0 له.
  13. استخدم عبارة المحاولة للقبض على استثناء. يمثل { بداية نص كتلة المحاولة/الالتقاط. سيصبح الرمز المضاف داخل النص هو الرمز المحمي.
  14. قم باستدعاء دالة zeroDivision وتمريرها إلى الوسيطتين a وb، أي 11 و0. سيتم تخزين نتيجة هذه العملية في المتغير c.
  15. اطبع قيمة المتغير c على وحدة التحكم.
  16. نهاية نص كتلة المحاولة/الالتقاط.
  17. قبض على الاستثناء. سيتم تخزين رسالة الخطأ التي تم إرجاعها في الرسالة المتغيرة.
  18. قم بطباعة رسالة الخطأ التي تم إرجاعها على وحدة التحكم.
  19. نهاية جسم كتلة الصيد.
  20. يجب أن يقوم البرنامج بإرجاع قيمة عند التنفيذ الناجح.
  21. نهاية نص الوظيفة الرئيسية ().

C++ الاستثناءات القياسية

C++ الاستثناءات القياسية

C++ يأتي مع قائمة الاستثناءات القياسية المحددة في فصل. هذه موصوفة أدناه:

استثناء الوصف
الأمراض المنقولة جنسيا::استثناء هذا استثناء والفئة الأم لجميع المعايير C++ استثناءات.
الأمراض المنقولة جنسيا::bad_alloc يتم طرح هذا الاستثناء بواسطة كلمة رئيسية جديدة.
الأمراض المنقولة جنسيا::bad_cast هذا استثناء تم طرحه بواسطةdynamic_cast.
الأمراض المنقولة جنسيا::bad_exception جهاز مفيد للتعامل مع الاستثناءات غير المتوقعة في C++ البرامج.
الأمراض المنقولة جنسيا::bad_typeid استثناء تم طرحه بواسطة typeid.
الأمراض المنقولة جنسيا::logic_error يمكن اكتشاف هذا الاستثناء نظريًا من خلال قراءة التعليمات البرمجية.
الأمراض المنقولة جنسيا::domain_error هذا استثناء تم طرحه بعد استخدام مجال غير صالح رياضيًا.
الأمراض المنقولة جنسيا::invalid_argument تم طرح استثناء لاستخدام وسيطات غير صالحة.
الأمراض المنقولة جنسيا :: length_error تم طرح استثناء بعد إنشاء سلسلة كبيرة::string.
الأمراض المنقولة جنسيا::out_of_range ألقيت في الأسلوب.
الأمراض المنقولة جنسيا::runtime_error هذا استثناء لا يمكن اكتشافه من خلال قراءة الكود.
الأمراض المنقولة جنسيا::overflow_error يتم طرح هذا الاستثناء بعد حدوث تجاوز رياضي.
الأمراض المنقولة جنسيا::range_error يتم طرح هذا الاستثناء عند محاولة تخزين قيمة خارج النطاق.
الأمراض المنقولة جنسيا::underflow_error تم طرح استثناء بعد حدوث التجاوز الرياضي.

الاستثناءات المحددة من قبل المستخدم

استخدم C++ تسمح لنا فئة std::exception بتعريف الكائنات التي يمكن طرحها كاستثناءات. وقد تم تعريف هذه الفئة في header. يزودنا الفصل بوظيفة عضو افتراضي تسمى ماذا.

تقوم هذه الدالة بإرجاع تسلسل أحرف منتهية بقيمة خالية من النوع char *. يمكننا الكتابة فوقه في الفئات المشتقة للحصول على وصف الاستثناء.

على سبيل المثال:

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

class newException : public exception
{
	virtual const char* what() const throw()
	{
		return "newException occurred";
	}
} newex;

int main() {

	try {
		throw newex;
		}
	catch (exception& ex) {
		cout << ex.what() << '\n';
	}
	return 0;	
}

الإخراج:

الاستثناءات المحددة من قبل المستخدم

فيما يلي لقطة شاشة للكود:

الاستثناءات المحددة من قبل المستخدم

Code التفسير:

  1. قم بتضمين ملف رأس iostream في برنامجنا. سوف نستخدم وظائفه دون الحصول على أخطاء.
  2. قم بتضمين ملف رأس الاستثناء في برنامجنا. سوف نستخدم وظائفها مثل ما دون أخطاء.
  3. قم بتضمين مساحة الاسم std في برنامجنا لاستخدام فئاتها دون استدعائها.
  4. قم بإنشاء فئة جديدة باسم newException. ترث هذه الفئة فئة الاستثناء C++.
  5. بداية الجسم الطبقي.
  6. قم بالكتابة فوق وظيفة العضو الظاهري () المحددة في ملف رأس الاستثناء. سنقوم بعد ذلك بوصف الاستثناء الخاص بنا، الاستثناء الجديد.
  7. ابدأ بتعريف الاستثناء الجديد.
  8. الرسالة التي سيتم إرجاعها إذا تم اكتشاف الاستثناء الجديد.
  9. انتهى تعريف الاستثناء الجديد.
  10. نهاية نص الفئة newException. newex هو الاسم الذي سيتم استخدامه لالتقاط الاستثناء الجديد، وبعده سيتم استدعاء newException.
  11. استدعاء الدالة الرئيسية (). يجب إضافة منطق البرنامج داخل جسمه. يمثل { بداية جسمه.
  12. استخدم عبارة محاولة لوضع علامة على الكود الذي نحتاج إلى وضع علامة الاستثناء فيه. يمثل { بداية نص كتلة المحاولة/الالتقاط. سيصبح الكود المحاط بهذا محميًا.
  13. قم برمي استثناء newex إذا تم اكتشافه.
  14. نهاية نص المحاولة.
  15. استخدم عبارة الصيد للقبض على الاستثناء. سيتم تخزين رسالة خطأ الاستثناء في المتغير ex.
  16. اطبع رسالة خطأ الاستثناء على وحدة التحكم.
  17. نهاية نص بيان الصيد.
  18. يجب أن يُرجع البرنامج قيمة إذا تم تنفيذه بنجاح.
  19. نهاية نص الدالة main().

الأسئلة الشائعة

تُعد معالجة الاستثناءات وسيلة لاكتشاف أخطاء وقت التشغيل والاستجابة لها في C++ باستخدام الكلمات المفتاحية try و throw و catch، حتى يتمكن البرنامج من التعافي بدلاً من التعطل.

C++ يستخدم ثلاث كلمات مفتاحية: try لتغليف التعليمات البرمجية التي قد تفشل، throw لإثارة استثناء عند حدوث خطأ، و catch للتعامل مع الاستثناء الذي تم طرحه.

ضع التعليمات البرمجية الخطرة في كتلة try، ثم اتبعها بكتلة catch واحدة أو أكثر، بحيث تتعامل كل منها مع نوع استثناء محدد يتم طرحه من كتلة try.

الاستثناءات القياسية هي فئات استثناءات مضمنة في رأس الاستثناء، مثل std::bad_alloc و std::out_of_range، والتي تقوم بالإبلاغ عن أخطاء وقت التشغيل الشائعة.

الاستثناء المعرف من قبل المستخدم هو فئة مخصصة، غالباً ما تكون مشتقة من std::exception، والتي تتجاوز وظيفة what() لوصف حالة الخطأ الخاصة بك.

تقوم المساعدات الذكية مثل GitHub Copilot بتغليف التعليمات البرمجية الخطرة في كتل try-catch، وإنشاء فئات استثناء مخصصة، واقتراح الاستثناءات التي يجب التقاطها أثناء الكتابة.

نعم. تكتشف الأدوات المدعومة بالذكاء الاصطناعي الاستثناءات غير المعالجة، وتقترح كتل معالجة محددة بدلاً من الكتل العامة، وتضيف رسائل خطأ ذات مغزى، مما يجعل تجربتك أكثر سهولة. C++ الكود أكثر متانة.

تقوم الدالة throw بإثارة استثناء عند اكتشاف خطأ، بينما تقوم الدالة catch باستقبال هذا الاستثناء وتشغيل الكود الذي يعالج الخطأ أو يبلغ عنه.

تلخيص هذه التدوينة بـ: