העמסת אופרטורי השוואה
חלק מהיחידה תכנות מונחה עצמים במסלול ה-C++ של Coddy. שיעור 42 מתוך 104.
אופרטורי השוואה כמו ==, !=, <, >, <= ו־>= מאפשרים לך להשוות אובייקטים מהמחלקות המותאמות אישית שלך. אופרטורים אלה מחזירים bool ויש לסמן אותם ב־const, מכיוון שהם אינם משנים אף אחד מהאופרנדים.
class Date {
int year, month, day;
public:
Date(int y, int m, int d) : year(y), month(m), day(d) {}
bool operator==(const Date& other) const {
return year == other.year &&
month == other.month &&
day == other.day;
}
bool operator<(const Date& other) const {
if (year != other.year) return year < other.year;
if (month != other.month) return month < other.month;
return day < other.day;
}
};טכניקה שימושית היא לממש אופרטורי השוואה אחרים באמצעות אלה שכבר הגדרת. לאחר שהגדרת את == ואת <, השאר נובעים באופן טבעי:
bool operator!=(const Date& other) const {
return !(*this == other);
}
bool operator>(const Date& other) const {
return other < *this;
}
bool operator<=(const Date& other) const {
return !(other < *this);
}
bool operator>=(const Date& other) const {
return !(*this < other);
}הגישה הזו מפחיתה כפילויות בקוד ומבטיחה שכל אופרטורי ההשוואה שלך יתנהגו באופן עקבי. אם תשנה בהמשך את אופן הפעולה של שוויון או של אופרטור קטן מ־, שאר האופרטורים יישארו מסונכרנים באופן אוטומטי.
אתגר
קלנבנה מחלקה Version שמייצגת מספרי גרסאות של תוכנה (כמו 2.1.0 או 3.0.5) ותומכת בכל ששת אופרטורי ההשוואה. זהו שימוש מעשי שבו השוואה בין גרסאות קובעת איזו תוכנה חדשה יותר, ומקרה מושלם לתרגול העמסת אופרטורי השוואה.
תיצרו שני קבצים כדי לארגן את הקוד:
Version.h: הגדירו מחלקהVersionששומרת שלושה מספרים שלמים המייצגים מספרי גרסה ראשית, משנית ותיקון. המחלקה צריכה לתמוך ב:- בנאי שמקבל ערכים של גרסה ראשית, משנית ותיקון
- פעולות גישה לכל רכיב:
getMajor(),getMinor(),getPatch()(כולן const) - כל ששת אופרטורי ההשוואה:
==,!=,<,>,<=,>= - מתודה
toString()שמחזירה את הגרסה כמחרוזת בפורמט"major.minor.patch"
ממשו ישירות את
==ואת<, ואז הגדירו את ארבעת האופרטורים הנותרים באמצעות שני אלה. בהשוואת קטן מ, השוו תחילה את הגרסה הראשית, אחר כך את המשנית אם הגרסאות הראשיות שוות, ולבסוף את גרסת התיקון אם גם הגרסאות הראשיות וגם המשניות שוות. כל אופרטורי ההשוואה צריכים להיות פונקציות חברות const.main.cpp: קראו מהקלט שישה מספרים שלמים המייצגים שתי גרסאות (major1, minor1, patch1, major2, minor2, patch2, כל אחד בשורה נפרדת). צרו שני אובייקטים מסוגVersionוהשוו ביניהם באמצעות כל האופרטורים שלכם.פורמט הפלט:
Version 1: <v1> Version 2: <v2> v1 == v2: <true/false> v1 != v2: <true/false> v1 < v2: <true/false> v1 > v2: <true/false> v1 <= v2: <true/false> v1 >= v2: <true/false>הדפיסו
trueאוfalse(באותיות קטנות) עבור כל תוצאת השוואה.
הטכניקה המרכזית כאן היא לממש את ארבעת האופרטורים הנגזרים (!=, >, <=, >=) באמצעות == ו-< בלבד. כך מצמצמים כפילות בקוד ומבטיחים שכל האופרטורים יישארו עקביים אם תשנו אי פעם את לוגיקת ההשוואה.
המירו מחרוזות קלט למספרים שלמים באמצעות std::stoi(). השתמשו ב-std::to_string() כדי לבנות את מחרוזת הגרסה. אל תשכחו להוסיף הגנות כותרת לקובץ הכותרת.
נסו בעצמכם
#include <iostream>
#include <string>
#include "Version.h"
using namespace std;
int main() {
// קראו שישה מספרים שלמים עבור שתי גרסאות
string line;
getline(cin, line);
int major1 = stoi(line);
getline(cin, line);
int minor1 = stoi(line);
getline(cin, line);
int patch1 = stoi(line);
getline(cin, line);
int major2 = stoi(line);
getline(cin, line);
int minor2 = stoi(line);
getline(cin, line);
int patch2 = stoi(line);
// TODO: צרו שני אובייקטים מסוג Version
// TODO: הציגו את Version 1 ואת Version 2 באמצעות toString()
// TODO: השוו באמצעות כל ששת האופרטורים והציגו את התוצאות
// השתמשו ב-"true" או ב-"false" (באותיות קטנות) עבור כל השוואה
// פורמט: "v1 == v2: true" או "v1 == v2: false"
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++ אונליין