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

< C++
תוכן שנמחק תוכן שנוסף
Ybungalobill (שיחה | תרומות)
דף חדש: {{C++‎}} מחלקה היא טיפוס המוגדר על ידי המתכנת. מלבד ההגדרה הטכנית הזו: מחלקה היא מבנה אבסטרקטי בעל תכונות...
(אין הבדלים)

גרסה מ־17:49, 18 במאי 2007

מחלקה היא טיפוס המוגדר על ידי המתכנת. מלבד ההגדרה הטכנית הזו: מחלקה היא מבנה אבסטרקטי בעל תכונות מסוימות ופעולות שניתן לבצע עליו. בפרק זה נסביר כיצד להגדיר ולהשתמש במחלקות. לצורך זה נתבונן בדוגמה הקלאסית של מחלקת התאריך.

הגדרת מחלקה

נגדיר את המחלקה בדומה למבנה. נרשום את המילה class ואחריה את שם המחלקה:

class Date
{
public:
    int d, m, y;
};

המילה public מצינת שחברי המחלקה המוגדרים בהמשך יהיו ציבוריים, כלומר מכל מקום בתוכנית נוכל להשתמש בהם כמו במבנה רגיל. בעצם הגדרת מחלקה זו שקולה להגדרת מבנה דומה (struct במקום class). שלושת משתני המחלקה (d, m, y) מיצגים את התאריך באמצעות יום, חודש ושנה. כיוון שנוכל לשנות אותם באופן ישיר על ידי השמה, עלולות להתעורר שגיאות נסתרות, למשל אם בטעות נכניס ל-m את הערך 13. גישה כזו נוגדת את עקרון תכנות מונחה העצמים.

עתה, כדי לעשות את התוכנית שלנו נוחה יותר, ברורה יותר ויציבה יותר, נחסום את הגישה למשתני המחלקה. לצורך זה נשנה את המילה public ל-private, מותר למחוק אותה כלל כיוון שחברי המחלקה הבאים ראשונים לאחר הסוגרים המסולסלים מוגדרים אוטומטית כפרטיים:

class Date
{
private: // שורה זו ניתן למחוק
    int d, m, y;
};

כעת לא נוכל לגשת למשתני המחלקה d, m ו y באופן ישיר, לכן נבנה ממשק נוח לטיפול במשתני מחלקה זו. ממשק זה יוגדר כציבורי והוא יבטיח שהערכים של משתני המחלקה תמיד יהיו תקינים (למשל m לא יהיה גדול מ-12). כמעט כל ממשק צריך לכלול פעולות על המחלקה ופונקציות לאיחזור נתונים. בדוגמה זו נגדיר תחילה רק את כותרות הפונקציות (אתחל, הוספת יום/חודש/שנה, אחזור יום/חודש/שנה):

class Date
{
    int d, m, y;

public:
    void init(int dd, int mm, int yy);
    void add_day(int n);
    void add_month(int n);
    void add_year(int n);

    int day() const;
    int month() const;
    int year() const;
};

הערה: המילה const אחרי כותרת הפונקציה מצינת שהפונקציה לא משנה את משתני המחלקה. אלה פונקציות ממשק המחזירות את הערכים של משתני המחלקה.

הגדרת גופי פונקציות המחלקה

עד כה הגדרנו את כותרות הפונקציות, את ממשק המחלקה. עלינו לישם אותו, להגדיר את גוף כל פונקציה. את פונקציות המחלקה מגדירים בדומה לפונקציות רגילות. ניתן להגדיר אותן בשני מקומות:

  • בתוך בלוק המחלקה. דרך זו מקובלת יותר לפונקציות inline. לדוגמה, נגדיר את הפונקציה ()year:
class Date
{
    int d, m, y;

public:
    // ...

    int year() const 
    {
        return y;
    }    
};
  • מחוץ לבלוק המחלקה. בדרך זו נגדיר את רוב הפונקציות. הסיבה לכך היא שנרצה להגדיר אותן בד"כ בקובץ cpp ואילו הגדרת המחלקה עצמה תמצא בקובץ h. כדי לציין שהפונקציה שאנו מגדירים שיכת למחלקה מסוימת, נוסיף את שם המחלקה וארבע נקודות (::) לפני שמה, בזהה למרחבי שם. כדוגמה נגדיר את הפעולה ()init:
class Date
{
    // ...
};

void Date::init(int dd, int mm, int yy)
{
    d = dd;
    m = mm;
    y = yy;
}

הערה: בין אם גוף פונקציה המחלקה מוגדר בתוך או מחוץ למחלקה יש לה גישה לכל משתני המחלקה, פונקציות המחלקה וטיפוסים המוגדרים בתוך המחלקה.

שימוש בטיפוס שהוגדר

לאחר שהגדרנו מחלקה וישמנו את כל הפונקציות שלה (לא נעשה את זה כאן), נוכל להשתמש בה בדומה לטיפוסים בסיסיים של C++. לצורך זה עלינו להצהיר על משתנה מטיפוס זה (מופע של מחלקה) ולגשת לפונקציות ומשתני המחלקה הציבורים בדומה למבנים:

Date dat;
dat.init(18, 6, 2007);

int n;
cin >> n;

dat.add_day(n);
cout << dat.day() << '.' << dat.month() << '.' << dat.year();

כיוון שחסמנו את הגישה למשתני המחלקה לא נוכל לגשת אליהם ישירות מתוך פונקציות שהן לא חברות המחלקה:

dat.d = 32; // שגיאה

הבדל בין מבנים למחלקות

ב++C אין הבדל משמעותי בין מבנים לבין מחלקות. כל מחלקה נוכל לשכתב בקלות למבנה וכל מבנה נוכל לשכתב בקלות למחלקה. ההבדל היחידי הוא שחברי המחלקה הם פרטיים כברירת מחדל ואילו חברי המבנה הם ציבוריים כברירת מחדל. שתי ההגדרות הבאות שקולות זו לזו:

class myType { // ...
struct myType { private: // ...

הבדל זה חל גם על כללי ההורשה (למדל בהמשך).

אז כיצד נחליט מתי להשתמש במבנה ומתי במחלקה? אין כללים ברורים, נוכל להשתמש במבנים כמו שהשתמשנו ב-C ולהוסיף אליהם פונקציות ציבוריות. כאשר נרצה ליצור טיפוס בו נפריד בין ישום לממשק ואולי נשתמש בהורשה, נבחר במחלקה.

   חלק זה של הספר הינו קצרמר. אתם מוזמנים לתרום לוויקיספר ולערוך אותו.