פולימורפיזם (מדעי המחשב)

במדעי המחשב, פולימורפיזםאנגלית Polymorphism, בעברית: רב־צורתיות) הוא תכונה של שפות תכנות המאפשרת לכתוב קוד מופשט מבחינת הטיפוס. הקוד האבסטרקטי ירוץ בצורה שונה, בהתאם לטיפוס עליו הוא עובד. כך אפשר לכתוב פעם אחת קוד המקבל משמעויות שונות בהקשרים שונים. פולימורפיזם הוא הדרך המקובלת בעולם התוכנה לבצע הפשטה מושגית.

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

סוגי הפולימורפיזם השונים

מבחינים בין סוגים של פולימורפיזם:

  • העמסה - הגדרה של מספר פונקציות שונות בעלות אותו שם, כך שהמהדר מחליט בדרך כלשהי באיזו מהפונקציות להשתמש, על פי הטיפוס של הערכים המועברים כפרמטר. בשפות מסוימות העמסה מוגדרת עבור מספר טיפוסים קבועים מראש. דוגמה לכך היא אופרטור החיבור בשפת C, המוגדר עבור חיבור בין מספרים שלמים ובין מספרים ממשיים (4+5 או 3.2+5.4). שפות רבות מאפשרות למתכנת להגדיר העמסה באופן ידני.
  • פולימורפיזם פרמטרי - היכולת לתת פרמטריזציה עבור מבנים של שפת התכנות. למשל פונקציות בשפה לא מוגדרות עבור טיפוס ספציפי, וכך מסוגלות לטפל במגוון רחב (ואינסופי) של טיפוסים שונים. פונקציות כאלה נקראות פונקציות פולימורפיות. ישנם שני סוגים של פולימורפיזם כזה:
    • Let-Polymorphism, שהדוגמה הבולטת עבורו היא פונקציות בשפת ML ובשפות פונקציונליות נוספות, כגון Haskell. הפרמטריזציה עבור פונקציות אלה איננה מפורשת, אלא אך ורק מוסקת מתוכן הפונקציה.
    • פולימורפיזם פרמטרי מפורש, כגון תבניות (Templates) בשפת ++C, וכן מבנים מסוימים בשפת ML והאסקל. בתכנות מונחה-עצמים, שימוש בפולימורפיזם פרמטרי נקרא תכנות גנרי. פולימורפיזם כזה, במימוש אידיאלי, ממומש על פי רוב בזמן הידור.
  • פולימורפיזם של תת-טיפוס (או פולימורפיזם הכלה) ממומש על פי רוב בשפות תכנות מונחות-עצמים. מושג זה מתורת הטיפוסים אומר שמזהה עשוי להתייחס למופע השייך למספר כלשהו של מחלקות, כל עוד הן חולקות ביניהן מחלקת אם משותפת. פולימורפיזם כזה מנצל את היכולת לבצע חיפוש דינמי בזמן ריצה, ובביצוע דריסה של מתודות.
  • Type Coercion - המרה אוטומטית ומובלעת בין טיפוסים. דוגמה להמרה כזאת היא ההרחבה של המספר 4 ממספר שלם למספר ממשי בביטוי 4+5.2 (בשפות התכנות המאפשרות כתיבה של ביטוי כזה). ניתן להראות שהמרה כזאת היא שקולה לפולימורפיזם של תת-טיפוסים (ירושה), ואכן, שפת D משתמשת במנגנון הזה כדרך לדמות ירושה מרובה.

הרעיון הבסיסי

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

פולימורפיזם אד-הוק

העמסה (Overloading)

פולימורפיזם בצורתו הבסיסית ביותר קיים בכל שפת תכנות עילית. כאשר כותבים ביטויים כגון (4 + 4) או (5.3 + 2.1), אנו מנצלים את העובדה שאופרטור החיבור מועמס - כלומר, בעל משמעות כפולה - גם לטיפוס המשמש למספרים שלמים כמו 4, וגם לטיפוס המשמש לייצוג מספרים ממשיים כמו 2.1; זאת, אף על פי שהייצוג של מספרים אלו כביטים בשפת המכונה שונה לחלוטין בין מספרים שלמים למספרים ממשיים, ולכן גם פקודות המכונה המורות למעבד לבצע את פעולת החיבור תהיינה שונות; כל זה שקוף למתכנת, ולכן מקל על עבודתו.

המרה (Coercion)

שפת C מאפשרת צורה מוגבלת מאוד של פולימורפיזם, נוסף על העמסה בסיסית של אופרטורים אריתמטיים: בשפה מוגדרת המרה אוטומטית מכל טיפוס של מצביע אל הטיפוס הגנרי *void, ובחזרה. מנגנון זה מנוצל על ידי פונקציות כגון פונקציית הספרייה הסטנדרטית qsort המשמשת למיון מערך, המקבלת מערך של מצביעים וממיינת אותו, תוך התייחסות אל כל המצביעים במערך כ-*void. טכניקה זו מאפשרת לבצע כל פעולה, אך היא איננה גמישה, ומצריכה מידע מפורש מהמתכנת בקשר לגודל של משתנים מהטיפוס שמועבר בפועל - מידע שאמור להימצא בידי המהדר בזמן הידור התוכנית, ולכן דורשת עבודה מיותרת. שפות אחרות, כגון שפת פסקל, לעיתים אינן מאפשרות אפילו גנריות בסיסית כזאת.

פולימורפיזם פרמטרי

שפת C

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

#define min(x,y) ( ((x) < (y)) ? (x) : (y) )

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

שפת ++C

בשפת ++C‏, פולימורפיזם פרמטרי ממומש בזמן הידור, תוך שימוש בתבניות (templates):

template <typename T>
T max(T x, T y)
{
 return x < y ? y : x;
}

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

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

ספריית התבניות התקנית של שפת ++C היא דוגמה לתכנות גנרי, ומבוססת ברובה על פולימורפיזם פרמטרי ושימוש בתבניות.

שפת עדה מאפשרת אף היא תכנות גנרי באופן דומה לתבניות של ++C.

שפת ML

בשפת ML, התומכת בפולימורפיזם מלא ומתוחכם, הדבר מתבצע כך: המתכנת כותב פונקציה, למשל פונקציה שהופכת רשימה, בדרך הטבעית לו, ללא הצהרה על הטיפוס אותו הפונקציה מקבלת. המהדר של השפה מסיק לבד, על פי הביטויים המשמשים בפונקציה, אילו טיפוסים ניתן להעביר אליה. טיפוסים אלה עשויים להיות קונקרטיים, כגון int שהוא מספר שלם, או גנריים, ואז הם יסומנו בתג ושם, למשל a' - זה בעצם "משתנה טיפוס" (type variable). המנגנון ידרוש עקביות: אם פונקציה מקבל שני ארגומנטים מטיפוס a', ניתן להעביר אליה שני משתנים שהם מספר שלם או שני משתנים שהם מספר ממשי, אך לעולם לא משתנה אחד ממשי ואחד שלם, כיוון ששני הארגומנטים חייבים להיות מאותו טיפוס.

דוגמה לפונקציה פולימורפית בשפת ML:

fun f x = [x,x,x];

פונקציה זאת מקבל ערך x מכל טיפוס שהוא, ומחזירה רשימה של שלושה איברים שערכם x. הטיפוס של הפונקציה הוא "פונקציה מטיפוס a אל רשימה של a". בניגוד לתבניות של שפת ++C פונקציה פולימורפית היא פונקציה לכל דבר.

גם שפת Haskell תומכת בפולימורפיזם פרמטרי באופן דומה, ואף נרחב יותר.

שפת ג'אווה

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

שפת #C

בשפת C# ישנן מתודות גנריות.[1]

פולימורפיזם של תת-טיפוסים

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

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

בשפת C# אפשר לבצע פולימורפיזם של תת-טיפוס בכמה דרכים: באמצעות שיטות וירטואליות, באמצעות ממשקים ובאמצעות מחלקה אבסטרקטית.

מנגנונים הרווחים ברב צורתיות

מנגנונים הרווחים ברב צורתיות, הם:

  • דריסה (Override) שבה ניתן להחליף פונקציה של מחלקת בסיס בפונקציה שונה במחלקה הנגזרת ממנה. באמצעות מנגנון זה ניתן להתאים את הפעולה לסוג המיוחד של האובייקט. שם הפעולה נשמר והיא מתבצעת בדרכים שונות בהתאם לאובייקט אליו היא מתייחסת. טכניקה נוספת היא הצללה שדומה ליכולת הדריסה.
  • העמסת אופרטורים (Operator Overloading), היא מקרה פרטי של העמסת פונקציות, שבו אופרטור מסוים מקבל מכניזם פנימי שונה בתוך אובייקט. למשל אופרטור + שנועד לחבר מספרים, במחלקה של מחרוזות מקבל יכולת שרשור, ובמחלקה של מערכים יכול לקבל יכולת לחבר בין שני מערכים.

