Menu
Coddy logo textTech

העמסת האופרטורים [] ו־()

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

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

הנה מעטפת פשוטה למערך עם אופרטור האינדקס:

class IntArray {
    int* data;
    size_t size;
    
public:
    IntArray(size_t s) : size(s), data(new int[s]()) {}
    ~IntArray() { delete[] data; }
    
    int& operator[](size_t index) {
        return data[index];
    }
    
    const int& operator[](size_t index) const {
        return data[index];
    }
};

שימו לב שאנחנו מספקים שתי גרסאות: אחת מחזירה הפניה שאינה const (ומאפשרת שינוי), והגרסה const פועלת עם אובייקטים מסוג const. כך אפשר לכתוב arr[0] = 5; לצורך קריאה וכתיבה.

אופרטור הקריאה לפונקציה יוצר אובייקטים שאפשר "לקרוא" להם כמו לפונקציות:

class Multiplier {
    int factor;
    
public:
    Multiplier(int f) : factor(f) {}
    
    int operator()(int value) const {
        return value * factor;
    }
};

Multiplier triple(3);
int result = triple(10);    // מחזיר 30

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

challenge icon

אתגר

קל

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

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

  • ScoreTracker.h: הגדר מחלקה ScoreTracker שמנהלת מערך של ציוני שחקנים ויכולה להחיל בונוסים. המחלקה שלך צריכה לכלול:
    • מערך int* שהוקצה באופן דינמי כדי לאחסן ציונים
    • איבר size_t למספר הציונים
    • איבר double למכפיל הבונוס
    • בנאי שמקבל את הגודל ואת מכפיל הבונוס, ומאתחל את כל הציונים ל-0
    • הורס שמנקה כראוי את הזיכרון הדינמי
    • את אופרטור האינדקס [] (גם גרסה const וגם גרסה שאינה const) כדי לגשת לציונים לפי אינדקס
    • את אופרטור הקריאה לפונקציה (), שמקבל ציון מסוג int ומחזיר את הציון כשהוא מוכפל במכפיל הבונוס (בתור int)
    • מתודה getSize() שמחזירה את מספר הציונים

    אופרטור האינדקס שאינו const מחזיר הפניה, כך שאפשר לכתוב tracker[0] = 100;. הגרסה const מאפשרת גישה לקריאה בלבד עבור אובייקטים מסוג const. יש לסמן את אופרטור הקריאה לפונקציה כ-const, מכיוון שהוא אינו משנה את מצב האובייקט.

  • main.cpp: קרא את הקלטים הבאים (כל אחד בשורה נפרדת):
    1. מספר השחקנים (גודל)
    2. מכפיל הבונוס (בתור double)
    3. הציונים של כל שחקן (אחד בכל שורה, כמספר השחקנים)
    4. ציון לבדיקה שעליו יש להחיל את הבונוס

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

    תבנית הפלט:

    Player 0: <score>
    Player 1: <score>
    ...
    Bonus applied to <test_score>: <result>

לדוגמה, עבור 3 שחקנים, מכפיל של 1.5, ציונים 100, 200, 150 וציון לבדיקה 80:

Player 0: 100
Player 1: 200
Player 2: 150
Bonus applied to 80: 120

השתמש ב-std::stoi() וב-std::stod() להמרת הקלט. אל תשכח להוסיף guards לכותרת בקובץ הכותרת שלך.

נסו בעצמכם

#include <iostream>
#include <string>
#include "ScoreTracker.h"

using namespace std;

// TODO: לממש את הבנאי של ScoreTracker
ScoreTracker::ScoreTracker(size_t size, double multiplier) {
    // TODO: לאתחל את המשתנים החברים ולהקצות מערך דינמי
    // לאתחל את כל הניקודים ל-0
}

// TODO: לממש את ההורס של ScoreTracker
ScoreTracker::~ScoreTracker() {
    // TODO: לשחרר את הזיכרון הדינמי
}

// TODO: לממש את אופרטור הגישה לפי אינדקס שאינו const

// TODO: לממש את אופרטור הגישה לפי אינדקס שהוא const

// TODO: לממש את אופרטור הקריאה לפונקציה

// TODO: לממש את המתודה getSize
size_t ScoreTracker::getSize() const {
    // TODO: להחזיר את מספר הניקודים
}

int main() {
    string line;
    
    // לקרוא את מספר השחקנים
    getline(cin, line);
    size_t numPlayers = stoi(line);
    
    // לקרוא את מכפיל הבונוס
    getline(cin, line);
    double multiplier = stod(line);
    
    // TODO: ליצור ScoreTracker עם numPlayers ו-multiplier
    
    // TODO: לקרוא את הניקוד של כל שחקן ולשמור אותו באמצעות אופרטור האינדקס
    
    // TODO: לקרוא את ניקוד הבדיקה
    
    // TODO: להציג את הניקוד של כל השחקנים בפורמט: "Player X: <score>"
    
    // TODO: להציג את התוצאה לאחר החלת הבונוס בפורמט: "Bonus applied to <test_score>: <result>"
    
    return 0;
}
quiz iconבחנו את עצמכם

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

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

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