Menu
Coddy logo textTech

מצייני גישה לעומק

חלק מהיחידה תכנות מונחה עצמים במסלול ה-C++ של Coddy. שיעור 35 מתוך 104.

כעת, לאחר שהבנת את שלושת מצייני הגישה, נבדוק איך הם מתנהגים כשיש לך כמה אובייקטים מאותה מחלקה. תפיסה שגויה נפוצה היא ש־private פירושו "רק האובייקט הזה" — אבל למעשה פירושו "רק המחלקה הזאת".

אובייקטים מאותה מחלקה יכולים לגשת לאיברים הפרטיים זה של זה:

class Person {
    std::string secret;
    
public:
    Person(std::string s) : secret(s) {}
    
    void readSecret(const Person& other) {
        // גישה לשדה הפרטי של אובייקט אחר - מותרת!
        std::cout << other.secret;
    }
};

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

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

class Mixed {
public:
    void publicMethod1();
    
private:
    int privateData;
    
public:
    void publicMethod2();    // חזרה ל-public
    
private:
    void privateHelper();    // שוב private
};

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

challenge icon

אתגר

קל

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

תיצרו שני קבצים כדי לארגן את הקוד:

  • Wallet.h: הגדירו מחלקת Wallet ששומרת נתונים פיננסיים פרטיים, אך מאפשרת השוואות בין ארנקים. המחלקה שלכם צריכה לכלול:
    • חברים פרטיים: ownerName (מחרוזת) ו-balance (מספר ממשי)
    • בנאי שמקבל את שם הבעלים ואת היתרה ההתחלתית
    • פונקציית getter ציבורית getOwnerName() שמחזירה את שם הבעלים
    • מתודה hasMoreThan(const Wallet& other) שמשווה בין היתרה של הארנק הזה לבין היתרה הפרטית של ארנק אחר, ומחזירה true אם יש בארנק הזה יותר כסף
    • מתודה combinedBalance(const Wallet& other) שמחזירה את סכום היתרות הפרטיות של שני הארנקים
    • מתודה transferTo(Wallet& other, double amount) שמעבירה כסף מהארנק הזה לארנק אחר. עליה לשנות ישירות את היתרות הפרטיות של שני הארנקים (רק אם הסכום חיובי ואינו עולה על היתרה של הארנק הזה)
  • main.cpp: הדגימו גישה לחברים פרטיים של אובייקטים אחרים. קראו מהקלט שני שמות בעלים ושתי יתרות (ארבע שורות: name1, balance1, name2, balance2), ואז:
    • צרו שני אובייקטים מסוג Wallet עם ערכי הקלט
    • הדפיסו "Combined wealth: $<amount>" באמצעות combinedBalance()
    • השוו בין הארנקים והדפיסו "<name> has more money" עבור הבעלים שהיתרה שלו גבוהה יותר (השתמשו ב-hasMoreThan() כדי לקבוע זאת)
    • העבירו 100.0 מהארנק הראשון לשני באמצעות transferTo()
    • הדפיסו "After transfer:"
    • הדפיסו שוב "Combined wealth: $<amount>" (הסכום אמור להישאר ללא שינוי)
    • השוו שוב והדפיסו "<name> has more money" (ייתכן שהתוצאה השתנתה)

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

עצבו את כל הערכים הכספיים עם שתי ספרות אחרי הנקודה העשרונית באמצעות std::fixed ו-std::setprecision(2) מתוך <iomanip>. המירו את ערכי היתרה שהתקבלו בקלט באמצעות std::stod().

נסו בעצמכם

#include <iostream>
#include <string>
#include <iomanip>
#include "Wallet.h"

using namespace std;

int main() {
    // קרא את הקלט: name1, balance1, name2, balance2
    string name1, name2;
    string balanceStr1, balanceStr2;
    
    getline(cin, name1);
    getline(cin, balanceStr1);
    getline(cin, name2);
    getline(cin, balanceStr2);
    
    double balance1 = stod(balanceStr1);
    double balance2 = stod(balanceStr2);
    
    // הגדר את עיצוב הפלט לערכים כספיים
    cout << fixed << setprecision(2);
    
    // TODO: צור שני אובייקטים מסוג Wallet עם ערכי הקלט
    
    // TODO: הדפס את ההון המשולב באמצעות combinedBalance()
    // פורמט: "Combined wealth: $<amount>"
    
    // TODO: השווה בין הארנקים באמצעות hasMoreThan() והדפס למי יש יותר כסף
    // פורמט: "<name> has more money"
    
    // TODO: העבר 100.0 מהארנק הראשון לשני באמצעות transferTo()
    
    // TODO: הדפס "After transfer:"
    
    // TODO: הדפס שוב את ההון המשולב
    
    // TODO: השווה שוב והדפס למי יש יותר כסף
    
    return 0;
}
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר C++ אונליין