ملخص
كان كل برنامج في الدورة حتى الآن كتلة واحدة، main، يُكتب فيها كل شيء حيث يُستعمل. يعلّم هذا الدرس كيف يُعطى جزء من البرنامج اسمًا وكيف يُستعمل دون النظر في داخله: إنها الدالة. ويُدرس التصريح، الذي يعلن للمترجم الاسم ونوع القيمة المُعادة والوسائط؛ والتعريف، الذي يضيف الجسم؛ والاستدعاء، الذي ينقل التحكم إلى ذلك الجسم ويتلقى القيمة المُعادة. ويُميَّز ما يتحقق منه المترجم عند الترجمة (أن يوافق كل استدعاء تصريحًا ما) مما يحدث عند التنفيذ (القفز إلى التعريف ثم الرجوع). ويُشرح لماذا يكون بلوغ نهاية دالة يجب أن تُعيد قيمة دون return سلوكًا غير معرَّف. ويُتتبَّع التنفيذ بمكدس الاستدعاءات، الذي يحفظ إطارًا لكل استدعاء جارٍ. وتُوصَف كل دالة بعقد، أي بشرطها المسبق وشرطها اللاحق، يقول ما تشترطه الدالة على من يستدعيها وما تضمنه له في المقابل.
أهداف التعلم
- التصريح بالدوال وتعريفها واستدعاؤها مع وسائط وقيمة مُعادة، وتعيين الجزء الذي هو التصريح والجزء الذي هو التعريف في برنامج ما.
- تتبّع تنفيذ برنامج فيه دوال يستدعي بعضها بعضًا برسم تخطيطي لمكدس الاستدعاءات.
- وصف دالة بشرطها المسبق وشرطها اللاحق، وكتابة استدعاء يخالف الشرط المسبق.
- شرح لماذا تكون الدالة التي لا تُعيد قيمة في مسار ما سلوكًا غير معرَّف، والتعرّف على تحذير المترجم المقابل لذلك.
لماذا الدوال
كانت برامج الوحدة الماضية تحل كل مسألة داخل main، وكفى ذلك ما دامت المسائل صغيرة. غير أن البرنامج ما إن يكبر حتى تظهر ثلاث صعوبات. الأولى هي التكرار: إذا احتيج إلى الحساب نفسه في ثلاثة مواضع كُتب ثلاث مرات، وصُحّح الخطأ فيه ثلاث مرات (أو نُسي تصحيحه في أحدها). والثانية هي القراءة: كتلة من خمسين سطرًا لا تقول ماذا تفعل، بل كيف تفعله، وعلى القارئ أن يعيد بناء القصد انطلاقًا من الآلية. والثالثة هي الاختبار: إذا اختلط كل شيء فلا سبيل إلى التحقق من جزء دون تنفيذ الباقي.
الدالة جزء من البرنامج له اسم، يتلقى معطيات تسمى الوسائط، ويسلّم نتيجة تسمى القيمة المُعادة. وتعرف الرياضيات هذه الفكرة منذ قرون: المسافة بين نقطتين من المستوى دالة في إحداثياتهما الأربعة، ، ومن يحسب محيط مثلث لا يكرر الصيغة ثلاث مرات، بل يسمّيها ويطبّقها ثلاث مرات. وفي C++ يُكتب الشيء نفسه.
يقرأ البرنامج إحداثيات رؤوس مثلث الثلاثة ويكتب محيطه، وهو مجموع أطوال أضلاعه الثلاثة.
#include <cmath>#include <iostream>#include <print>// المسافة بين النقطتين (x1, y1) و(x2, y2).double distance(double x1, double y1, double x2, double y2){ const double dx{x2 - x1}; const double dy{y2 - y1}; return std::sqrt(dx * dx + dy * dy);}int main(){ double ax{}; double ay{}; double bx{}; double by{}; double cx{}; double cy{}; std::cin >> ax >> ay >> bx >> by >> cx >> cy; const double perimeter{distance(ax, ay, bx, by) + distance(bx, by, cx, cy) + distance(cx, cy, ax, ay)}; std::println("المحيط: {}", perimeter);}0 0 3 0 0 4المحيط: 12أضلاع المثلث الذي رؤوسه و و أطوالها 3 و5 و4، ومجموعها 12.
تُكتب الدالة distance مرة واحدة وتُستعمل ثلاث مرات؛ وتُقرأ main كأنها تعريف المحيط، «مجموع ثلاث مسافات»؛ ويمكن اختبار distance وحدها، بزوج من النقاط معلومة المسافة بينهما. وهكذا تُكسب الأمور الثلاثة التي كانت تنقص. والعبرة العامة، التي تصحّ في أي لغة، أن الدالة تسمّي فكرة: من يستعملها يفكر في ماذا تفعل، لا في كيف تفعله. ويسمى هذا الفصل بين الاستعمال والتنفيذ الداخلي التجريد الإجرائي، وهو موضوع الوحدة كلها.
جارٍ تحميل المحتوى…