Menu
CoddyTech
flag Ar iconالعربيةdown icon

تعمق في الموادم

جزء من قسم البرمجة كائنية التوجه في رحلة C++ على Coddy. الدرس 24 من 104.

‏المُدمِّر هو دالة عضو خاصة تُنفَّذ تلقائيًا عند تدمير كائن. وتتمثل مهمته الأساسية في تحرير الموارد التي حصل عليها الكائن خلال فترة حياته، مثل الذاكرة المخصَّصة ديناميكيًا، أو معالجات الملفات، أو اتصالات الشبكة.

للمُدمِّر الاسم نفسه الذي يحمله الصنف، مسبوقًا بعلامة التلدة ~. ولا يأخذ أي معاملات وليس له نوع إرجاع:

class FileHandler {
    std::string filename;
    int* buffer;
public:
    FileHandler(std::string name, size_t size) 
        : filename(name), buffer(new int[size]) {
        std::cout << "Opening " << filename << "\n";
    }
    ~FileHandler() {
        delete[] buffer;
        std::cout << "Closing " << filename << "\n";
    }
};

يتم استدعاء المُدمّرات تلقائيًا في هذه الحالات:

  • تخرج كائنات المكدس من النطاق
  • يُستدعى delete على كائن مخصّص في الذاكرة الديناميكية
  • تنتهي فترة حياة كائن مؤقت
void example() {
    FileHandler f1("data.txt", 100);    // تم استدعاء المُنشئ
    FileHandler* f2 = new FileHandler("log.txt", 50);
    delete f2;                           // تم استدعاء المُدمِّر لـ f2
}   // تم استدعاء المُدمِّر لـ f1 (يخرج من النطاق)

على عكس المُنشئات، يمكن أن يكون للفئة مُدمّر واحد فقط. لا يمكنك تحميله بشكل زائد.

إذا لم تُعرِّف واحدًا، يُنشئ المصرّف مُدمِّرًا افتراضيًا لا يفعل شيئًا خاصًا - بل يُدمّر كل عضو ببساطة. بالنسبة إلى الفئات التي تدير الموارد، يجب أن تكتب مُدمِّرك الخاص لمنع تسرّبات الذاكرة.

challenge icon

التحدي

سهل

لنَبْنِ مديرًا للجلسات يتتبّع جلسات المستخدمين النشطة ويوضّح كيف تنظّف المدمرات الموارد تلقائيًا عند تدمير الكائنات، سواء خرجت من النطاق أو حُذفت صراحةً.

ستُنشئ ملفين لتنظيم شفرتك:

  • Session.h: عرّف فئة Session تمثّل جلسة مستخدم نشطة تحتوي على بيانات مخصّصة ديناميكيًا. يجب أن تحتوي فئتك على:
    • أعضاء خاصون: username (سلسلة نصية)، وsessionId (عدد صحيح)، ومؤشر إلى مصفوفة أعداد صحيحة تُسمّى activityLog لتتبّع إجراءات المستخدم، بالإضافة إلى logSize لحجم المصفوفة
    • منشئ يستقبل اسم مستخدم ومعرّف جلسة وحجم سجل. يجب أن يخصّص مصفوفة سجل الأنشطة على الكومة، ويهيّئ جميع العناصر إلى 0، ويطبع "Session <sessionId> started for <username>"
    • مدمر يحرّر الذاكرة المخصّصة ويطبع "Session <sessionId> ended for <username>"
    • طريقة logActivity(int activityCode) تخزّن رمز النشاط في الخانة المتاحة التالية (مع تتبّع الموضع الحالي داخليًا)؛ وإذا كان السجل ممتلئًا بالفعل، يتم تجاهل الاستدعاء، ولذلك لا يتجاوز العدد حجم السجل
    • طريقة getActivityCount() تعيد عدد الأنشطة التي تم تسجيلها
    • طريقة getUsername() تعيد اسم المستخدم
  • main.cpp: وضّح سلوك المدمر في سيناريوهات مختلفة. اقرأ اسم مستخدم وحجم سجل من الإدخال (كلٌّ منهما في سطر منفصل)، ثم:
    • أنشئ كتلة نطاق باستخدام الأقواس المعقوفة { }، وأنشئ داخلها كائن Session مخصّصًا على المكدس باستخدام اسم المستخدم المُدخل، ومعرّف الجلسة 101، وحجم السجل المُدخل. سجّل نشاطين بالرمزين 1 و2، ثم اطبع "Stack session activities: <count>". عند انتهاء الكتلة، يجب أن يعمل المدمر تلقائيًا.
    • بعد الكتلة، اطبع "Stack session destroyed"
    • أنشئ كائن Session مخصّصًا على الكومة باستخدام new، باسم المستخدم "Guest"، ومعرّف الجلسة 202، وحجم السجل 3. سجّل نشاطًا واحدًا بالرمز 5، واطبع "Heap session activities: <count>"، ثم احذفه صراحةً باستخدام delete.
    • بعد الحذف، اطبع "Heap session destroyed"

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

ضمّن ملف الترويسة في main.cpp باستخدام #include "Session.h".

جرّب بنفسك

#include <iostream>
#include <string>
#include "Session.h"

using namespace std;

int main() {
    // اقرأ المدخلات
    string username;
    int logSize;
    getline(cin, username);
    cin >> logSize;
    
    // TODO: أنشئ كتلة نطاق بأقواس معقوفة { }
    // داخل الكتلة:
    //   - أنشئ Session مخصصًا على المكدس مع اسم المستخدم المدخل، ومعرف الجلسة 101، وحجم السجل المدخل
    //   - سجّل نشاطين بالكودين 1 و 2
    //   - Print "Stack session activities: <count>"
    // عندما تنتهي الكتلة، يعمل المدمر تلقائيًا
    
    // TODO: After the block, print "Stack session destroyed"
    
    // TODO: أنشئ Session مخصصًا على الكومة باستخدام new
    //   - اسم المستخدم: "Guest"، معرف الجلسة: 202، حجم السجل: 3
    //   - سجّل نشاطًا واحدًا بالكود 5
    //   - Print "Heap session activities: <count>"
    //   - احذف الجلسة
    
    // TODO: After deletion, print "Heap session destroyed"
    
    return 0;
}
quiz iconاختبر نفسك

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

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم C++ عبر الإنترنت