C++/פונקציות: הבדלים בין גרסאות בדף
תוכן שנמחק תוכן שנוסף
פונקציות |
Ybungalobill (שיחה | תרומות) VOID++ |
||
שורה 2:
{{בעבודה}}
'''פונקציות''' הן אבני הבניין של [[w:תכנות פרוצדורלי|תכנות פרוצדורלי]]. כל [[w:פונקציה (תכנות)|פונקציה]] היא חלק מהתוכנה שיכול '''לקבל פרמטרים''' ויכול '''להחזיר ערך'''. לכל פונקציה כזאת נוכל לקרוא בכל מיני מקומות שונים בתוכנית.
לפי פרדיגמת התכנות הפרוצדורלי יש לפרק את התוכנית לכמה שיותר פונקציות קטנות שכל אחת מהן תבצע מינימום פעולות פשוטות. פונקציות נקראות גם כן '''תת-תוכניות''', שם זה מרמז על כך שהן חלקים מהתוכנית הגדולה כאשר כל פונקציה מתפקדת כתוכנית קטנה בפני עצמה.
עד כה כבר
== קריאה לפונקציות ==
שורה 13:
<source lang="cpp">
double alpha = atan2(y, x);
</source>{{הארה|1=
}} בדוגמה זו קראנו לפונקציה בשם atan2. שני הפרמטרים שנתנו לפונקציה הם y ו-x. כיוון שהפונקציה מחזירה ערך, אנחנו שמרנו אותו במשתנה alpha. כמו כן לאו דווקא יש לשמור את הערך שמחזירה פונקציה. קיימות פונקציות רבות שהערך המוחזר הוא לא המטרה שעבורה
קריאה לפונקציה היא מעבר ביצוע התוכנית ממקום אחד בקוד למקום שני. בניגוד ללולאות או תנאים, התוכנית תחזור למקום ממנו נקראה הפונקציה כאשר הפונקציה תסתיים. ברגע הקריאה לפונקציה התוכנית דוחפת את הפרמטרים של הפונקציה אל [[w:מחסנית (מבנה נתונים)|המחסנית]] (אזור מיוחד בזיכרון), שומרת את כתובת החזרה ורק אז מבצעת קפיצה אל קוד הפונקציה עצמה. כאשר התוכנית מסיימת לבצע את קוד הפונקציה היא שולפת מהמחסנית את כתובת החזרה ומבצעת קפיצה על פיה. שיטה זו מאפשרת גם לקרוא לכל פונקציה שהיא מכל מקום בתוכנית וגם לאפשר קריאות רקורסיביות, קריאות לפונציה אחת מתוך פונקציה אחרת.
חשוב להבין שלעומת שפות אחרות, כמו Pascal למשל, הקריאה לפונקציה '''לא''' נעשת כאשר אנו כותבים את שמה. הפונקציה נקראת על ידי אופרטור קריאה לפונקציה: () (סוגריים). אופרטור זה מיוחד בכך שיכול לקבל מספר שרירותי של אופרנדים. האופרנד הראשון הוא שם הפונקציה שאותה אנו רוצים לקרוא לה, במקום שם הפונקציה ניתן לתת גם מצביע לפונקציה (למד בהמשך על [[C++/מצביעים והמשתנה המיוחס|מצביעים]]). שאר האופרנדים הם הפרמטרים שיש להעביר אל הפונקציה. הטיפוסים של הפרמטרים המועברים לפונקציה צריכים להתאים לטיפוסים של הפרמטרים בהכרזה על הפונקציה או ניתנים להמרת implicit אליהם (ראה למטה).
נכתוב בפרק זה פונקציה שמטרתה תהיה לעגל מספר שיבוא בפרמטר הראשון אל הכפולה הקרובה ביותר של חזקה של 10. החזקה של 10 אליה יש לעגל תבוא בפרמטר השני. הפונקציה תחזיר את התוצאה לאחר העיגול. נקרא לפונקציה זו בשם roundTo. לדוגמה נביא מספר קריאות לפונקציה זו:
שורה 34 ⟵ 37:
== הגדרת פונקציות ==
{{הערה|הכרזה או הגדרה של הפונקציה תעשה לפני השימוש הראשון בה. '''טרם למדנו על הכרזות, יש לכתוב את הגדרת
=== כותרת הפונקציה ===
כל הגדרה של פונקציה תתחיל מכותרתה. כותרת הפונקציה מגדירה בסדר הבא את:
* '''הטיפוס של הערך המוחזר מהפונקציה''' – זהו טיפוס כלשהו, מובנה או מוגדר על ידי המתכנת. ניתן במקום זאת לרשום את המילה השמורה void שפירושה שהפונקציה '''לא''' מחזירה ערך (ראה בהמשך).
* '''שם הפונקציה''' – הכללים לבחירת שם הפונקציה זהים לכללים לבחירת כל שם אחר ב-C++‎. נשתמש בשם זה על מנת לקרוא לפונקציה משאר התוכנית.
* '''טיפוסים ושמות הפרמטרים''' – רשימה זו תבוא בסוגריים אחרי שם הפונקציה. כל פרמטר יהיה מופרד בפסיקים משאר הרשימה. הגדרת פרמטרים אלה דומה להגדרה של משתנים מקומיים, הם אף מתפקדים וממומשים כמשתנים מקומיים לכל דבר. ההבדל היחידי הוא בהגדרה: נצטרך לרשום טיפוס לכל פרמטר בנפרד, גם אם כולם מאותו הטיפוס. שם הפרמטר ישמש אותנו אך ורק בגוף הפונקציה בפניות אליו, לכן אם מסיבות כלשהן הפרמטר לא נמצא בשימוש, ניתן לא לתת לו שם.
שורה 52 ⟵ 55:
=== גוף הפונקציה ===
'''הגדרה''' של פונקציה מכילה את קוד הפונקציה, כלומר היא מגדירה בפירוש מה הפונקציה עושה. כאשר אנו מגדירים פונקציה אנו נכתוב אחרי הכותרת את גופה בתוך בלוק התחום בסוגריים מסולסלים. בלוק זה יכיל הוראות הניתנות לביצוע, בין השאר, כמו בכל בלוק אחר, גם בבלוק הפונקציה נוכל להגדיר משתנים מקומיים (לוקאליים). משתנים אלה יושמדו בעת יציאה מהפונקציה. בתוך גוף הפונקציה נוכל להשתמש בפרמטרים שהפונקציה מקבלת. פרמטרים אלה גם הם מתפקדים כמשתנים מקומיים. נכתוב את גוף הפונקציה roundTo:
<source lang="cpp">
int roundTo(int number, int exponent)
שורה 66 ⟵ 69:
בפונקציה זו הגדרנו משתנה לוקאלי powerOfTen ושמרנו לתוכו את החזקה של 10 שאליה ברצוננו לעגל את המספר. בשורה לפני האחרונה של גוף הפונקציה אנו מעגלים את המספר ושומרים את התוצאה במשתנה עזר result. לאחר מכן בשורה האחרונה אנו מחזירים (return) את הערך שנמצא במשתנה result.
המשתנים הלוקאליים (מקומיים) נקראים גם משתנים אוטומטיים (auto). הקצאת זיכרון עבור משתנים אלה מתבצעת באופן אוטומטי כמו גם שיחרורו. זיכרון זה הוא זיכרון המחסנית. כיוון שבעת יציאה מהפונקציה המחסנית מוחזרת למצבה כפי שהוא היה לפני קריאתה, כל המשתנים הלוקאליים נשלפים ממנה.
=== הוראת return ===
שורה 105 ⟵ 110:
=== טיפוס void ===
בשפות אחרות מפרידים את המושג "פונקצייה" מ-"פרוצדורה" (למשל ב-Pascal יש מילה שמורה function ומילה procedure, ב-Visual Basic יש Function ויש Sub). '''פרוצדורה''' היא פונקציה שלא מחזירה ערך. כדי להגדיר פונקציה שלא תחזיר ערך יש לכתוב את הטיפוס void (ריק) בטיפוס המוחזר שלה. טיפוס זה מיוחד בכך שלא ניתן ליצור משתנה מטיפוס זה. טיפוס זה משמש ליצירת טיפוסים מורכבים.
כאשר הפונקציה לא מחזירה ערך (פונקציית void), לא הכרחי להשתמש בהוראה return. אם בכל זאת נרצה לצאת מגוף הפונקציה נוכל לרשום return ללא ביטוי אחריו:
<source lang="cpp">
void g()
{
int n;
cin >> n;
if(n < 0)
return;
cout << "I'm a void function!\n";
}
</source>
פונקציה זו תקינה. כמו כן, אם נכתוב אחרי ה-return ביטוי שהטיפוס שלו הוא לא void, המהדר יתן שגיאה. אחרי ה-return ניתן לכתוב ביטויים שהטיפוס שלהם הוא void, לדוגמה ניתן להחזיר את ערך ה-void המוחזר מפונקציית void אחרת, או ליצור ערך "void" זמני (כמובן פעולות אלה הן אך ורק דרכי כתיבה שונות, הרי לא קיימים ערכי void). אפשרות זו נוספה ל-C++‎ כדי להקל על יצירת [[C++/תבניות|תבניות]] עם פרמטרי void.
<source lang="cpp">
return void();
return f();
</source>
בהנחה ש-f היא פונקציית void, שתי הוראות אלו תהינה נכונות כאשר נכתובן בפונקציה g.
=== פונקציית main ===
שורה 126 ⟵ 153:
== רקורסיה ==
== פרמטרים שרירותיים ==
== ערכי ברירת מחדל ==
== העמסת פונקציות ==
העמסת פונקציות (
===דוגמה להעמסה===
|