وظيفة رد الاتصال في C ++

Callback Function C



وظيفة رد الاتصال هي دالة ، وهي وسيطة ، وليست معلمة ، في دالة أخرى. يمكن تسمية الوظيفة الأخرى بالوظيفة الرئيسية. لذلك يتم تضمين وظيفتين: الوظيفة الأساسية ووظيفة رد الاتصال نفسها. في قائمة معلمات الوظيفة الرئيسية ، يوجد إعلان عن وظيفة رد الاتصال بدون تعريفها ، تمامًا كما توجد إعلانات كائن بدون تخصيص. يتم استدعاء الوظيفة الأساسية مع الوسيطات (in main ()). إحدى الوسائط في استدعاء الوظيفة الأساسية هي التعريف الفعال لدالة رد الاتصال. في C ++ ، تعتبر هذه الوسيطة مرجعًا لتعريف دالة رد الاتصال ؛ ليس هذا هو التعريف الفعلي. يتم استدعاء وظيفة رد الاتصال نفسها في الواقع ضمن تعريف الوظيفة الأساسية.

لا تضمن وظيفة رد الاتصال الأساسية في C ++ السلوك غير المتزامن في البرنامج. السلوك غير المتزامن هو الفائدة الحقيقية لنظام وظيفة رد الاتصال. في نظام وظيفة رد الاتصال غير المتزامن ، يجب الحصول على نتيجة الوظيفة الأساسية للبرنامج قبل الحصول على نتيجة وظيفة رد الاتصال. من الممكن القيام بذلك في C ++ ؛ ومع ذلك ، يحتوي C ++ على مكتبة تسمى المستقبل لضمان سلوك نظام وظيفة رد الاتصال غير المتزامن.







تشرح هذه المقالة نظام وظيفة رد الاتصال الأساسي. الكثير منه مع C ++ النقي. بقدر ما يتعلق الأمر بمعاودة الاتصال ، يتم أيضًا شرح السلوك الأساسي للمكتبة المستقبلية. المعرفة الأساسية لـ C ++ ومؤشراتها ضرورية لفهم هذه المقالة.



محتوى المادة

مخطط وظيفة رد الاتصال الأساسية

يحتاج نظام وظيفة رد الاتصال إلى وظيفة أساسية ، ووظيفة رد الاتصال نفسها. إعلان وظيفة رد الاتصال هو جزء من قائمة معلمات الوظيفة الأساسية. يشار إلى تعريف وظيفة رد الاتصال في استدعاء الوظيفة للوظيفة الأساسية. يتم استدعاء وظيفة رد الاتصال في الواقع ضمن تعريف الوظيفة الأساسية. البرنامج التالي يوضح هذا:



#يشمل

استخدام مساحة الاسمساعات؛



intرئيسي(شارالفصل[]وint (*ptr)(int))

{

intمعرف 1= 1؛

intمعرف 2= 2؛

intعادة= (*ptr)(معرف 2)؛

كلفة<<'الوظيفة الأساسية':<<معرف 1<<'<<الفصل<<'<<عادة<<'ن'؛

إرجاعمعرف 1؛

}


intcb(intمعرف)

{

كلفة<<'وظيفة رد الاتصال'<<'ن'؛

إرجاعمعرف؛

}


intالأساسية()

{

int (*ptr)(int) = &cb؛

شارلا[] = 'و'؛

رئيسي(الأب ، cb)؛



إرجاع 0؛

}

الخرج هو:





وظيفة رد الاتصال

الوظيفة الرئيسية: 1 و 2

يتم تحديد الوظيفة الرئيسية من خلال mainFn (). يتم تحديد وظيفة رد الاتصال بواسطة cb (). يتم تعريف وظيفة رد الاتصال خارج الوظيفة الأساسية ولكن يتم استدعاؤها بالفعل داخل الوظيفة الأساسية.

