5.2.5. מימוש Dynamic Binding

כיצד ממומש overriding? על ידי מצביעים לפונקציות.

לכל אובייקט יש טבלה של מצביעים אל המימוש המתאים של הפונקציות הוירטואליות שלו.

טבלה זו – Virtual Methods Table, מכונה בקיצור vtbl.

נגדיש: רק פונקציות וירטואליות מופיעות ב-vtbl. פונקציות שאינן וירטואליות מקושרות סטאטית בזמן ההידור. כמו כן, פונקציה שהיא overloading, מספר פונקציות עם מספר פרמטרים משתנה, מופיעים כמספר כניסות נפרדות בטבלה.

טבלת המצביעים לפונק' מתעדכנת כשנוצר עצם מהמחלקה.

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

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

במצב אידיאלי, היינו רוצים שלכל מחלקה תהיה vtbl יחידה, כך שנוכל לזהות שכל העצמים המצביעים אל אותה vtbl שייכים למחלקה הנ"ל.

ב-C++ מודל הקומפילציה הוא כזה שאינו מאפשר לנו להשיג מטרה זו. המודל הוא מודל קומפילציה נפרדת. כל קובץ עובר קומפילציה בנפרד. אפשר לאסוף לתוכנית אחת קבצים שקומפלו בזמן שונה ואפילו במחשבים שונים. לפיכך - המהדר צריך ליצור vtbl עבור כל קובץ בפרויקט.

כאמור לכל אובייקט יש טבלת מצביעים לפונקציות המתאימה לו. הטבלה ממוקמת במקום כלשהו בזיכרון. על מנת לגשת אליה, קיים בכל אובייקט שדה נוסף בשם vptr, המצביע אל הטבלה הנ"ל.

מתעוררת השאלה היכן נמקם את מצביע זה.

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

ב-dynamic binding, על השפה לדאוג שהוא לא ישלם עלויות עבור תמיכה במנגנון זה.

מיד נראה שגישה זו יוצרת מספר סיבוכים במימוש מנגנון ה-dynamic binding.



מאת: ניצן

Borland style vptr

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