Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

تسلسلات الاستثناءات المخصصة

جزء من قسم Object Oriented Programming في رحلة C++ على Coddy — الدرس 82 من 104.

بينما توفر المكتبة القياسية فئات استثناءات مفيدة مثل std::runtime_error، غالبًا ما تستفيد التطبيقات الواقعية من إنشاء هيكليات استثناءات مخصصة. من خلال تعريف فئات الاستثناءات الخاصة بك والتي ترث من الاستثناءات القياسية، يمكنك إنشاء أنواع أخطاء خاصة بالمجال تحمل سياقًا إضافيًا وتسمح بمعالجة أخطاء أكثر دقة.

عادةً ما ترث فئة الاستثناء المخصصة من std::exception أو إحدى الفئات المشتقة منها وتتجاوز التابع what():

#include <exception>
#include <string>

class DatabaseException : public std::exception {
    std::string message;
public:
    DatabaseException(const std::string& msg) : message(msg) {}
    const char* what() const noexcept override { return message.c_str(); }
};

class ConnectionException : public DatabaseException {
public:
    ConnectionException(const std::string& host) 
        : DatabaseException("Failed to connect to: " + host) {}
};

class QueryException : public DatabaseException {
public:
    QueryException(const std::string& query) 
        : DatabaseException("Invalid query: " + query) {}
};

يسمح هذا التسلسل الهرمي لكتل catch بمعالجة الاستثناءات بمستويات مختلفة من التخصيص:

try {
    // عمليات قاعدة البيانات...
    throw ConnectionException("localhost");
} catch (const ConnectionException& e) {
    std::cout << "Connection issue: " << e.what() << "\n";
} catch (const DatabaseException& e) {
    std::cout << "Database error: " << e.what() << "\n";
} catch (const std::exception& e) {
    std::cout << "General error: " << e.what() << "\n";
}

يعد محدد noexcept في what() أمراً مهماً - فهو يضمن أن الدالة لن تطرح استثناءً، وهو أمر مطلوب من قبل واجهة الفئة الأساسية. قم بترتيب كتل catch الخاصة بك من الأكثر تحديداً إلى الأكثر عمومية، حيث تستخدم لغة C++ أول معالج مطابق.

challenge icon

التحدي

سهل

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

ستقوم بتنظيم الكود الخاص بك عبر ثلاثة ملفات:

  • FileExceptions.h: حدد التسلسل الهرمي المخصص للاستثناءات لعمليات الملفات.

    قم بإنشاء فئة أساسية FileException ترث من std::exception. يجب أن تخزن رسالة خطأ وتتجاوز (override) تابع what() مع محدد noexcept.

    ثم قم بإنشاء فئتين مشتقتين للاستثناءات:

    • FileNotFoundException — تأخذ اسم ملف وتنشئ رسالة: File not found: [filename]
    • PermissionDeniedException — تأخذ اسم ملف وتنشئ رسالة: Permission denied: [filename]

    يجب على كل فئة مشتقة استدعاء منشئ الفئة الأب بالرسالة المناسبة.

  • FileProcessor.h: حدد فئة FileProcessor تحاكي عمليات الملفات وتطرح استثناءاتك المخصصة.

    يجب أن تحتوي فئة FileProcessor على تابع openFile(const std::string& filename) يحاكي فتح ملف:

    • إذا كان اسم الملف يحتوي على missing، قم بطرح FileNotFoundException
    • إذا كان اسم الملف يحتوي على locked، قم بطرح PermissionDeniedException
    • خلاف ذلك، قم بإرجاع السلسلة النصية Successfully opened: [filename]
  • main.cpp: اقرأ اسم ملف واحد من المدخلات.

    قم بإنشاء FileProcessor وحاول فتح الملف. استخدم كتلة try-catch مع معالجات مرتبة من الأكثر تحديداً إلى الأكثر عموماً:

    1. التقط FileNotFoundException واطبع: File Error: [message]
    2. التقط PermissionDeniedException واطبع: Access Error: [message]
    3. التقط FileException واطبع: General File Error: [message]

    إذا لم يتم طرح أي استثناء، اطبع رسالة النجاح التي أرجعها التابع openFile().

على سبيل المثال، مع المدخلات report.txt:

Successfully opened: report.txt

مع المدخلات missing_data.csv:

File Error: File not found: missing_data.csv

مع المدخلات locked_config.ini:

Access Error: Permission denied: locked_config.ini

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

ورقة مرجعية

ترث فئات الاستثناءات المخصصة من std::exception أو الفئات المشتقة منها وتقوم بتجاوز (override) الدالة what():

#include <exception>
#include <string>

class DatabaseException : public std::exception {
    std::string message;
public:
    DatabaseException(const std::string& msg) : message(msg) {}
    const char* what() const noexcept override { return message.c_str(); }
};

قم بإنشاء تسلسلات هرمية للاستثناءات من خلال الوراثة من استثناءات أساسية مخصصة:

class ConnectionException : public DatabaseException {
public:
    ConnectionException(const std::string& host) 
        : DatabaseException("Failed to connect to: " + host) {}
};

تعامل مع الاستثناءات بمستويات مختلفة من التحديد عن طريق ترتيب كتل catch من الأكثر تحديداً إلى الأكثر عموماً:

try {
    throw ConnectionException("localhost");
} catch (const ConnectionException& e) {
    std::cout << "Connection issue: " << e.what() << "\n";
} catch (const DatabaseException& e) {
    std::cout << "Database error: " << e.what() << "\n";
} catch (const std::exception& e) {
    std::cout << "General error: " << e.what() << "\n";
}

يضمن المحدد noexcept في الدالة what() أن الطريقة لن تطلق استثناءً، وهو أمر مطلوب بواسطة واجهة الفئة الأساسية.

جرّب بنفسك

#include <iostream>
#include <string>
#include "FileExceptions.h"
#include "FileProcessor.h"

using namespace std;

int main() {
    string filename;
    cin >> filename;
    
    FileProcessor processor;
    
    // TODO: استخدم كتلة try-catch لمعالجة الاستثناءات (exceptions)
    // رتب المعالجات من الأكثر تحديداً إلى الأكثر عموماً:
    // 1. التقط FileNotFoundException - اطبع: "File Error: [message]"
    // 2. التقط PermissionDeniedException - اطبع: "Access Error: [message]"
    // 3. التقط FileException - اطبع: "General File Error: [message]"
    // إذا لم يحدث استثناء، اطبع رسالة النجاح من openFile()
    
    try {
        // TODO: استدعِ processor.openFile() وقم بمعالجة النتيجة
        
    }
    // TODO: أضف كتل catch بالترتيب من الأكثر تحديداً إلى الأكثر عموماً
    
    return 0;
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Object Oriented Programming