لاحظ إعلان وظيفة رد الاتصال كمعامل في قائمة المعلمات لإعلان الوظيفة الأساسية. إعلان وظيفة رد الاتصال هو int (* ptr) (int). لاحظ تعبير دالة رد الاتصال ، مثل استدعاء دالة ، في تعريف الوظيفة الأساسية ؛ يتم تمرير أي وسيطة لاستدعاء وظيفة رد الاتصال هناك. بيان استدعاء الوظيفة هذا هو:



intعادة= (*ptr)(معرف 2)؛

حيث id2 حجة. ptr هو جزء من المعلمة ، المؤشر ، الذي سيتم ربطه بمرجع وظيفة رد الاتصال في الدالة main ().

لاحظ التعبير:

int (*ptr)(int) = &cb؛

في دالة main () ، التي تربط التصريح (بدون تعريف) لوظيفة رد الاتصال باسم تعريف وظيفة رد النداء نفسها.

تسمى الوظيفة الرئيسية ، في الوظيفة () الرئيسية ، على النحو التالي:

رئيسي(الأب ، cb)؛

حيث cha عبارة عن سلسلة و cb هو اسم وظيفة رد الاتصال بدون أي وسيط لها.

السلوك المتزامن لوظيفة رد الاتصال

ضع في اعتبارك البرنامج التالي:

#يشمل

استخدام مساحة الاسمساعات؛



فارغرئيسي(فارغ (*ptr)())

{

كلفة<<'الوظيفة الرئيسية'<<'ن'؛

(*ptr)()؛

}


فارغcb()

{

كلفة<<'وظيفة رد الاتصال'<<'ن'؛

}


فارغالجبهة الوطنية()

{

كلفة<<'رأيت'<<'ن'؛

}


intالأساسية()

{

فارغ (*ptr)() = &cb؛

رئيسي(cb)؛

الجبهة الوطنية()؛



إرجاع 0؛

}

الخرج هو:

الوظيفة الرئيسية

وظيفة رد الاتصال

رأيت

هناك وظيفة جديدة هنا. كل ما تفعله الوظيفة الجديدة ، هو عرض الإخراج ، مرئي. في الوظيفة () الرئيسية ، يتم استدعاء الوظيفة الرئيسية ، ثم يتم استدعاء الوظيفة الجديدة ، fn (). يوضح الإخراج أنه تم تنفيذ رمز الوظيفة الأساسية ، ثم تم تنفيذ ذلك الخاص بوظيفة رد الاتصال ، وأخيراً تم تنفيذ ذلك الخاص بوظيفة fn (). هذا هو السلوك المتزامن (مترابط واحد).

إذا كان سلوكًا غير متزامن ، فعند استدعاء ثلاثة أجزاء من التعليمات البرمجية بالترتيب ، يمكن تنفيذ مقطع الرمز الأول ، متبوعًا بدلاً من ذلك بتنفيذ مقطع الرمز الثالث ، قبل تنفيذ مقطع الرمز الثاني.

حسنًا ، يمكن استدعاء الوظيفة fn () من داخل تعريف الوظيفة الرئيسية ، بدلاً من استدعاء الوظيفة الرئيسية () ، على النحو التالي:

#يشمل

استخدام مساحة الاسمساعات؛



فارغالجبهة الوطنية()

{

كلفة<<'رأيت'<<'ن'؛

}


فارغرئيسي(فارغ (*ptr)())

{

كلفة<<'الوظيفة الرئيسية'<<'ن'؛

الجبهة الوطنية()؛

(*ptr)()؛

}


فارغcb()

{

كلفة<<'وظيفة رد الاتصال'<<'ن'؛

}


intالأساسية()

{

فارغ (*ptr)() = &cb؛

رئيسي(cb)؛



إرجاع 0؛

}

الخرج هو:

الوظيفة الرئيسية

رأيت

وظيفة رد الاتصال

هذا تقليد للسلوك غير المتزامن. إنه ليس سلوكًا غير متزامن. إنه لا يزال سلوكًا متزامنًا.

