التصريح عن مؤشرات الدوال
جزء من قسم Object Oriented Programming في رحلة C على Coddy — الدرس 33 من 61.
حتى الآن، تعلمنا كيفية محاكاة الوراثة باستخدام تضمين الهياكل (struct embedding). ولكن تعدد الأشكال (polymorphism) الحقيقي — حيث تستجيب الكائنات المختلفة بشكل مختلف لنفس الاستدعاء — يتطلب شيئًا إضافيًا: مؤشرات الدالة (function pointers).
مؤشر الـ function هو متغير يخزن عنوان function. تمامًا كما يحمل المؤشر العادي عنوان البيانات، يحمل مؤشر الـ function عنوان كود قابل للتنفيذ.
قد يبدو بناء الجملة (syntax) مخيفًا في البداية. لـ Declare `pointer` لـ `function`، تحدد نوع الـ `return`، ثم اسم الـ `pointer` بين قوسين مع علامة نجمية، يليه أنواع الـ `parameters`:
int (*operation)(int, int);يعلن هذا عن متغير يُسمى operation يمكنه الإشارة إلى أي function تأخذ اثنين من parameters من نوع int و return قيمة من نوع int. الأقواس المحيطة بـ *operation حاسمة — فبدونها، ستكون تعلن عن function تقوم بـ returning pointer.
لتعيين `function` إلى هذا `pointer`، استخدم ببساطة اسم الـ `function` (بدون أقواس):
int add(int a, int b) {
return a + b;
}
int (*operation)(int, int);
operation = add; // الآن operation يشير إلى addيعمل اسم الدالة كعنوان لها. يمكنك أيضًا استخدام &add صراحةً، لكنه اختياري — فكلا الشكلين متكافئان في لغة C.
التحدي
سهلدعنا نتدرب على الإعلان عن مؤشرات الدوارل (function pointers) وتعيين الدوال لها. ستنشئ نظام عمليات حسابية بسيط حيث يمكن لمؤشر الدالة أن يحمل دوال حسابية مختلفة.
اكتب برنامجًا يقوم بما يلي:
- يعرّف دالتين:
multiply— تأخذ معامِلين من نوعintوترجع حاصل ضربهماsubtract— تأخذ معامِلين من نوعintوترجع حاصل طرح الثاني من الأول
- في الدالة
main، يصرّح عن متغير مؤشر دالة يدعىoperationيمكنه الإشارة إلى دوال تأخذ معامِلين من نوعintوترجع قيمة من نوعint - يقرأ ثلاثة مدخلات: عددين صحيحين ورمز العملية (1 لـ multiply، و 2 لـ subtract)
- بناءً على رمز العملية، يقوم بتعيين الدالة المناسبة لمؤشر
operationالخاص بك - يطبع اسم العملية المعينة، ثم يطبع نتيجة استدعاء الدالة من خلال المؤشر
ستتلقى ثلاثة مدخلات: الرقم الأول، والرقم الثاني، ورمز العملية (1 أو 2).
يجب أن يبدو مخرجك كما يلي:
Operation: multiply
Result: 35حيث multiply هو اسم العملية (أو subtract إذا كان الرمز 2)، و 35 هي نتيجة استدعاء الدالة عبر المؤشر الخاص بك (في هذه الحالة، 5 × 7).
تذكر: للإعلان عن مؤشر الدالة، تحتاج إلى نوع الإرجاع، واسم المؤشر بين قوسين مع علامة النجمة (*)، وأنواع المعاملات. لتعيين دالة، استخدم اسم الدالة فقط بدون أقواس.
جرّب بنفسك
#include <stdio.h>
// TODO: عرّف دالة الضرب هنا
// TODO: عرّف دالة الطرح هنا
int main() {
int num1, num2, code;
// قراءة الإدخال
scanf("%d", &num1);
scanf("%d", &num2);
scanf("%d", &code);
// TODO: أعلن عن مؤشر دالة يسمى 'operation' يمكنه الإشارة إلى
// دوال تأخذ معاملين من نوع int وتُرجع int
// TODO: بناءً على رمز العملية (1 للضرب، 2 للطرح)،
// عيّن الدالة المناسبة إلى مؤشر العملية الخاص بك
// TODO: اطبع اسم العملية والنتيجة
// التنسيق:
// Operation: <name>
// Result: <result>
return 0;
}يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Object Oriented Programming
1أساسيات البرمجة التركيبية
ملفات الترويسةحواجز التضمينملفات المصدرالدوال الساكنةمراجعة: آلة حاسبة تركيبية4التغليف (Encapsulation)
مفهوم الـ Opaque Pointersتعريف الـ Opaque Structsالـ Getters والـ Settersالتحقق من البيانات في الـ Settersملخص: الصندوق السري7مؤشرات الدوال
التصريح عن مؤشرات الدوالاستدعاء مؤشرات الدوالاستخدام Typedef لمؤشرات الدوالتمرير الدوال كوسطاءمراجعة: Calculator Dispatch2الكائنات والأساليب
الـ Structs ككائناتمؤشر 'Self'صحة استخدام Constالمؤشر مقابل القيمةالأساليب المساعدةملخص: Point Manager5مشروع: حساب بنكي بسيط
إعداد المشروعتنفيذ الحساب3دورة حياة الكائن
نمط المنشئ (Constructor Pattern)نمط الهادم (Destructor Pattern)تهيئة الـ Stackالنسخ العميق (Deep Copy)مراجعة: String Wrapper6الوراثة عبر التركيب
تضمين الـ Structقاعدة العضو الأولالوصول إلى أعضاء الأبعملية الـ Upcastingمراجعة: هرمية الأشكال9مشروع: رسّام الأشكال
نظرة عامة على المشروعتنفيذ الدائرةتنفيذ المستطيلاستخدام تعدد الأشكالحاوية الأشكال