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

مؤشرات الدوال في الـ Structs

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

حتى الآن، استخدمنا مؤشرات الدوال كمتغيرات مستقلة أو مررناها كوسطاء. الخطوة التالية نحو تعدد الأشكال (polymorphism) هي تضمين مؤشر دالة مباشرة داخل struct — مما يمنح الـ struct سلوكاً خاصاً به.

عندما يحتوي الـ struct على مؤشر دالة (function pointer)، يمكن لكل مثيل (instance) أن يحمل دالة مختلفة. وهذا يعني أن كائنين من نفس النوع يمكن أن يتصرفا بشكل مختلف عند استدعاء مؤشر الدالة الخاص بهما:

typedef void (*PrintFunc)(const char*);

typedef struct {
    const char* name;
    PrintFunc print;  // مؤشر دالة كعضو
} Printer;

يحتوي الـ Printer struct الآن على عضوين: بيانات (name) وسلوك (print). لاستخدامه، تقوم بتعيين دالة للمؤشر أثناء التهيئة:

void loud_print(const char* msg) {
    printf("!!! %s !!!\n", msg);
}

int main() {
    Printer p;
    p.name = "Alert";
    p.print = loud_print;
    
    p.print("Hello");  // المخرجات: !!! Hello !!!
    return 0;
}

لاحظ كيف نقوم باستدعاء الدالة من خلال الـ struct: p.print("Hello"). يبدو هذا شبيهاً جداً باستدعاء ميثود (method) على كائن في لغات أخرى. يحمل الـ struct كلاً من بياناته والدالة التي تعمل عليها.

هذا النمط هو أساس تعدد الأشكال (polymorphism) في لغة C — حيث يمكن تعيين دوال مختلفة لمثيلات (instances) مختلفة، مما ينتج عنه سلوكيات مختلفة من نفس نوع الـ struct.

challenge icon

التحدي

سهل

لنقم ببناء نظام Notifier يوضح كيف يمكن للهياكل (structs) أن تحمل سلوكها الخاص من خلال مؤشرات الدوال (function pointers).

ستقوم بإنشاء ملفين لتنظيم الكود الخاص بك:

  • notifier.h: قم بتعريف نوع مؤشر دالة يسمى NotifyFunc يأخذ معامل من نوع const char* ولا يعيد شيئاً. ثم قم بتعريف هيكل Notifier يحتوي على name (من نوع const char*) ومؤشر دالة notify من النوع NotifyFunc.
  • main.c: قم بتضمين ملف الرأس الخاص بك وتنفيذ دالتي إشعار:
    • alert_notify — تطبع الرسالة بالتنسيق التالي: [ALERT] message
    • info_notify — تطبع الرسالة بالتنسيق التالي: [INFO] message
    ثم قم بإنشاء مثيل (instance) من Notifier، وقم بربط الدالة المناسبة بناءً على المدخلات، واستدعِ الإشعار من خلال مؤشر الدالة الخاص بالهيكل.

سيتلقى برنامجك مدخلين: نوع الإشعار (1 للتنبيه alert، و 2 للمعلومات info) و رسالة لعرضها.

بناءً على النوع، قم بتعيين الدالة المقابلة لعضو notify في الـ notifier الخاص بك، ثم استدعها من خلال الهيكل لعرض الرسالة.

مثال على المخرجات عندما يكون النوع 1 والرسالة "System starting":

[ALERT] System starting

مثال على المخرجات عندما يكون النوع 2 والرسالة "All systems normal":

[INFO] All systems normal

تذكر استخدام حراس التضمين (include guards) في ملف الرأس الخاص بك، واستدعاء الدالة من خلال عضو الهيكل: n.notify(message)

جرّب بنفسك

#include <stdio.h>
#include "notifier.h"

// TODO: تنفيذ دالة alert_notify
// يجب أن تطبع: [ALERT] message


// TODO: تنفيذ دالة info_notify
// يجب أن تطبع: [INFO] message


int main() {
    int type;
    char message[256];
    
    // قراءة المدخلات
    scanf("%d", &type);
    getchar(); // استهلاك السطر الجديد
    fgets(message, sizeof(message), stdin);
    
    // إزالة السطر الجديد الزائد من message إذا وجد
    int len = 0;
    while (message[len] != '\0') len++;
    if (len > 0 && message[len-1] == '\n') message[len-1] = '\0';
    
    // TODO: إنشاء مثيل (instance) من Notifier
    
    
    // TODO: بناءً على type (1 للتنبيه، 2 للمعلومات)،
    // تعيين الدالة المناسبة للعضو notify الخاص بـ notifier
    
    
    // TODO: استدعاء الإشعار من خلال مؤشر الدالة (function pointer) الخاص بـ struct
    // استخدم: n.notify(message)
    
    
    return 0;
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming