نمط الهادم (Destructor Pattern)
جزء من قسم البرمجة كائنية التوجه في رحلة C على Coddy. الدرس 13 من 61.
يجب في النهاية تحرير كل كائن تم إنشاؤه باستخدام malloc. وكما كتبنا دالة create_ للتعامل مع التخصيص، نكتب دالة free_ للتعامل مع التنظيف. يُسمّى هذا نمط المُدمّر.
الفكرة الأساسية هي أن عملية التحرير يجب أن تحدث بالترتيب العكسي لـ allocation. إذا كان constructor قد خصص internal members أولًا ثم البنية نفسها، فيجب على destructor أن يحرر members البنية أولًا، ثم البنية نفسها:
typedef struct {
char *name;
int age;
} Person;
void free_person(Person *p) {
if (p == NULL) return; // فحص السلامة
free(p->name); // حرر العضو الداخلي أولاً
free(p); // ثم حرر الـ struct نفسه
}
يمنع check الخاص بـ NULL في البداية حدوث الأعطال إذا مرّر أحدهم مؤشّرًا غير صالح عن طريق الخطأ. بعد تحرير سلسلة name internal، نقوم بتحرير البنية نفسها. إذا قمنا بتحرير p أولًا، فسوف نفقد الوصول إلى p->name ونتسبب في تسرّب في الذاكرة.
استخدام destructor أمر مباشر:
Person *alice = create_person("Alice", 30);
// ... استخدم alice ...
free_person(alice); // نظّف عند الانتهاء
يضمن هذا النمط تحرير كل memory بشكل صحيح. وبدونه، سيسرّب كل كائن تنشئه memory حتى تنفد من برنامجك.
التحدي
سهللنَبْنِ وحدة Movie توضّح دورة حياة الكائن كاملةً: الإنشاء والتدمير معًا. ستتدرّب على كتابة دالة destructor تنظّف جميع الذاكرة allocated بالترتيب الصحيح.
ستنشئ ثلاثة ملفات:
movie.h: Declare بنيةMovieتحتوي على عضوين:char *title(سلسلة نصية allocated dynamically) وint year. Declare كلًا من constructorcreate_movieالذي يستقبل title وyear، وdestructorfree_movieالذي يستقبل مؤشرًا إلى Movie. استخدم include guards بالرمزMOVIE_H.movie.c: Implement كلتا الدالتين. يجب أن يخصص constructor ذاكرة للبنية ولسلسلة title (لا forget null terminator). يجب أن يحرر destructor الذاكرة بترتيب عكسي للتخصيص: أولًا سلسلةtitleالداخلية، ثم البنية نفسها. أضف NULL check في بداية destructor لضمان الأمان.main.c: أنشئ movie، واعرض information الخاصة به، ثم نظّف الذاكرة بشكل صحيح.
ستتلقى inputين: عنوان movie (سلسلة نصية) وسنة الإصدار (عدد صحيح).
في ملف main، استخدم create_movie لإنشاء movie جديد، واطبع information الخاصة به، ثم استدعِ free_movie لتحرير كل الذاكرة. بعد التحرير، اطبع رسالة تأكيد.
اطبع output بهذا format:
Movie: {title} ({year})
Memory freedعلى سبيل المثال، عند استخدام inputين Inception و2010، سيكون output كما يلي:
Movie: Inception (2010)
Memory freedتذكّر: المفتاح إلى destructor سليم هو التحرير بالترتيب العكسي. كل ما يخصصه constructor أولًا يتم تحريره أخيرًا، وكل ما يخصصه أخيرًا يتم تحريره أولًا.
جرّب بنفسك
#include <stdio.h>
#include <stdlib.h>
#include "movie.h"
int main() {
char title[100];
int year;
// اقرأ الإدخال
scanf("%[^\n]", title);
scanf("%d", &year);
// TODO: أنشئ فيلمًا باستخدام create_movie
// TODO: اطبع معلومات الفيلم بالصيغة:
// فيلم: {title} ({year})
// TODO: حرّر الفيلم باستخدام free_movie
// TODO: اطبع "Memory freed"
return 0;
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات البرمجة التركيبية
ملفات الترويسةحواجز التضمينملفات المصدرالدوال الساكنةمراجعة: آلة حاسبة تركيبية4التغليف (Encapsulation)
مفهوم الـ Opaque Pointersتعريف الـ Opaque Structsالـ Getters والـ Settersالتحقق من البيانات في الـ Settersملخص: الصندوق السري2الكائنات والأساليب
الـ Structs ككائناتمؤشر 'Self'صحة استخدام Constالمؤشر مقابل القيمةالأساليب المساعدةملخص: Point Manager5مشروع: حساب بنكي بسيط
إعداد المشروعتنفيذ الحساب3دورة حياة الكائن
نمط المنشئ (Constructor Pattern)نمط الهادم (Destructor Pattern)تهيئة الـ Stackالنسخ العميق (Deep Copy)مراجعة: String Wrapper6الوراثة عبر التركيب
تضمين الـ Structقاعدة العضو الأولالوصول إلى أعضاء الأبعملية الـ Upcastingمراجعة: هرمية الأشكال9مشروع: رسّام الأشكال
نظرة عامة على المشروعتنفيذ الدائرةتنفيذ المستطيلاستخدام تعدد الأشكالحاوية الأشكالتدرّب بنفسك: مترجم C عبر الإنترنت