דוגמאות

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

  1. עצרו בצד והציבו סימנים המיידעים שהרכב בטיפול.
  2. הציבו את המגבה במקומו ושחררו מעט את בורגי הגלגל.
  3. הגביהו את הרכב בעזרת המגבה.
  4. פרקו את הגלגל והרכיבו במקומו גלגל תקין.
  5. חזקו מעט את הברגים.
  6. הנמיכו את הרכב עד שהגלגל יגע קלות בקרקע.
  7. חזקו את בורגי הגלגל בהצלבה.
  8. הנמיכו את הרכב, איספו את הכלים והמשיכו בנסיעה.

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

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

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

  1. בחרו וקטור כלשהו ונרמלו אותו.
  2. בחרו וקטור נוסף והטילו אותו על תת-המרחב הנפרש על ידי הווקטורים שכבר בחרתם.
  3. מצאו את ההפרש בין הווקטור להטלה שלו, נרמלו אותו והוסיפו אותו לרשימת הווקטורים שכבר נבחרו.
  4. חיזרו על הפעולות 2 ו-3 עד שיגמרו הווקטורים בבסיס המקורי. רשימת הווקטורים שנבחרו מהווה בסיס אורתונורמלי למרחב.

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

מימוש בתכנות

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

 class Car {...};

 class Bus: public Car{...};

 class PrivateCar: public Car{...};
 void changeWheel(Car *p) {
 p->stop();
 p->placeJack();
 p->lift();
 ...
 }
 int main() {
 Car* array[3];
 array[0]=new Bus();
 array[1]=new PrivateCar();
 array[2]=new Bus();
 for(int i=0;i<3; ++i)
 changeWheel(array[i]);
 }

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

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

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

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

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

מימוש פולימורפיזם על ידי המהדר

נתבונן שוב בקטע הקוד המממש פולימורפיזם בזמן ריצה:

void changeWheel(Car *p) {
 p->stop();
 p->placeJack();
 p->lift();
 ...
}

נשאלת השאלה כיצד מתורגם קטע זה לשפת מכונה. לדוגמה הפעלת הפונקציה stop:

p->stop();

בניגוד להפעלת פונקציה רגילה, בזמן ההידור לא ידוע איזה קוד יש להפעיל. האם מדובר ב -() Bus::stop ,ב -() PrivateCar::stop או אולי פונקציית stop של טיפוס אחר. התשובה לשאלה זו מתבררת רק בזמן ריצה, כאשר ידוע על איזה טיפוס ספציפי מצביע p. הקומפיילר, אם כן, צריך לייצר קוד הקורא לפונקציה מסוימת בהתאם לטיפוס האובייקט שמוצבע על ידי p באותו הרגע. כדי לייצר קוד כזה, יש להתייחס לקוד הנמצא בכתובת משתנה. במילים אחרות יש להשתמש במושג של מצביע לפונקציה.

הקוד הבא מדגים איך אפשר לממש פולימורפיזם בשפת C, שפה שלא תומכת בפולימורפיזם באופן מובנה:

 #include <malloc.h>
 #include <stdio.h>

 typedef void (*fun_t)(void);

 typedef struct Car {
 fun_t stop;
 /* fun_t placeJack, lift, ... */
 } Car;

 Car* createCar(fun_t stopFunction) {/*fun_t placeJackFunction, fun_t liftFunction,...*/
 Car *p = (Car*)malloc(sizeof(Car));
 p->stop = stopFunction;
 /* p->placeJack = placeJackFunction; p->lift = ... */
 return p;
 }

 void busStop() { printf("Stopping the bus...\n"); }
 /* void busPlaceJack() {...} void busLift() {...} ... */
 Car* createBus() { return createCar(busStop); }

 void privateStop() { printf("Stopping the private car...\n"); }
 /* void privatePlaceJack() {...} void privateLift() {...} ... */
 Car* createPrivate() { return createCar(privateStop); }

 void changeWheel(Car *car) {
 car->stop();
 /* car->placeJack(); car->lift();... */
 }

 int main() {
 Car *p1 = createBus(), *p2 = createPrivate();
 changeWheel(p1);
 changeWheel(p2);
 /* free memory .. */
 return 0;
 }

