C++/העמסת אופרטורים: הבדלים בין גרסאות בדף

תוכן שנמחק תוכן שנוסף
Ybungalobill (שיחה | תרומות)
אין תקציר עריכה
Ybungalobill (שיחה | תרומות)
אין תקציר עריכה
שורה 5:
== הגדרת פונקציית האופרטור ==
 
מבחינת המהדר אופרטור הוא פונקציה שכדי לקרוא לה נשתמש בתחביר שונה מזה של קריאה לפונקציה רגילה. להלן חלק מהגדרת מבנה המייצג ווקטור מתמימתמטי דו מימדי ופונקציית האופרטור המחברשמחבר שני ווקטורים נתונים:
<div style="direction: ltr;"><source lang="cpp">
struct Vector2D
שורה 82:
== פרטי האופרטורים הניתנים להעמסה ==
 
בשפת C++ ישנם אופרטורים אוּנָרִיים (בעלי אופרנד אחד), בִינָרִיים (בעלי שני אופרנדים), טֵרְנָרִיים (בעלי שלושה אופרנדים) ואפילו אופרטור קריאה לפונקציה () שמספר האופרנדים בו משתנה. כנאמר למעלה, חלק מהאופרטורים אנו יכולים להגדיר כחברי המחלקה, חלק כפונקציות סטטיות, חלק מותר גם כך וגם כך וחלק אין באפשרותינו להעמיס.
 
להלן רשימת אופרטורים בינאריים הניתנים להעמסה גם כפונקציות המחלקה וגם כפונקציות סטטיות. אם נגדיר אותם כפונקציות סטטיות אז יהיו להן שני פרמטרים, אם נגדיר אותן כחברי מחלקה יהיה להן פרמטר אחד:
בחלק זה נחלק את האופרטורים למספר קטגוריות כדי להקל את ההבנה. נפרט על כל קטגוריה בנפרד.
<div style="direction: ltr;"><source lang="cpp">
=+ *= - /= %=* += / -= <<= >>=% &= |= ^= ,
> << >=> <= <>= == && || !=
</source></div>
 
להלן רשימת אופרטורים בינאריים הניתנים להעמסה רק בתוך המחלקה, לפונקציות אופרטורים אלה יהיה פרמטר אחד תמיד:
=== פעולות חשבוניות בינאריות ===
<div style="direction: ltr;"><source lang="cpp">
= += -= *= /= %= &= |= ^= <<= >>= [] ->*
</source></div>
 
