التصريح عن مؤشرات الدوال
جزء من قسم Object Oriented Programming في رحلة C على Coddy — الدرس 33 من 61.
حتى الآن، تعلمنا محاكاة الوراثة باستخدام تضمين الـ struct. ولكن تعدد الأشكال (polymorphism) الحقيقي — حيث تستجيب الكائنات المختلفة بشكل مختلف لنفس الاستدعاء — يتطلب شيئاً أكثر: مؤشرات الدوال (function pointers).
مؤشر الدالة (function pointer) هو متغير يخزن عنوان دالة. تماماً كما يحمل المؤشر العادي عنوان البيانات، يحمل مؤشر الدالة عنوان كود قابل للتنفيذ.
قد يبدو بناء الجملة مخيفاً في البداية. للإعلان عن مؤشر دالة، يجب عليك تحديد نوع الإرجاع، ثم اسم المؤشر بين قوسين مع علامة النجمة، متبوعاً بأنواع المعاملات:
int (*operation)(int, int);يقوم هذا بتصريح متغير يسمى operation يمكنه الإشارة إلى أي دالة تأخذ معاملين من نوع int وتعيد قيمة من نوع int. الأقواس حول *operation ضرورية للغاية — فبدونها، ستكون بصدد التصريح عن دالة تعيد مؤشراً.
لتعيين دالة لهذا المؤشر، ببساطة استخدم اسم الدالة (بدون أقواس):
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).
تذكر: للتصريح عن مؤشر الدالة، تحتاج إلى نوع الإرجاع، واسم المؤشر بين قوسين مع علامة النجمة، وأنواع المعاملات. لتعيين دالة، استخدم اسم الدالة فقط بدون أقواس.
ورقة مرجعية
مؤشر الدالة (function pointer) هو متغير يخزن عنوان دالة، مما يتيح تعدد الأشكال (polymorphism) من خلال السماح باستدعاء دوال مختلفة عبر نفس المؤشر.
التصريح عن مؤشر دالة
تحدد الصيغة البرمجية نوع الإرجاع، واسم المؤشر مع وجود نجمة بين قوسين، وأنواع المعاملات:
int (*operation)(int, int);يصرح هذا عن operation كمؤشر لأي دالة تأخذ معاملين من نوع int وتعيد قيمة من نوع int. الأقواس حول *operation ضرورية.
إسناد دالة إلى مؤشر
استخدم اسم الدالة بدون أقواس:
int add(int a, int b) {
return a + b;
}
int (*operation)(int, int);
operation = add; // operation now points to addيعمل اسم الدالة كعنوان لها. يمكنك أيضاً استخدام &add بشكل صريح، لكنه أمر اختياري.
جرّب بنفسك
#include <stdio.h>
// مهام: قم بتعريف دالة الضرب هنا
// مهام: قم بتعريف دالة الطرح هنا
int main() {
int num1, num2, code;
// قراءة المدخلات
scanf("%d", &num1);
scanf("%d", &num2);
scanf("%d", &code);
// مهام: قم بالتصريح عن مؤشر دالة يسمى 'operation' يمكنه الإشارة إلى
// دوال تأخذ معاملين من نوع int وتعيد قيمة من نوع int
// مهام: بناءً على رمز العملية (1 للضرب، 2 للطرح)،
// قم بتعيين الدالة المناسبة لمؤشر العملية الخاص بك
// مهام: اطبع اسم العملية والنتيجة
// التنسيق:
// 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مشروع: رسّام الأشكال
نظرة عامة على المشروعتنفيذ الدائرة