אז ככה:
לכל מחלקה שיש בה לפחות פונקציה וירטואלית אחת(או יורשת ממחלקה שיש בה לפחות פונקציה וירטואלית אחת), הקומפיילר מוסיף באופן אוטומטי vtable.
כל רשומה ב- vtable הזה הוא למעשה פוינטר לפונקציה וירטואלית במחלקה הכי נמוכה בעץ ההורשה של אותה מחלקה.
למה אני מתכוון? נניח שיש לנו את המחלקות: class base { public: virtual void f1() {} virtual void f2() {} };class derived { public: virtual void f1() {} };
|
אז, ה VTABLE של מחלקת base יצביע ל f1, ו f2 של base.
ה VTABLE של מחלקת derived, יצביע ל f1 של derived, ול- f2 של base.
הטבלאות נבנות בזמן קמפול.
עכשיו, בנוסף לכל זה, הקומפיילר מוסיף גם מצביע לטבלה - __vfptr כאחד הממברים של המחלקה(כמובן בצורה מוסווית).
עכשיו. בזמן ריצה(!), כאשר המחלקה נבנית(בctor), הruntime של C++ מחליט לאן לאתחל את ה vfptr של כל מחלקה. זה נקרא late binding.
מה שבעצם קורה זה שהruntime בודק את סוג המחלקה: אם היא מסוג derived, הוא יגרום ל vptr להצביע ל vtable של derived. אם היא מסוג base, ה vptr יצביע לטבלה של base.
בשביל להוכיח שאני לא משקר, הנה דגימה מ windbg הנפלא
(אם אתם לא מכירים, רוצו להוריד את כלי הדיבאגינג החזק ביותר שיש ):
זה הכל
לירן.
\x6C\x65\x65\x74\x68\x61\x78\x30
\x72\x3A\x2D\x29
tresp4sser