אופרטורים אונריים הניתנים להעמסה מחוץ למחלקה הם, לפונקציות אופרטורים אלה יהיה פרמטר אחד כשהם מחוץ למחלקה ולא יהיו להן פרמטרים כלל כשהם בתוך המחלקה:
נייחס לקטגוריה זו את הפעולות המתמטיות ואת הפעולות על סיביות:
<div style="direction: ltr;"><source lang="cpp">
+~ ! - *+ /* %
& | ^ >> <<
</source></div>
אופרטורים אלה נוכל להגדיר גם כחברי המחלקה וגם כאופרטורים סטטיים (בתוך מרחב שם, כולל גולובלי). כיוון שאופרטורים אלה הם בינאריים הם מקבלים שני אופרנדים. חוק הקיבוץ לא תקף לאופרטורים אלה, אלא אם כן לא נדאג לדבר זה בעצמינו. סדר הקיבוץ של הבטוי שירשור האופרטורים הוא משמאל לימין, כלומר: {{קוד בשורה|(a + b + c)}} זהה ל-{{קוד בשורה|((a + b) + c)}} ולא ל-{{קוד בשורה|(a + (b + c))}}.
 
אופרטורים אונריים הניתנים להעמסה רק בתוך המחלקה הם, לפונקציות אופרטורים אלה אף פעם לא יהיו פרמטרים:
אם אופרטורים אלה הם חברי מחלקה אז האופרנד הראשון יהיה המופע של המחלקה עבורו נקראת פונקציית האופרטור, ואילו האופרנד השני יתקבל דרך הפרמטר היחידי של אותה הפונקציה. לרוב אופרטורים כאלה לא משנים את האובייקט עצמו אלא מחזירים אובייקט חדש, במקרה זה נגדיר אותם כפונקציות const (אפשר לעשות גם אחרת, אם נרצה למשל ש>> ישנה את האופרנד שלו).
 
אם אופרטורים אלה לא יהיו חברי מחלקה, אזי שני הפרמטרים שלהם ייצגו את האופרנדים. למשל:
<div style="direction: ltr;"><source lang="cpp">
-> ++ -- &
struct A {
// ...
A operator * (const A& x) const; // בסדר גמור
A operator + (const A& x, const A& y) const; // שגיאה, יותר מדי פרמטרים - צריך 1 או 0
};
A operator % (const A& x); // שגיאה, חסרים פרמטרים - צריך 2
A operator / (const A& x, int y); // עובד
void operator - (A& x, const A& y); // מותר להחזיר כל ערך, אבל זה יבלבל
</source></div>
 
קביעה זו של השתייכות האופרטור לקבוצה של אלה שמותר להגדיר אותם מחוץ או בתוך המחלקה נעשתה לפי הגיון פשוט: אופרטורים שבמשמעות המקורית שלהם השתמשו באופרנד שהוא lvalue (כלומר אובייקט הנמצא בזיכרון), ניתן להגדיר רק כחברי מחלקה ולא כפונקציות סטטיות. אופרטורים שלא שינו את האופרנדים שלהם ולא עבדו עם הכתובת שלהם (כמו + למשל) ניתן להגדיר גם כפונקציות סטטיות.
זיכרו שהעמסת אופרטורים, מטרתה להקל את הבנת הקוד, לכן לא כדאי להגדיר אופרטורים שלא יתאימו למשמעותם האינטואיטיבית. באופרטור האחרון נצטרך להתשמש כך: {{קוד בשורה|a - b;}} כאשר a, ו-b הם משתנים מטיפוס A. במקרה זה האופרטור לא מחזיר ערך אלה משנה את האופרנד הראשון שלו (a), מה שלא משתלב עם משמעות הסימן '-' אליה אנו רגילים.
 
בחלק זה נפרט על אופרטורים מסויימים בנפרד.
המהדר לא יחליף את סדר האופרנדים מעצמו בשום מקרה, לכן, בהנתן ההגדרות שלמעלה, לא נוכל לכתוב {{קוד בשורה|100/a}}, אולם מותר לכתוב {{קוד בשורה|a/100}}.
 
=== פעולות קלט ופלט ===
שורה 131 ⟵ 127:
 
וכתוצאה יודפס: {{קוד בשורה|<nowiki>pos = (12.0, 32.0)</nowiki>}}.
 
=== פעולות לוגיות ופעולות השוואה ===
 
נייחס לקטגוריה זו את הפעולות:
<div style="direction: ltr;"><source lang="cpp">
> >= < <= == !=
&& ||
</source></div>
 
אופרטורים אלה המוגדרים עבור טיפוסים מובנים מחזירים את הטיפוס הלוגי bool. אם נרצה לשמור על בהירות התוכנית ועל משמעותם האגילה, גם אנחנו נגדיר אותם באופן זה, אלה אם כן נרצה לשנות את משמעות זו.
 
אופרטורים אלה ניתן להגדיר גם כחברי מחלקה וגם כפונקציות סטטיות. גם להם שני אופרנדים. סדר הקיבוץ גם כאן הוא משמאל לימין: {{קוד בשורה|(a && b && c)}} זהה ל-{{קוד בשורה|((a && b) && c)}}.
 
לדוגמה:
<div style="direction: ltr;"><source lang="cpp">
bool operator == (const Vector2D &a, const Vector2D &b)
{
return a.x == b.x && a.y == b.y;
}
</source></div>
 
''הערה:'' בעבודה עם נקודה צפה יש לעשות השוואה עם epsilon עקב אי-דיוק ועיגול התוצאות.
 
=== פעולות השמה ===
 
נייחס לקטגוריה זו את הפעולות:
<div style="direction: ltr;"><source lang="cpp">
= *= /= %= += -= <<= >>= &= |= ^=
</source></div>
 
כיוון שהמשמעות המקורית של אופרטורים אלה היא לבצע שינוי באופרנד השמאלי, אופרטורים אלה צריכים להיות מוגדרים בתוך המחלקה. דבר זה מבטיח שהאופרנד השמאלי ימצא בזיכרון (יהיה lvalue), ומסיבה זו לפונקציות האופרטורים האלה יהיה תמיד רק פרמטר אחד (האופרנד הימני). סדר קיבוץ פעולות אלה הוא מימין לשמאל: {{קוד בשורה|<nowiki>(a = b = c)</nowiki>}} זהה ל-{{קוד בשורה|<nowiki>(a = (b = c))</nowiki>}}.
 
=== פעולות אונריות ===
 
=== הגדלה והפחתה ===