חברי מופע לעומת חברים סטטיים
חלק מהיחידה תכנות מונחה עצמים במסלול ה-C++ של Coddy. שיעור 27 מתוך 104.
עד כה, כל משתנה חבר שיצרת שייך לאובייקט מסוים. כשאתה יוצר שני אובייקטים מסוג Player, לכל אחד מהם יש name ו-health משלו. אלה נקראים חברי מופע — הם קיימים בנפרד עבור כל מופע של המחלקה.
אבל מה אם צריך נתונים שמשותפים לכל האובייקטים? למשל, מעקב אחר מספר השחקנים הכולל.
כאן נכנסים לתמונה חברים סטטיים. חבר סטטי שייך למחלקה עצמה, ולא לאובייקט מסוים כלשהו.
class Player {
std::string name; // שדה של מופע - לכל שחקן יש שדה משלו
int health; // שדה של מופע
static int playerCount; // שדה סטטי - משותף לכל השחקנים
public:
Player(std::string n) : name(n), health(100) {
playerCount++; // יש להגדיל את הערך כשנוצר שחקן כלשהו
}
~Player() {
playerCount--; // יש להקטין את הערך כששחקן כלשהו נהרס
}
};ההבדל המרכזי: ניגשים לחברי מופע דרך אובייקט, ואילו לחברים סטטיים אפשר לגשת דרך שם המחלקה עצמו. חשבו על חברי מופע כעל "אחד לכל אובייקט" ועל חברים סטטיים כעל "אחד לכל מחלקה".
| חברי מופע | חברים סטטיים |
|---|---|
| ייחודיים לכל אובייקט | משותפים לכל האובייקטים |
| נוצרים בעת יצירת האובייקט | קיימים לפני יצירת אובייקט כלשהו |
ניגשים אליהם דרך אובייקט: player.health | ניגשים אליהם דרך מחלקה: Player::playerCount |
אתגר
קלבואו נבנה מערכת מלאי של מוצרים שעוקבת גם אחר פרטים של כל מוצר בנפרד וגם אחר נתונים סטטיסטיים כלליים של המלאי, באמצעות איברי מופע ואיברים סטטיים.
תיצרו שני קבצים כדי לארגן את הקוד:
Product.h: הגדירו מחלקתProductשמנהלת מוצרים בודדים ובמקביל עוקבת אחר נתונים של כלל המלאי. המחלקה צריכה לכלול:- איברי מופע:
name(מחרוזת) ו-price(double): ייחודיים לכל מוצר - איבר סטטי
totalProductsשסופר כמה מוצרים קיימים כרגע - איבר סטטי
totalValueשעוקב אחר המחיר הכולל של כל המוצרים - בנאי שמקבל שם ומחיר, מאתחל את איברי המופע ומעדכן את שני המונים הסטטיים (מגדיל את המונה ומוסיף את המחיר לערך הכולל)
- הורס שמעדכן את המונים הסטטיים כאשר מוצר מוסר (מקטין את המונה ומחסיר את מחיר המוצר מהערך הכולל)
- מתודה
getInfo()שמחזירה מחרוזת בפורמט:"<name>: $<price>" - מתודה סטטית
getInventoryStats()שמחזירה מחרוזת:"Products: <count>, Total Value: $<value>"
- איברי מופע:
main.cpp: הדגימו כיצד איברים סטטיים משותפים לכל האובייקטים, בעוד שאיברי מופע נשארים ייחודיים. קראו שני שמות של מוצרים ואת מחיריהם מהקלט (name1, price1, name2, price2: כל אחד בשורה נפרדת), ואז:- הדפיסו את נתוני המלאי ההתחלתיים באמצעות שם המחלקה:
Product::getInventoryStats() - צרו בלוק תחום באמצעות סוגריים מסולסלים ובתוכו צרו
Productעם השם והמחיר הראשונים. הדפיסו את הפרטים שלו ואת נתוני המלאי הנוכחיים. - לאחר סיום הבלוק (המוצר הראשון הושמד), הדפיסו
"After first scope:"ולאחר מכן את נתוני המלאי - צרו
Productנוסף עם השם והמחיר השניים. הדפיסו את הפרטים שלו ואת נתוני המלאי. - צרו
Productשלישי עם השם"Bonus"והמחיר5.00. הדפיסו את נתוני המלאי הסופיים.
- הדפיסו את נתוני המלאי ההתחלתיים באמצעות שם המחלקה:
זכרו להגדיר את האיברים הסטטיים מחוץ למחלקה בקובץ הכותרת (לאחר הגדרת המחלקה). עצבו את המחירים עם שתי ספרות אחרי הנקודה העשרונית באמצעות std::fixed ו-std::setprecision(2) מתוך <iomanip>.
כללו את קובץ הכותרת ב-main.cpp באמצעות #include "Product.h".
נסו בעצמכם
#include <iostream>
#include <string>
#include "Product.h"
using namespace std;
int main() {
// קרא את הקלט
string name1;
double price1;
string name2;
double price2;
getline(cin, name1);
cin >> price1;
cin.ignore();
getline(cin, name2);
cin >> price2;
// TODO: הדפס את נתוני המלאי ההתחלתיים באמצעות Product::getInventoryStats()
// TODO: צור בלוק תחום באמצעות סוגריים מסולסלים
// בתוך הבלוק:
// - צור אובייקט Product עם name1 ו-price1
// - הדפס את המידע שלו באמצעות getInfo()
// - הדפס את נתוני המלאי הנוכחיים
// TODO: לאחר סיום הבלוק, הדפס "After first scope:"
// לאחר מכן הדפס את נתוני המלאי
// TODO: צור אובייקט Product נוסף עם name2 ו-price2
// הדפס את המידע שלו ואת נתוני המלאי
// TODO: צור אובייקט Product שלישי עם השם "Bonus" והמחיר 5.00
// הדפס את נתוני המלאי הסופיים
return 0;
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות OOP
קבצים חיצונייםבנייה וקומפילציה של C++קובצי Header וקובצי מקורמרחבי שמות והיקףמבוא ל-OOP ב-C++מחלקות לעומת אובייקטיםמצביע thisמתודות (פונקציות איבר)תכונות (חברי נתונים)יסודות הבנאים וההורסיםסיכום – מחשבון פשוט4מאפייני מחלקה
חברי מופע לעומת חברים סטטייםגטרים וסטריםפונקציות איבר קבועותמילת המפתח mutableמתודות ומשתנים סטטייםפונקציות ומחלקות ידידותסיכום – מנהל חשבונות בנק7ירושה
ירושה בסיסיתרמות גישה בירושהסדר הקריאות לבנאי ולמפרקדריסת מתודותפונקציות וירטואליות ו־VTableירושה מרובהירושה וירטואליתסיכום – היררכיית עובדים2ניהול זיכרון
זיכרון Stack לעומת Heapמצביעים והפניותזיכרון דינמי (new/delete)מצביעים חכמים ב-C++RAII ב-C++סיכום – מנהל מערכים דינמיים5כימוס
מצייני גישה ב-C++מצייני גישה לעומקהסתרת מידעמבנה לעומת מחלקהמחלקות מקוננות ופנימיותסיכום – מערכת רשומות תלמידים8רב־צורתיות
רב־צורתיות בזמן קומפילציה לעומת בזמן ריצההעמסת פונקציותפונקציות וירטואליות — מבט נוסףפונקציות וירטואליות טהורותמחלקות מופשטותתכנון ממשקים ב־C++המרה דינמית ו־RTTIסיכום — מחשבון צורות3בנאים והורסים
בנאי ברירת מחדלבנאי עם פרמטריםבנאי העתקהבנאי העברהרשימות אתחול בבנאיםבנאים מאציליםמעמיקים בנושא הורסיםכלל השלושה / החמישה / האפססיכום – מחלקת String6העמסת אופרטורים
מבוא להעמסת אופרטוריםהעמסת אופרטורים אריתמטייםהעמסת אופרטורי השוואהאופרטורי זרםהעמסת אופרטור השמההעמסת האופרטורים [] ו־()אופרטורים להמרת טיפוסיםסיכום – מחלקת Matrix9תבניות
תבניות פונקציהתבניות מחלקההתמחות תבניותתבניות ארגומנטים משתנותיסודות SFINAE ותכונות טיפוסיםסיכום – מכל גנריתרגלו בעצמכם: קומפיילר C++ אונליין