أيضًا ، يمكن تبديل ترتيب تنفيذ مقطع الكود الخاص بالوظيفة الرئيسية ومقطع الكود الخاص بوظيفة رد الاتصال في تعريف الوظيفة الأساسية. البرنامج التالي يوضح هذا:

#يشمل

استخدام مساحة الاسمساعات؛



فارغرئيسي(فارغ (*ptr)())

{

(*ptr)()؛

كلفة<<'الوظيفة الرئيسية'<<'ن'؛

}


فارغcb()

{

كلفة<<'وظيفة رد الاتصال'<<'ن'؛

}


فارغالجبهة الوطنية()

{

كلفة<<'رأيت'<<'ن'؛

}


intالأساسية()

{

فارغ (*ptr)() = &cb؛

رئيسي(cb)؛

الجبهة الوطنية()؛



إرجاع 0؛

}

الإخراج الآن ،

وظيفة رد الاتصال

الوظيفة الرئيسية

رأيت

هذا أيضًا تقليد للسلوك غير المتزامن. إنه ليس سلوكًا غير متزامن. إنه لا يزال سلوكًا متزامنًا. يمكن الحصول على السلوك غير المتزامن الحقيقي كما هو موضح في القسم التالي أو مع المكتبة ، في المستقبل.

السلوك غير المتزامن مع وظيفة رد الاتصال

الكود الزائف لنظام وظيفة رد الاتصال غير المتزامن الأساسي هو:

اكتب الإخراج؛

اكتب cb(اكتب الإخراج)

{

//صياغات

}


اكتب mainFn(اكتب الإدخال ، اكتب cb(اكتب الإخراج))

{

//صياغات

}

لاحظ مواضع بيانات الإدخال والإخراج في أماكن مختلفة من الكود الزائف. مدخلات وظيفة رد الاتصال هو ناتجها. معلمات الوظيفة الرئيسية هي معلمة الإدخال للكود العام ومعلمة وظيفة رد الاتصال. باستخدام هذا المخطط ، يمكن تنفيذ وظيفة ثالثة (تسمى) في الوظيفة الرئيسية () قبل قراءة إخراج وظيفة رد الاتصال (لا تزال في الوظيفة الرئيسية ()). يوضح الكود التالي هذا:

#يشمل

استخدام مساحة الاسمساعات؛

شار *انتاج؛


فارغcb(شارخارج[])

{

انتاج=خارج؛

}



فارغرئيسي(شارإدخال[]وفارغ (*ptr)(شار[خمسون]))

{

(*ptr)(إدخال)؛

كلفة<<'الوظيفة الرئيسية'<<'ن'؛

}


فارغالجبهة الوطنية()

{

كلفة<<'رأيت'<<'ن'؛

}


intالأساسية()

{

شارإدخال[] = 'وظيفة رد الاتصال'؛

فارغ (*ptr)(شار[]) = &cb؛

رئيسي(المدخلات ، cb)؛

الجبهة الوطنية()؛

كلفة<<انتاج<<'ن'؛



إرجاع 0؛

}

مخرجات البرنامج هي:

الوظيفة الرئيسية

رأيت

وظيفة رد الاتصال

في هذا الكود المعين ، يكون مرجع الإخراج والمدخل هو نفس المسند. تم عرض نتيجة استدعاء الوظيفة الثالث في الوظيفة main () قبل نتيجة وظيفة رد الاتصال. نفذت وظيفة رد الاتصال ، وانتهت ، وخصصت نتيجتها (القيمة) للمتغير ، الناتج ، مما يسمح للبرنامج بالاستمرار دون تدخله. في وظيفة main () ، تم استخدام إخراج وظيفة رد الاتصال (قراءة وعرض) عند الحاجة إليها ، مما أدى إلى سلوك غير متزامن للنظام بأكمله.

هذه هي الطريقة أحادية الترابط للحصول على سلوك غير متزامن لوظيفة رد الاتصال مع C ++ النقي.