הדוגמה האחרונה פשטנית במקצת. היא מתחמקת מבעיות טכניות שונות המופיעות באובייקטים פחות מנוונים מאלה שבדוגמה. בנוסף, ניתן לראות שהשיטה המוצגת בדוגמה, בזבזנית בזיכרון. עבור כל אובייקט (מכונית) יש לשמור מספר מצביעים לפונקציות כמספר הפונקציות שיש למכונית. אותם מצביעים לפונקציות יכולים להוות את רוב הזיכרון הדרוש לאחסון האובייקט. בזבוז הזיכרון נובע מהעובדה, שאוסף הפונקציות עליהם מצביע האובייקט הוא מאפיין של ה - class ולא של האובייקט הספציפי. לדוגמה, לכל האובייקטים מסוג Bus יהיו בדיוק אותם ערכים בכל מצביעי הפונקציות שלהם.

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

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

 p1.placeJack()

יתורגם לקוד הדומה לקוד הבא:

 p1.m_vtbl_ptr[2]()

כפי שניתן לראות, קיימת כאן הסתמכות על העובדה שהפונקציה placeJack נמצאת תמיד באותו אינדקס, בכל הטבלאות הווירטואליות (במקרה זה - 2).

מחיר פולימורפיזם הממומש על ידי virtual table

מבחינת זיכרון, כאשר ל-Class יש לפחות פונקציה פולימורפית (וירטואלית) אחת, כל אובייקט מסוגו (ומסוג יורשיו) יכיל מצביע virtual table pointer. עבור אובייקטים גדולים הדבר עשוי להיות זניח אבל עבור אובייקטים קטנים, במיוחד אם יש מופעים רבים שלהם, הדבר עלול להיות משמעותי.

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

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

לקריאה נוספת

  • John C. Mitchell, Concepts In Programming Languages, Cambridge University Press, 2003 פרק 6
  • David A. Watt, Programming Language Concepts and Paradigms, פרק 7

קישורים חיצוניים

הערות שוליים

Read other articles:

Dutch artist (1625–1657) Woman spinning with a child in an interior (Dutch: Spinster) Geertruydt Roghman (1625, in Amsterdam – 1657, in Amsterdam), was a Dutch Golden Age painter, engraver, and printmaker. Biography Roghman was born in Amsterdam, the daughter of the engraver Henrick Lambertsz Roghman and Maria Jacobs Savery. According to the RKD she was the oldest sister of Roelant and Magdalena Roghman and the granddaughter of the painter Roelant Savery through her mother.[1] She...

 

Taiwan railways redirects here. For the national railway of Taiwan, see Taiwan Railway. TaiwanOperationNational railwayTaiwan RailwayMajor operatorsTaiwan High Speed RailStatisticsRidership287 million[1] (2016)Passenger km21.5 billion[1] (2016)System lengthTotal2,033 kilometres (1,263 mi)Double track107 km (66 mi)Electrified1,233 km (766 mi)High-speed352 km (219 mi)Track gaugeMain1,067 mm (3 ft 6 in)High-speed1,435...

 

United States Senate special election 1855 United States Senate special election in Massachusetts ← 1853 January 23 and 31, 1855 1859 → 40 members of the Massachusetts Senate396 members of the Massachusetts HouseMajority vote of both houses needed to win   Nominee Henry Wilson Party Know Nothing Senate 21 Percentage 52.5% House 234 Percentage 57.8% U.S. senator before election Julius Rockwell Whig Elected U.S. senator Henry Wilson Know Nothing The 1855 United States...

Football league seasonBulgarian State Football ChampionshipVladislav Varna with the title in 1925.Season1925ChampionsVladislav VarnaMatches played5Goals scored18 (3.6 per match)← 1924 1926 → The 1925 Bulgarian State Football Championship was the second edition of the competition. It was contested by 6 teams, and Vladislav Varna won the championship by beating Levski Sofia 2–0 in the finals. They became the first football champions of Bulgaria. Qualified teams The teams that partici...

 

