מאמר רביעי בסדרת מאמרים בנושא תכנות מונחה עצמים, והפעם - Using Virtual/Pure Virtual
1 of 2
Download to read offline
More Related Content
בדרך לפולימורפיזם - Using Virtual/Pure Virtual
1. פולימורפיזם – "Using "Virtual" and "Pure Virtual
Virtual Functions
כבר הזכרנו שהרעיון הוא להפוך את הקוד לפולימורפי ככל שניתן ועל כן, יש מקום לדבר על האפשרות ליצור
מצביע יחיד שישמש אותנו גם עבור המחלקה עצמה וגם עבור תתי המחלקות שלה.
היות ותת המחלקה היא נגזרת של המחלקה עצמה, כלומר, יש בה את כל ה – DNAשל מחלקה ההורה ויותר
מכך, אין מניעה לפנות אליה באמצעות אותו המצביע שהיה משמש אותנו אילו רצינו לפנות למחלקת ההורה,
עם ההגבלות הברורות כמובן, שמצביע זה ידע לגשת אך ורק ל membersשמוכרים לו מהמבנה של מחלקת
ההורה ולא לתוספות / שינויים אלו ואחרים שקרו אולי במחלקת הילד.
בחזרה לדוגמה שלנו; נניח ויצרנו פונקציה WhoRUחיצונית למחלקה ,Robotאשר מקבלת כתובת לאינסטנס
של רובוט, כלומר לאובייקט מסוג רובוט, ותפקידה הוא להפעיל את הפונקציה;) ( WhatAreYouעבור אותו
האינסטנס.
הצהרה ומימוש של פונקציה שכזו ייראו כך:
{ ) void WhoRU ( Robot& Bot
} ;) (Bot.WhoAreYou
וקריאה לפונקציה תיעשה באופן הבא:
;)1WhoRU (robot
;)2WhoRU (robot
;)3WhoRU (robot
נשים לב שאנחנו שולחים לפונקציה בכל פעם אינסטנס מתת מחלקה שונה, בפעם הראשונה, אינסטנס של
מחלקת האב ,Robotבפעם השנייה אינסטנס של מחלקת הילד 2 R2Dובפעם השלישית אינסטנס של מחלקת
הילד ,Optimusאך יחד עם זאת, הפונקציה שמקבלת את הכתובת, הוגדרה לקבל כתובת אינסטנס של
מחלקת האב !Robot
במצב זה, הקומפלייר לא יודע שאנחנו מעוניינים לפנות לפונקציות שהוגדרו בתתי המחלקה ולכן הפלטים יהיו
זהים וילקחו ממחלקת האב.
על מנת לפתור סוגיה זו, עלינו לומר לקומפלייר שאנו דורשים התייחסות דווקא לפונקציה של הילד במידה
והיא בעלת אותה הצהרה, ואנו יכולים לעשות זאת על ידי הוספת המילה virtualבראשית הצהרת הפונקציה
במחלקת האב, כך שפונקציה זו תהפוך וירטואלית אם ליורש הוגדרה פונקציה בעלת הצהרה זהה.
כלומר, בעת הגדרת המחלקה ,Robotאו כאשר מתעורר הצורך בהורשה מסוג שכזה, אנו ניגש להצהרת
הפונקציה במחלקת האב ונדאג להוסיף לה את המילה השמורה virtualכך:
{ class Robot
:public
;) (virtual void WhoAreYou
;} ... :private
2. PureVirtual-Abstract Functions
ע" מ להבין את המושג פונקציות אבסטרקטיות או פונקציות וירטואליות טהורות כמו שניתן לכנותן,
ראשית נסביר את המושג אבסטרקט.
אם נשאל את ד"ר גוגל, נקבל תשובה די נכונה:
/ab·stract/abˈstrakt Existing in thought or as an idea but not having a physical or
:Adjective .concrete existence
כלומר, מדובר בפונקציות אשר מהוות קונספט רעיוני כבור פונקציות שעתידות להיגזר מהן.
ע"מ להבהיר את הערפול סביב הנושא, ניקח דוגמה, איך אם לא, מהחיים האמיתיים: בן אדם.
בן אדם הוא קונספט רעיוני, שהרי אף אחד מאיתנו לא באמת פגש פעם בבן אדם. כן, פגשנו את יוסי, שהוא
גבר כבן 03 מלוס אנג'לס, פגשנו גם את רינה, בחורה בת 62 מכפר סבא... אבל הישות הזאת, "בן אדם", היא
לא משהו שקיים באמת כישות בפני עצמה.
אם כן, נוכל לומר ש"בן אדם" הוא טיפוס אבסטרקטי.
כאשר אנו מאפיינים מחלקה, כאמור, אנו חושבים על כל האפשרויות העתידיות עבור מחלקה זו.
אם נחזור לדוגמה שלנו, אותה פיתחנו במאמרים הקודמים בנושא, מחלקת ,Robotניזכר שהיא מכילה את
המתודה .SetName
היות ואנו עובדים בחברה מאוד רצינית לייצור רובוטים, אנו יכולים לייצר63 סוגים שונים של רובוט ועל כן,
למחלקה 36 ,Robotמחלקות יורשות, כ" א מהן מאופיינת בהתאם לסוג הרובוט אותו היא מייצגת.
מכאן, שאין באמת דבר כזה "רובוט". המכונה לא מבינה מה אומרים לה אם מבקשים ממנה "רובוט", היא
מבינה "2 ,"Optimus" ,"R2Dוכד'...
מכאן, ש"רובוט" הוא טיפוס אבסטרקטי. מה הופך אותו לכזה כבר ברור, אבל מה לעשות, צריך לחזור לעולם
הקוד ולשאול, כיצד אנו ממשים את ההבנה שהשגנו כאן ברמת הסינטקס?
ובכן, פונקציות שכאלו, כגון SetNameלמשל, אשר הנן חסרות משמעות פיסית עבור מחלקת האב, אך
חיוניות עבור המחלקות היורשות, ניתנות להגדרה כפונקציות , pure virtualכלומר, פונקציות שאנו מצהירים
מראש ב Base Classשהן חלק אינטגרלי ב , Derived Classאך לא קיימות בפועל ב Base Classעצמו.
בפועל, הגדרה של פונקציה כ Pure Virtualתיעשה באופן הבא במחלקת האב:
{ class Robot
:public
; 0 = ) (virtual void SetName
... :private
;}
בעוד הגדרת מחלקת הילד תתבצע כרגיל:
;{ { class R2D2 : public Robot
אך פרט שחשוב לציין הוא, שאין אפשרות לייצר אינסטנס של2 R2Dלפני שבוצע מימוש של הפונקציה
.SetNameכלומר, 2 R2Dבעצמו הוא אבסטרקטי, עד שמבצעים מימוש של הפונקציה ה Pure Virtualשירש
מ!Robot