העמסת אופרטורים אריתמטיים
חלק מהיחידה תכנות מונחה עצמים במסלול ה-C++ של Coddy. שיעור 41 מתוך 104.
אופרטורים אריתמטיים כמו +, -, * ו-/ עוברים לעיתים קרובות העמסת יתר כדי לגרום למחלקות מותאמות אישית להתנהג כמו טיפוסים מספריים מובנים. אופרטורים אלה מחזירים בדרך כלל אובייקט חדש במקום לשנות את האופרנדים.
הנה מחלקת Fraction עם אופרטורים אריתמטיים:
class Fraction {
int numerator, denominator;
public:
Fraction(int n, int d) : numerator(n), denominator(d) {}
Fraction operator+(const Fraction& other) const {
return Fraction(
numerator * other.denominator + other.numerator * denominator,
denominator * other.denominator
);
}
Fraction operator*(const Fraction& other) const {
return Fraction(numerator * other.numerator,
denominator * other.denominator);
}
};שימו לב ששני האופרטורים מסומנים כ-const מכיוון שהם אינם משנים אף אחד מהאופרנדים. הם יוצרים ומחזירים Fraction חדש עם התוצאה.
עבור אופרטורי השמה מורכבים כמו +=, התבנית שונה. הם משנים את האופרנד השמאלי ומחזירים הפניה אליו:
Fraction& operator+=(const Fraction& other) {
numerator = numerator * other.denominator + other.numerator * denominator;
denominator = denominator * other.denominator;
return *this;
}נוהג נפוץ הוא לממש את האופרטור הבסיסי באמצעות השמה מורכבת, וכך לצמצם כפילות בקוד:
Fraction operator+(const Fraction& other) const {
Fraction result = *this; // העתק את האובייקט הזה
result += other; // השתמש באופרטור השמה משולב
return result;
}הגישה הזו מבטיחה ששני האופרטורים יישארו עקביים ומקלה על התחזוקה.
אתגר
קלבואו נבנה מחלקת Money שמטפלת בחישובי מטבע באמצעות העמסת אופרטורים אריתמטיים. תממשו כמה אופרטורים אריתמטיים שיאפשרו לכם לעבוד עם ערכי כסף באופן טבעי, ממש כמו עם מספרים רגילים.
תיצרו שני קבצים כדי לארגן את הקוד שלכם:
Money.h: הגדירו מחלקתMoneyששומרת סכום בסנטים (בתורint) כדי להימנע מבעיות דיוק של מספרים בנקודה צפה. המחלקה שלכם צריכה לתמוך ב:- בנאי שמקבל דולרים וסנטים כמספרים שלמים נפרדים
- פונקציית אחזור
getDollars()שמחזירה את חלק הדולרים - פונקציית אחזור
getCents()שמחזירה את חלק הסנטים (0-99) - האופרטורים
+ו--בהעמסת אופרטורים, שמחזירים אובייקטMoneyחדש - אופרטורי ההשמה המשולבים
+=ו--=בהעמסת אופרטורים, שמשנים את האובייקט הנוכחי ומחזירים הפניה אליו - מתודה
display()שמדפיסה את סכום הכסף בתבנית$X.YY(תמיד שתי ספרות עבור סנטים)
ממשו את האופרטורים הבסיסיים (
+ו--) באמצעות אופרטורי ההשמה המשולבים כדי לצמצם כפילות בקוד, כפי שמוצג בשיעור. יש לסמן את כל האופרטורים האריתמטיים ב-constבמקרים המתאימים.main.cpp: קראו ארבעה מספרים שלמים מהקלט, המייצגים שני סכומי כסף (dollars1, cents1, dollars2, cents2 בשורות נפרדות). צרו שני אובייקטים שלMoney, ואז הדגימו את כל האופרטורים:- הדפיסו
"Amount 1: "ואחריו הציגו את הסכום הראשון - הדפיסו
"Amount 2: "ואחריו הציגו את הסכום השני - חברו את שני הסכומים והדפיסו
"Sum: "ואחריו את התוצאה - חסרו את הסכום השני מהראשון והדפיסו
"Difference: "ואחריו את התוצאה - השתמשו ב-
+=כדי להוסיף את הסכום השני לראשון, ואז הדפיסו"After +=: "ואחריו את הסכום הראשון לאחר השינוי
- הדפיסו
עבור המתודה display(), השתמשו ב-std::setw(2) וב-std::setfill('0') מתוך <iomanip> כדי להבטיח שהסנטים תמיד יוצגו בשתי ספרות (למשל, $5.07 ולא $5.7).
המירו מחרוזות קלט למספרים שלמים באמצעות std::stoi(). אל תשכחו להוסיף מגיני הכללה בקובץ הכותרת.
נסו בעצמכם
#include <iostream>
#include <string>
#include "Money.h"
using namespace std;
int main() {
// קרא קלט עבור שני סכומי כסף
string line;
getline(cin, line);
int dollars1 = stoi(line);
getline(cin, line);
int cents1 = stoi(line);
getline(cin, line);
int dollars2 = stoi(line);
getline(cin, line);
int cents2 = stoi(line);
// TODO: צור שני אובייקטים מסוג Money עם ערכי הקלט
// TODO: הדפס "Amount 1: " ואחריו את הסכום הראשון
// TODO: הדפס "Amount 2: " ואחריו את הסכום השני
// TODO: חבר את שני הסכומים והדפס "Sum: " ואחריו את התוצאה
// TODO: חסר את הסכום השני מהראשון והדפס "Difference: " ואחריו את התוצאה
// TODO: השתמש ב-+= כדי להוסיף את הסכום השני לראשון, ואז הדפס "After +=: " ואחריו את הסכום הראשון לאחר השינוי
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++ אונליין