Television channel Comedy CentralCountryFranceBroadcast areaFrance, Switzerland, BelgiumProgrammingLanguage(s)FrenchPicture format1080i HDTVOwnershipOwnerParamount Networks FranceSister channelsMTVMTV HitsBETNickelodeonNickelodeon JuniorNickelodeon TeenGame OneJ-OneParamount ChannelHistoryLaunched4 October 2018LinksWebsitewww.comedycentral.frAvailabilityStreaming mediaMyCanalcanalplus.com/liveMolotov.tvWatch live Comedy Central is a French pay television channel operated by Paramount France....

 

Progress 31A Progress 7K-TG spacecraftMission typeMir resupplyCOSPAR ID1987-066A SATCAT no.18283[1] Spacecraft propertiesSpacecraftProgress (No.138)Spacecraft typeProgress 7K-TG[2]ManufacturerNPO Energia Start of missionLaunch date3 August 1987, 20:44:11 UTC[1]RocketSoyuz-U2[2]Launch siteBaikonur, Site 1/5 End of missionDisposalDeorbitedDecay date23 September 1987, 00:22:00 UTC[3] Orbital parametersReference systemGeocentricRegimeLow EarthPerigee ...

يفتقر محتوى هذه المقالة إلى الاستشهاد بمصادر. فضلاً، ساهم في تطوير هذه المقالة من خلال إضافة مصادر موثوق بها. أي معلومات غير موثقة يمكن التشكيك بها وإزالتها. (نوفمبر 2019) الدوري السوفيتي الممتاز لكرة القدم 1978 تفاصيل الموسم الدوري السوفييتي الممتاز  النسخة 42  البلد الات�...

 

Prva makedonska fudbalska ligaSport Calcio TipoSquadre di club FederazioneFFM Paese Macedonia del Nord OrganizzatoreFederazione calcistica della Macedonia del Nord TitoloCampione della Macedonia del Nord Cadenzaannuale Aperturaagosto Chiusuramaggio Partecipanti12 squadre Formulagirone doppio A/R/A/R Retrocessione inVtora liga Sito Internetffm.com.mk StoriaFondazione1992 Numero edizioni26 Detentore Struga Record vittorie Vardar (11) Ultima edizionePrva makedonska fudbalska liga ...

 

Australian politician The HonourableMichael RonaldsonMinister for Veterans' AffairsIn office18 September 2013 – 21 September 2015Prime MinisterTony AbbottMalcolm TurnbullPreceded byWarren SnowdonSucceeded byStuart RobertMinister Assisting the Prime Minister for the Centenary of ANZACIn office18 September 2013 – 21 September 2015Prime MinisterTony AbbottMalcolm TurnbullPreceded byWarren SnowdonSucceeded byStuart RobertSpecial Minister of StateIn office18 September 2013...

Pitt Street beralih ke halaman ini. Untuk nama jalan sama di tempat lain, lihat Pitt Street (disambiguasi). Pitt St sekitar tahun 1900 Pitt Street adalah jalan terbesar kedua di Australia yang terletak di distrik bisnis pusat Sydney, New South Wales, Australia. Pitt St terkenal karena mempunyai distrik Pitt St Mall, yang berawal di persimpangan Pitt St dan Market St. Pitt St Mall adalah jalan paling mahal di Australia dan termahal ke-7 di dunia. Riteler terbesar Australia, Westfields akan mem...

 

Ця стаття потребує додаткових посилань на джерела для поліпшення її перевірності. Будь ласка, допоможіть удосконалити цю статтю, додавши посилання на надійні (авторитетні) джерела. Зверніться на сторінку обговорення за поясненнями та допоможіть виправити недоліки. Мат...

 

