C++/פונקציות: הבדלים בין גרסאות בדף

תוכן שנמחק תוכן שנוסף
Ybungalobill (שיחה | תרומות)
Ybungalobill (שיחה | תרומות)
שורה 374:
== העמסת פונקציות ==
 
'''העמסת פונקציות''' (function overloading) היא יצירה של יותרמספר מפונקציהפונקציות אחת עםשלכולן אותו שם, כאשרהשם. הןהפונקציות נבדלות זו מזו על ידי רשימת הפרמטרים שלהן. ישבאמצעות צורךהעמסת באלמנטפונקציות זהנוכל בכדילכתוב ליצורעבור פונקציהטיפוסי אחתפרמטרים (בעצםשונים כמה,מספר בעלותמימושים שםשל זהה)אותה שהיאהפונקציה. רבלמשל שימושית,נוכל הוילהגדיר אומרפונקציה שלמשלשתדפיס פונקציהמספר שמחזירהשלם, אתפונקציה הגדולשתדפיס מביןמספר שניממשי מספריםופונקציה שמתקבליםשתדפיס כפרמטריםמחרוזת, תהיהכאשר מתאימהשלושתן למספרתקראנה טיפוסי נתוניםprint.<br />ההבדל למשל:בין היאשלושת תוכלפונקציות לחשבאלה אתיהיה התוצאהבטיפוסים גםשל אםהפרמטרים יתקבלושהן משתנים מטיפוס int וגם אם יתקבלו משתנים מטיפוס double, ואפשר כמובן שיהיה שוני בין שני החישובים.תקבלנה:
<source lang="cpp">
 
void print(int x)
===דוגמה להעמסה===
כעת, נדגים את הרעיון ע"י העמסה של פונקציה המחזירה את סכומם של שני מספרים שנשלחו אליה כפרמטרים:
<pre style="direction:ltr;">
#include<iostream.h>
 
int sum(int num1,int num2);
double sum(double num1,double num2);
 
int main()
{
// Print an integer number
cout << sum(5,6) << endl << sum(3.56,8.5);
return 0;
}
 
void print(float x)
int sum(int num1,int num2)
{
// Print a real number
return num1+num2;
}
 
void print(const char *str)
double sum(double num1,double num2)
{
// Print a string
return num1+num2;
}
</presource>
 
העמסת פונקציות עוזרת לנו להמנע מ-"סגנון C" בו הצטרכו המתכנתים להוסיף בסוף שם כל אחת מהפונקציות תוספת שתרמוז על הטיפוס של הפרמטרים: print_int, print_float, print_string וכד'... דוגמה נוספת מהחיים היא OpenGL. בספרייה זו רוב הפונקציות קיימות במספר גרסות עבור מספר טיפוסים של פרמטרים, למשל הפונקציה glColor קיימת ב-32 גרסות שונות כאשר לכל גרסה שם שונה. באמצעות העמסת פונקציות יכלו מפתחי הסיפרייה לקרוא לכולן באותו השם אך כיוון שהסיפרייה פותחה במקורה עבור שפת C, הדבר לא כך הוא.
 
מבחינת מימוש הפונקציות המועמסות לא חל שינוי. נתרכז כרגע באופן קריאתן. כיוון שיש מספר פונקציות עם אותו השם יש צורך לדעת איזו גרסה תקרא. המהדר יחליט לאיזו פונקציה לקרוא לפי בדיקת הטיפוסים של הפרמטרים המועברים במקום הקריאה והשוואתם לטיפוסים של הפרמטרים בפונקציות הקיימות באותו שם. הכללים הם הבאים:
# אם חלה התאמה מלאה של טיפוסי הפרמטרים ומספרם לאחת גרסות הפונקציה, זו הגרסה שתקרא.
# אחרת, המהדר יחפש גרסה שמתאימה לאחר ביצוע המרות מרחיבות של הפרמטרים.
# אחרת, המהדר יחפש גרסה שמתאימה לאחר ביצוע המרות מצרות של הפרמטרים.
# אחרת, המהדר יחפש גרסה שמתאימה לאחר ביצוע המרות המוגדרות על ידי המתכנת.
# אחרת, המהדר יחפש גרסה שמתאימה כי היא מקבלת פרמטרים שרירותיים.
# אחרת לא קיימת פונקציה מתאימה ותהיה שגיאת הידור.
 
אם יש מספר גרסות שמתאימות לכלל הראשון המתקיים מבין אלה, הקריאה אינה חד-משמעית וגם היא תגרום לשגיאת הידור. כמו כן, הטיפוס של הערך המוחזר לא משפיע על החלטתו של המהדר.
 
נציג כעת מספר דוגמות בעיתיות:
שימו לב ששני הפונקציות כאן הן בעלות שם זהה - sum. אם הפונקציה תקרא עם שני פרמטרים מסוג int, אזי הגרסא הראשונה תצא לפעולה, אם תקרא עם פרמטרים מסוג double, הגרסה השניה תצא לפעולה.
<source lang="cpp">
אפשר גם לשנות את אחת הפונקציות, למקרה שנרצה לעשות חישוב שונה לdouble ולint.
print(1.5); // Error
</source>
בהנתן ההגדרות שלמעלה, המהדר לא יודע לאיזו משתי הגרסות הראשונות לקרוא (הגרסה השלישית לא מתאימה בכל אופן). כיוון שטיפוס המספר 1.5 הוא double, גם המרה ל-int בגרסה הראשונה וגם המרה ל-float בגרסה השנייה הן המרות מצרות, לכן הכלל הראשון שמתאים (מס. 3) הוא דו-משמעי.
 
{{להשלים}}
===המרה ובעיות אפשריות===
אם למשל נקרא לפונקציה sum()‎ שיצרנו קודם עם שני פרמטרים מסוג שונה מהמוזכרים בקוד, יתרחש מיד ניסיון המרה של המהדר. במקרה שלנו, אם נקרא לפונקציה עם פרמטרים מסוג float, המהדר ימיר אותם לdouble ותקרא הגירסא השניה של sum()‎.
כמובן שכזאת המרה עלולה שלא להצליח, אם למשל מדובר במצביע שנשלח לפונקציה sum()‎, אז המהדר יתן הודעת שגיאה.
עניין חשוב יותר הוא המצב הבא:<br />
אם לפונקציה שלנו למשל, נשלחים שני פרמטרים שונים, אחד double והשני int, איזו גירסה תיקרא?<br />
התשובה החד משמעית לכך היא שאף אחת מהן, העניין יצור בלבול אצל המהדר באשר לפרמטרים.<br />
double יכול ליהיות מומר לint ואז תיקרא הגירסה הראשונה, וint יכול ליהיות מומר לdouble, במקרה כזה תיקרא הגירסה השניה. מצב כזה יכול לקרות לעתים קרובות, לכן כדאי לשים לב לכך.
 
{{C++|מוגבל=כן}}