الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

Pointers To Functions

مغلق
بدأه Robatic في 10 فبراير 2008 · 7 رد · 3,158 مشاهدة · في المواضيع والدروس
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ورحمة الله وبركاته

أخوتي في الله أسعد الله صباحكم أو مسائكم

سنتحدث اليوم عن المؤشرات وكيفية تسخيرها لجعلها تؤشر إلى داله

تمهيد

إذا أردنا أن نرى عنوان متغير ما في الذاكره نستخدم الـ & كما هو موضح في الكود التالي:

int x;
cout << &x << endl;

ماذا عن عنوان دالة ؟؟؟ طبعا علامة الـ & لا تنطبق على الدوال ولكن العملية ليست صعبه كل ما عليك فعله هو كتابة إسم الدالة فقط دون الأقواس، ولنفرض أن لدينا دالة بإسم myfunction، فإذا أردنا أن نعرف عنوانها نكتب كما يلي :

cout << myfunction << endl;

دعونا نسأل أنفسنا هذا السؤال : ما الفائده الناجمه عن معرفة عنوان دالة ما ؟؟

في الحقيقة معرفة عنوان أي داله لا يفيدك كمبرمج أو كمستخدم، إذا من المستفيد من ذلك ؟؟؟ المستفيد الأوحد هو الـ compiler أو البرنامج.

كيف لي أن أعرّف مؤشر إلى داله ؟

عن طريق القاعدة التاليه :

return_type (*pointer_name) (parameters_list) = function_name;

فإذا أردنا إستخدام ذلك المؤشر ( أي إستدعاء الدالة التي يؤشر عليها) نكتب كما يلي :

pointer_name(argument_list);

// or

(*poiter_name)(argument_list);

وكلتا الطريقتين صحيحه، والآن دعنا نأخذ مثال عملي فالتجربة خير برهان:

#include <iostream>

using namespace std;

int function1(int x) {
	return x * 10;
}

void function2() {
	cout << "Whatever!\n";
}

int main(void) {

	int (*fp1)(int) = function1;

	void (*fp2)() = function2; // or void (*fp2)(void) = function2;

	cout << fp1(10) << endl; // or cout << (*fp1)(10) << endl;

	(*fp2)(); // or (*fp2)(void); or fp2(); or fp2(void);

	return 0;
}

ماذا عن مصفوفة من المؤشرات للدوال ؟

قد يدل السؤال إلى شيء صعب ولكن في الحقيقه كل مافي الأمر هو تضمين علامة [ ] في التعريف كما هو موضح في القعدة التالية :

return_type (*pointer_name[])(parameter_list) = { function1, function2, function3, ..... , functionN };

ولكي ندخل إلى محتوى المصفوفه نستخدم القاعدة التاليه :

pointer_name[index](argument_list); // or (*pointer_name[index])(argument_list);

دعونا نطبق علميا :

#include <iostream>

using namespace std;

int getSquare(int x) { return x * x; }

int getCube(int x) { return x * x * x; }

int getQuad(int x) { return x * x * x * x; }

int main(void) {

	int (*fp[])(int) = { getSquare, getCube, getQuad };

	for(int i = 0; i < 3; i++)
		cout << fp(10) << endl;  // or cout << (*fp)(10) << endl;

	return 0;
}

بتعلم هذا التكتيك في البرمجه قد يفتح لك أو لكي بابا كبير حيث يمكنك أن تقوم بتعريف دوال قد يكون أحد القيم المرسله إليها مؤشراً إلى داله أو مصفوفة مؤشرات، ويمكنك أيضا بناء stack or queue بحيث كل عنصر فيها يؤشر إلى دالة ويتم تنفيذها وفق شروط معينه، فكر في حجم الإحتمالات الممكنه.

أسأل الله أن يكتب لي ولكم الأجر والثواب والفائده وأعوذ به من علم لا ينفع

أخوكم Robatic

1
#2

شكراً جزيلاً على الدرس الجميل

تعقيب بسيط ... كذلك عنوان الدالة مفيد جداً فى حالة الاحتياج لإستخدام Callback Functions

تم تعديل هذه المشاركة بواسطة Eng. Usama El-Mokadem في 10 فبراير 2008 في 11:36