周處除三害The Pig, The Snake and The Pigeon正式版海報基本资料导演黃精甫监制李烈黃江豐動作指導洪昰顥编剧黃精甫主演阮經天袁富華陳以文王淨李李仁謝瓊煖配乐盧律銘林孝親林思妤保卜摄影王金城剪辑黃精甫林雍益制片商一種態度電影股份有限公司片长134分鐘产地 臺灣语言國語粵語台語上映及发行上映日期 2023年10月6日 (2023-10-06)(台灣) 2023年11月2日 (2023-11-02)(香�...

土库曼斯坦总统土库曼斯坦国徽土库曼斯坦总统旗現任谢尔达尔·别尔德穆哈梅多夫自2022年3月19日官邸阿什哈巴德总统府(Oguzkhan Presidential Palace)機關所在地阿什哈巴德任命者直接选举任期7年,可连选连任首任萨帕尔穆拉特·尼亚佐夫设立1991年10月27日 土库曼斯坦土库曼斯坦政府与政治 国家政府 土库曼斯坦宪法 国旗 国徽 国歌 立法機關(英语:National Council of Turkmenistan) ...

 

2020年夏季奥林匹克运动会波兰代表團波兰国旗IOC編碼POLNOC波蘭奧林匹克委員會網站olimpijski.pl(英文)(波兰文)2020年夏季奥林匹克运动会(東京)2021年7月23日至8月8日(受2019冠状病毒病疫情影响推迟,但仍保留原定名称)運動員206參賽項目24个大项旗手开幕式:帕维尔·科热尼奥夫斯基(游泳)和马娅·沃什乔夫斯卡(自行车)[1]闭幕式:卡罗利娜·纳亚(皮划艇)&#...

 

دي أغوستينيمعلومات عامةالبلد  إيطاليا التأسيس 1901 النوع عمل تجاري — منظمة الشكل القانوني شركة مساهمة المقر الرئيسي نُفارة مواقع الويب deagostini.com… ideahobby.it المنظومة الاقتصاديةالشركة الأم Gruppo De Agostini (it) الشركات التابعة Editions Atlas (en) UTET (en) الصناعة شركة قابضة أهم الشخصياتالمؤسس G...

A Northern Song coin (sheng song yuan bao 聖宋元寶) The economy of the Song dynasty (960–1279) has been characterized as the most prosperous in the world at the time.[1] The dynasty moved away from the top-down command economy of the Tang dynasty (618–907) and made extensive use of market mechanisms as national income grew to be around three times that of 12th century Europe.[2] The dynasty was beset by invasions and border pressure, lost control of North China in 112...

 

This article may require cleanup to meet Wikipedia's quality standards. No cleanup reason has been specified. Please help improve this article if you can. (October 2010) (Learn how and when to remove this message) Methods have been devised to modify the yield strength, ductility, and toughness of both crystalline and amorphous materials. These strengthening mechanisms give engineers the ability to tailor the mechanical properties of materials to suit a variety of different applications. For e...

 

Japanese sprinter and long jumper Ayako YoshikawaAyako Yoshikawa at the 1952 OlympicsPersonal informationBorn(1933-03-01)March 1, 1933SportSportAthleticsEvent(s)Sprint, long jumpAchievements and titlesPersonal best(s)100 m – 12.0 (1951)LJ – 5.75 m (1952) Medal record Representing  Japan Asian Games 1951 New Delhi 4×100 m 1951 New Delhi Long jump Ayako Yoshikawa (吉川 綾子, Yoshikawa Ayako, later Hoshino, born March 1, 1933) is a Japanese retired athlete. She won a gold medal in ...

PolandiaJulukanBiało-czerwoni (Si Putih dan Merah)Orły (Si Elang)AsosiasiAsosiasi Sepak Bola Polandia (PZPN)KonfederasiUEFA (Eropa)Pelatih Michał ProbierzKaptenRobert LewandowskiPenampilan terbanyakRobert Lewandowski (128)Pencetak gol terbanyakRobert Lewandowski (74)Stadion kandangStadion Nasional WarsawaKode FIFAPOLPeringkat FIFATerkini 26 2 (20 Juni 2024)[1]Tertinggi5 (Agustus 2017)Terendah78 (November 2013)Peringkat EloTerkini 39 14 (19 Januari 2024)[2] Warna pertama War...

 

Coppa dell'Imperatore 1984第64回天皇杯全日本サッカー選手権大会 Competizione Coppa dell'Imperatore Sport Calcio Edizione 64ª Organizzatore JFA Date 15 dicembre 1984 - 1º gennaio 1985 Luogo  Giappone Partecipanti 32 Risultati Vincitore  Yomiuri(1º titolo) Secondo  Furukawa Electric Statistiche Incontri disputati 31 Cronologia della competizione 1983 1985 Manuale La Coppa dell'Imperatore 1984 (第64回天皇杯全日本サッカー選手権大会?, Dai 61...