C++/מחלקות: הבדלים בין גרסאות בדף

תוכן שנמחק תוכן שנוסף
Ybungalobill (שיחה | תרומות)
דף חדש: {{C++‎}} מחלקה היא טיפוס המוגדר על ידי המתכנת. מלבד ההגדרה הטכנית הזו: מחלקה היא מבנה אבסטרקטי בעל תכונות...
 
Ybungalobill (שיחה | תרומות)
אין תקציר עריכה
שורה 23:
};
</source></div>
כעת לא נוכל לגשת למשתני המחלקה d, m ו y באופן ישיר, לכן נבנה ממשק נוח לטיפול במשתני מחלקה זו. ממשק זה יוגדר כציבורי והוא יבטיח שהערכים של משתני המחלקה תמיד יהיו תקינים (למשל m לא יהיה גדול מ-12). כמעט כל ממשק צריך לכלול פעולות עלהמשנות את המחלקה ופונקציות לאיחזור נתונים. בדוגמה זו נגדיר תחילה רק את כותרות הפונקציות (אתחל, הוספת יום/חודש/שנה, אחזור יום/חודש/שנה):
<div style="direction: ltr;"><source lang="cpp">
class Date
שורה 40:
};
</source></div>
''הערה:'' המילה const אחרי כותרת הפונקציה מצינת שהפונקציה לא משנה את משתני המחלקה. אלה פונקציות ממשק המחזירות את הערכים של משתנימשתנים המחלקהאלה.
 
== הגדרת גופי פונקציות המחלקה ==
עד כה הגדרנוהצהרנו את כותרות הפונקציות, את ממשק המחלקה. עלינו לישםלממש אותו, להגדיר את גוף כל פונקציה. את פונקציות המחלקה מגדירים בדומה לפונקציות רגילות. ניתן להגדיר אותן בשני מקומות:
 
* '''בתוך בלוק המחלקה.''' דרך זו מקובלת יותר לפונקציות inline. לדוגמה, נגדיר את הפונקציה ()year:
שורה 80:
== שימוש בטיפוס שהוגדר ==
 
לאחר שהגדרנו מחלקה וישמנוומימשנו את כל הפונקציות שלה (לא נעשה את זה כאן), נוכל להשתמש בה בדומה לטיפוסים בסיסיים של C++. לצורך זה עלינו להצהיר על משתנה מטיפוס זה (מופע של מחלקה) ולגשת לפונקציות ומשתני המחלקה הציבורים בדומה למבנים:
<div style="direction: ltr;"><source lang="cpp">
Date dat;
שורה 99:
== הבדל בין מבנים למחלקות ==
 
ב++C אין הבדל משמעותי בין מבנים לבין מחלקות. כל מחלקה נוכל לשכתב בקלות למבנה וכל מבנה נוכל לשכתב בקלות למחלקה. ההבדל היחידי הוא שחברי המחלקה הם פרטיים כברירת מחדל ואילו חברי המבנה הם ציבוריים כברירת מחדל. משמעות הדבר שנוכל לגדיר גם משתני המבנה כפרטיים ולהוסיף פונקציות לטיפול בהם. שתי ההגדרות הבאות שקולות זו לזו:
<div style="direction: ltr;"><source lang="cpp">
class myType { // ...
struct myType { private: // ...
</source></div>
הבדל זה חל גם על כללי ההורשה (למדללמד בהמשך).
 
אז כיצד נחליט מתי להשתמש במבנה ומתי במחלקה? אין כללים ברורים, נוכל להשתמש במבנים כמו שהשתמשנו ב-C ולהוסיף אליהם פונקציות ציבוריות. כאשר נרצה ליצור טיפוס בו נפריד בין ישוםמימוש לממשק ואולי נשתמש בהורשה, נבחר במחלקה.
 
== בנאים ==
 
בנאי הוא פונקציה שאנו מגדירים עבור המחלקה, הוא יופעל בעת הגדרת מופע חדש של מחלקה. תפקיד פונקציה זו הוא לבנות את המחלקה, כלומר לאתחל את משתני המחלקה.
 
במחלקה אנו כתבנו בפרק עלינו לקרוא ל-init בכל פעם שנרצה לאתחל את המופע. דבר זה גורר שגיאות, למשל אם נשכח לקרוא לפונקציה זו לפני השימוש הראשון במשתנה Date. בדומה לאי-איתחול של כל משתנה אחר, גם במשתני המחלקה יהיו ערכים לא מוגדרים - 'זבל'. הבנאים יאפשרו לנו לכתוב פונקציה שתאתחל את המופע של המחלקה באופן אוטומטי באמצעות ערך חוקי כלשהו. הנה בנאי המאתחל את כל התאריכים ל-01/01/1970 (תוכלו לשנות בנאי זה שיאתחל את התאריך באמצעות התאריך של היום, ע"י שימוש בפונקציות מתאימות מהסיפריה ctime):
<div style="direction: ltr;"><source lang="cpp">
class Date
{
int d, m, y;
 
public:
Date()
{
d = 1, m = 1, y = 1970;
}
// ...
};
</source></div>
הבנאים של כל מחלקה יקראו על שם המחלקה, במקרה שלנו Date, אך הם אף פעם לא יחזירו ערך ולכן גם לא נכתוב את טיפוס הערך המוחזר, גם לא void. דבר זה מובן מאילו כאשר נתבונן בדרך בה אנו נפעילים את הבנאי, הרי זו הצהרה רגילה על משתנה past (הבנאי מופעל אוטומטית):
<div style="direction: ltr;"><source lang="cpp">
Date past; // כאן מופעל הבנאי
cout << past.day() << '.' << past.month() << '.' << past.year();
</source></div>
בדוגמה זו יופיע תמיד בפלט 1.1.1970.
 
''הערה:'' לא נוכל לקרוא לבנאי באופן ישיר {{קוד בשורה|past.Date()}} דבר זה נחשב לשגיאה, כי כל אובייקט מאותחל רק פעם אחת.
 
נוכל להוסיף פרמטרים לבנאים שאנו כותבים, נזכור שהעמסת בנאים מותרת כמו העמסת שאר הפונקציות. לכן נוכל להגדיר בנאי המאתחל את האוביקט באמצעות הערכים הנמסרים לו כפרמטרים, הוא יחליף לנו את הפונקציה init. בדוגמה הבאה יש להוסיף את בדיקת תקינות הפרמטרים ולהחליט על דרך פעולה כלשהי כאשר הפרמטרים לא תקינים (למשל לזרוק חריגה):
<div style="direction: ltr;"><source lang="cpp">
class Date
{
int d, m, y;
 
public:
Date(int dd, int mm, int yy)
{
d = dd, m = mm, y = yy;
}
// ...
};
</source></div>
כאן העמסנו בנאי נוסף לבנאי הקודם. כדי למסור פרמטרים לבנאי כלשהו בעת אתחול המשתנה, נרשום אותם בסוגרים עגולים לאחר שם המשתנה (''הערה:'' אם אין פרמטרים אז אין לרשום סוגרים כלל):
<div style="direction: ltr;"><source lang="cpp">
Date future(1,1,2970); // בנאי עם פרמטרים
Date past; // בנאי ללא פרמטרים
</source></div>
 
== מפרקים ==
 
== העתקת אוביקטים ==
 
{{קצרמר}}