5.3.1. הצגת הנושא

שמורות של המחלקה – תכונות בסיסיות המשותפות לכל איברי המחלקה.

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

למחלקת הבן מותר להגביל יותר את השמורות, אך לא להגביל פחות. למשל, אם ערך של שדה מסוים במחלקה האב נקבע שהוא בין 1 ל-100, מחלקת הבן יכולה להחליט שתחום ערכים חוקי בשבילו הוא בין 1 ל-50, אולם היא איננה יכולה לפתע להחליט שהערכים בו יהיו בין 1 ל-200 – זו תהיה פגיעה בתאימות – ייתכן שיהיה מצב בו נוכל להשתמש באובייקט של מחלקת האב, אך לא באובייקט של מחלקת הבן.

המצב הכללי: על עצם a מפעילים מתודה f שמקבלת עצם b ומחזירה תוצאה אל c:

c = a.f(b);

תאימות: אם השורה הנ"ל עבדה נכון לפני ההורשה, היא תעבור גם אחרי.

הפונקציה f() החדשה צריכה לעמוד לספק לפחות את אותם שירותים שהפונקציה הקודמת נתנה.

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

דגש נוסף: אם קוד מסוים עבר הידור לפני שהגדרנו הורשה, הוא צריך להיות בר-קומפילציה גם אחרי ההורשה. כמו כן, בהינתן מחלקת D הנורשת מ-A והאובייקטים a, d שהינם עצמים השייכים למחלקות אלו, הקוד הבא חייב אף הוא לעבור קומפילציה:

c = d.f(b);

וזאת מכיוון שכל מה שעבד עבור אובייקטים של המחלקה A, חייב לעבוד גם עבור אובייקטים של D.



מאת: ניצן

Borland style vptr

לפי מה שאני מכיר:
"חסרון בגישה זו: גם כאשר איננו משתמשים ב-dynamic binding – אנחנו משלמים במקום"
לא נכון , עבור מחלקה A שאין לה מתודות דינמיות לא יווצר כלל המצביע, ולמשל עבור מחלקה B שיורשת מA פשוט נוסיף בהתחלה את המצביע, ואחרי הבלוק של A את שאר האינפורמציה של B . וככה לא משלמים על מה שלא משתמשים ועקרונות C++ נשמרים.
מה שכן באמת הcasting קצת יותר מסובך....
שיתוף:
| עוד