الاستخدام الأساسي لمكتبة المستقبل

فكرة نظام وظيفة رد الاتصال غير المتزامن هي أن الوظيفة الأساسية تعود قبل أن تعود وظيفة رد الاتصال. تم ذلك بشكل غير مباشر وفعال في الكود أعلاه.

لاحظ من الكود أعلاه أن وظيفة رد الاتصال تتلقى الإدخال الرئيسي للكود وتنتج المخرجات الرئيسية للكود. مكتبة C ++ ، المستقبل ، لها وظيفة تسمى sync (). الوسيطة الأولى لهذه الوظيفة هي مرجع دالة رد الاتصال ؛ الوسيطة الثانية هي الإدخال إلى وظيفة رد الاتصال. ترجع وظيفة sync () دون انتظار اكتمال تنفيذ وظيفة رد الاتصال ولكنها تسمح لإكمال وظيفة رد الاتصال. يوفر هذا سلوكًا غير متزامن. بينما تستمر وظيفة رد الاتصال في التنفيذ ، نظرًا لأن وظيفة sync () قد عادت بالفعل ، فإن العبارات الموجودة أدناه تستمر في التنفيذ. هذا مثل السلوك المثالي غير المتزامن.

تمت إعادة كتابة البرنامج أعلاه أدناه ، مع الأخذ في الاعتبار مكتبة المستقبل ووظيفة المزامنة ():

#يشمل

#يشمل

#يشمل

استخدام مساحة الاسمساعات؛

مستقبل<سلسلة>انتاج؛

سلسلة cb(ستريب سلسلة)

{

إرجاعستريب؛

}



فارغرئيسي(إدخال سلسلة)

{

انتاج=غير متزامن(cb ، المدخلات)؛

كلفة<<'الوظيفة الرئيسية'<<'ن'؛

}


فارغالجبهة الوطنية()

{

كلفة<<'رأيت'<<'ن'؛

}


intالأساسية()

{

إدخال سلسلة=سلسلة('وظيفة رد الاتصال')؛

رئيسي(إدخال)؛

الجبهة الوطنية()؛

سلسلة ret=انتاج.احصل على()؛ // ينتظر رد الاتصال للعودة إذا لزم الأمر

كلفة<<حق<<'ن'؛



إرجاع 0؛

}

تقوم وظيفة sync () أخيرًا بتخزين ناتج وظيفة رد الاتصال في الكائن المستقبلي. يمكن الحصول على المخرجات المتوقعة في الدالة main () ، باستخدام دالة العضو get () للكائن المستقبلي.

استنتاج

وظيفة رد الاتصال هي دالة ، وهي وسيطة ، وليست معلمة ، في دالة أخرى. يحتاج نظام وظيفة رد الاتصال إلى وظيفة أساسية ، ووظيفة رد الاتصال نفسها. إعلان وظيفة رد الاتصال هو جزء من قائمة معلمات الوظيفة الأساسية. يشار إلى تعريف وظيفة رد الاتصال في استدعاء الوظيفة للوظيفة الأساسية (في main ()). يتم استدعاء وظيفة رد الاتصال في الواقع ضمن تعريف الوظيفة الأساسية.

مخطط وظيفة رد الاتصال ليس بالضرورة غير متزامن. للتأكد من أن نظام وظيفة رد الاتصال غير متزامن ، أدخل الإدخال الرئيسي للكود ، والمدخل إلى وظيفة رد الاتصال ؛ جعل الإخراج الرئيسي للكود ، إخراج وظيفة رد الاتصال ؛ تخزين ناتج وظيفة رد الاتصال في متغير أو بنية بيانات. في الدالة main () ، بعد استدعاء الوظيفة الرئيسية ، قم بتنفيذ عبارات التطبيق الأخرى. عندما تكون هناك حاجة إلى إخراج وظيفة رد الاتصال ، في الوظيفة الرئيسية () ، استخدم (قراءة وعرض) هناك ثم.