Eng. Usama El-Mokadem

Nothing is impossible, the word impossible itself says that: I M - Possible

#3

سبقتني يا robatic ..

كنت محضر موضوع لمؤشرات الدوال ..

ولكن بالتاكيد فالشرح الذي كنت اريد وضعه لن يكن افضل مما وضعته انت ..

ولكن لو وجدت به بعض الامور التي يمكن ان تكمل موضوعك ساضعها هنا ليكتمل الموضوع ...

تحياتي العطرة ..

يَارَبُ إِن ضَاقَت قُلُوُب الْنَّاسٍ عَنْ مّافِي .. مِنْ خَيْرٍٍ فَعَفْوكَ لَا يَضِيْقْ ..

#4

السلام عليكم ورحمة الله وبركاته

اولا يشرفني ويسعدني مرور كل من المهند اسامة والأستاذ سنان

ثانيا والله يا استاذ سنان أخجلني تواضعك ويظهر إنه القلوب والعقول عند بعضها ويسرني إكمالك أو تعقيبك للموضوع

أخوكم Robatic

#5

السلام عليكم ,,

أخ Robatic لماذا تضع دروسك و تغيب فجأة B)

على كل حال مؤشرات الدوال هي من أمتع المواضيع, رغم أنها تحتاج لخبرة جيدة,

الحقيقة سأذكر مثالاً قمت بعمله عندما تعلمت الموضوع,

هل تعرفون معنى هذا السطر :

system( "pause" );

هذا السطر يقوم بعملية إيقاف مؤقت للبرنامج, و لكن هذه الطريقة ليست قياسية و تعتمد على نظام التشغيل إضافة إلى استهلاكها مصادر النظام بشكل بشع,

ما رأيكم بطريقة قياسية و الأجمل من ذلك أنها أنيقة B)

هذه إحدى تعريفات كائن الإدخال :

istream& operator>> (istream& ( *pf )(istream&));

بكل بساطة تستطيع استقبال مؤشر لدالة يمكنها تنفيذ أي شيء !!

كيف سنقوم بعمل الإيقاف المؤقت إذاً ؟

هذا هو الكود الذي قمت بكتابته :

std::istream& pause( std::istream& in ){

	in.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
	in.get();
	return in;
}

لكي تستخدمه كل ما عليك هو كتابة التالي :

string str;
std::cin >> str >> pause;

لنعتبره تطبيقاً للدرس الذي وضعه أخونا Robatic, و إذا كان هناك أي سؤال حول الكود نحن في الخدمة,

تحياتي ,,

تم تعديل هذه المشاركة بواسطة Khaled.Alshaya في 11 فبراير 2008 في 03:11

#6

الاعيبك جميلة يا خالد ..

والفكرة مفهومه وواضحه ..

فقط سؤال واحد ..

هل محتويات هذا السطر اجبارية ام انها تاتي من الدالة main ؟؟؟

numeric_limits<std::streamsize>::max()

وضح لي هذه النقطة فقط ..

تحياتي العطرة ..

يَارَبُ إِن ضَاقَت قُلُوُب الْنَّاسٍ عَنْ مّافِي .. مِنْ خَيْرٍٍ فَعَفْوكَ لَا يَضِيْقْ ..

#7

السلام عليكم ,,

مرحباً أخي سنان,

std::numeric_limits<std::streamsize>::max()

الصنف numeric_limits يستقبل نوع, و نستطيع عن طريقه الحصول على أكبر قيمة يمكن لهذا النوع أن يحملها,

و streamsize هو نوع معرف في مكتبة الـ IO تستخدمه الكائنات للإشارة إلى حجمها (حجم الـ Buffer الخاص بالكائن ),

تحياتي ,,

تم تعديل هذه المشاركة بواسطة Khaled.Alshaya في 12 فبراير 2008 في 05:28

#8

شكرا ياخالد على المعلومات القيمة .. وعلى الاضافة ..

تحياتي العطرة ..

يَارَبُ إِن ضَاقَت قُلُوُب الْنَّاسٍ عَنْ مّافِي .. مِنْ خَيْرٍٍ فَعَفْوكَ لَا يَضِيْقْ ..

هذا الموضوع مغلق.

مواضيع مشابهة