העמסת פונקציות
חלק מהיחידה תכנות מונחה עצמים במסלול ה-C++ של Coddy. שיעור 57 מתוך 104.
העמסת פונקציות מאפשרת לך להגדיר כמה פונקציות בעלות אותו שם אך עם רשימות פרמטרים שונות. המהדר בוחר את הגרסה המתאימה על סמך הארגומנטים שמעבירים לה. זוהי צורה מרכזית של פולימורפיזם בזמן הידור.
כדי שהעמסת יתר תעבוד, החתימות של הפונקציות חייבות להיות שונות — במספר הפרמטרים, בסוגים שלהם או בשניהם:
class Calculator {
public:
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
};
Calculator calc;
calc.add(5, 3); // קורא ל-add(int, int)
calc.add(2.5, 3.7); // קורא ל-add(double, double)
calc.add(1, 2, 3); // קורא ל-add(int, int, int)המהדר בוחן כל קריאה ומתאים אותה לגרסת העמסת היתר המתאימה. הדבר מתרחש כולו בזמן הקומפילציה, ולכן אין תקורה בזמן ריצה.
חשוב: טיפוס ההחזרה לבדו אינו מבדיל בין פונקציות בעלות אותו שם. הדבר הבא יגרום לשגיאת קומפילציה:
int getValue();
double getValue(); // שגיאה: אי אפשר לבצע העמסה על סמך טיפוס ההחזרה בלבדהעמסת פונקציות הופכת את הקוד שלך לאינטואיטיבי יותר. במקום ליצור שמות נפרדים כמו addInts, addDoubles ו-addThreeInts, משתמשים בשם משמעותי אחד ונותנים למהדר לטפל בשאר.
אתגר
קלבואו נבנה מחלקה לעיצוב הודעות, שמדגימה את העוצמה של העמסת פונקציות. תיצרו מחלקה בשם Formatter עם כמה מתודות format() שמטפלות בסוגי קלט שונים, כך שהמהדר יבחר את הגרסה המתאימה לפי מה שתעבירו לה.
תארגנו את הקוד בשני קבצים:
Formatter.h: הגדירו מחלקה בשםFormatterעם מתודותformat()עמוסות, שמטפלות בתרחישים שונים:- מתודה שמקבלת
std::stringיחיד ומדפיסה:Message: <text> - מתודה שמקבלת
std::stringוערך עדיפות מסוגint, ומדפיסה:[Priority <priority>] <text> - מתודה שמקבלת
std::stringוחותמת זמן מסוגdouble, ומדפיסה:[<timestamp>s] <text> - מתודה שמקבלת שלושה פרמטרים מסוג
std::string(sender, receiver, message) ומדפיסה:From <sender> to <receiver>: <message>
format(): המהדר יבחר את המתודה המתאימה לפי הארגומנטים.- מתודה שמקבלת
main.cpp: קראו ארבעה קלטים (כל אחד בשורה נפרדת):- טקסט פשוט של הודעה
- רמת עדיפות (מספר שלם)
- חותמת זמן (מספר מסוג double)
- שם השולח
צרו אובייקט מסוג
Formatterוהדגימו את כל ארבע המתודות העמוסות:- קראו ל־
format()עם טקסט ההודעה בלבד - קראו ל־
format()עם טקסט ההודעה ורמת העדיפות - קראו ל־
format()עם טקסט ההודעה וחותמת הזמן - קראו ל־
format()עם השולח, כאשר "Admin" הוא הנמען, ועם טקסט ההודעה
לדוגמה, עם הקלטים System ready, 3, 12.5 ו־Server:
Message: System ready
[Priority 3] System ready
[12.5s] System ready
From Server to Admin: System readyשימו לב שאתם קוראים לאותה מתודה בשם format() ארבע פעמים, אבל כל קריאה מפעילה גרסה אחרת בהתאם לסוג ולמספר הארגומנטים. זוהי פולימורפיזם בזמן הידור בפעולה: המהדר קובע באיזו העמסת מתודה להשתמש עוד לפני שהתוכנית רצה.
נסו בעצמכם
#include <iostream>
#include <string>
#include "Formatter.h"
using namespace std;
int main() {
// קראו את הקלטים
string message;
getline(cin, message);
int priority;
cin >> priority;
double timestamp;
cin >> timestamp;
cin.ignore();
string sender;
getline(cin, sender);
// TODO: צרו אובייקט מסוג Formatter
// TODO: קראו ל־format() עם טקסט ההודעה בלבד
// TODO: קראו ל־format() עם טקסט ההודעה ועם priority
// TODO: קראו ל־format() עם טקסט ההודעה ועם timestamp
// TODO: קראו ל־format() עם sender, עם "Admin" כנמען ועם טקסט ההודעה
return 0;
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות OOP
קבצים חיצונייםבנייה וקומפילציה של C++קובצי Header וקובצי מקורמרחבי שמות והיקףמבוא ל-OOP ב-C++מחלקות לעומת אובייקטיםמצביע thisמתודות (פונקציות איבר)תכונות (חברי נתונים)יסודות הבנאים וההורסיםסיכום – מחשבון פשוט4מאפייני מחלקה
חברי מופע לעומת חברים סטטייםגטרים וסטריםפונקציות איבר קבועותמילת המפתח mutableמתודות ומשתנים סטטייםפונקציות ומחלקות ידידותסיכום – מנהל חשבונות בנק7ירושה
ירושה בסיסיתרמות גישה בירושהסדר הקריאות לבנאי ולמפרקדריסת מתודותפונקציות וירטואליות ו־VTableירושה מרובהירושה וירטואליתסיכום – היררכיית עובדים2ניהול זיכרון
זיכרון Stack לעומת Heapמצביעים והפניותזיכרון דינמי (new/delete)מצביעים חכמים ב-C++RAII ב-C++סיכום – מנהל מערכים דינמיים5כימוס
מצייני גישה ב-C++מצייני גישה לעומקהסתרת מידעמבנה לעומת מחלקהמחלקות מקוננות ופנימיותסיכום – מערכת רשומות תלמידים8רב־צורתיות
רב־צורתיות בזמן קומפילציה לעומת בזמן ריצההעמסת פונקציותפונקציות וירטואליות — מבט נוסףפונקציות וירטואליות טהורותמחלקות מופשטותתכנון ממשקים ב־C++המרה דינמית ו־RTTIסיכום — מחשבון צורות3בנאים והורסים
בנאי ברירת מחדלבנאי עם פרמטריםבנאי העתקהבנאי העברהרשימות אתחול בבנאיםבנאים מאציליםמעמיקים בנושא הורסיםכלל השלושה / החמישה / האפססיכום – מחלקת String6העמסת אופרטורים
מבוא להעמסת אופרטוריםהעמסת אופרטורים אריתמטייםהעמסת אופרטורי השוואהאופרטורי זרםהעמסת אופרטור השמההעמסת האופרטורים [] ו־()אופרטורים להמרת טיפוסיםסיכום – מחלקת Matrix9תבניות
תבניות פונקציהתבניות מחלקההתמחות תבניותתבניות ארגומנטים משתנותיסודות SFINAE ותכונות טיפוסיםסיכום – מכל גנריתרגלו בעצמכם: קומפיילר C++ אונליין