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

 

מחלקות בסיס וירטואליות

אלמנט שנוי במחלוקת יכול להיות מוצג בתוכניות של ++c מתי שיש הכפלה של מחלקות בסיס בהורשה ,לדוגמה תוכנית שהיא שגויה:


// this program contains an error and will not compile.

# include < iostream >
class base  {
public :
       int i ;
};

//derived1 inherits base . 
class derived1 : public base { 
public :
       int j ;
};

//derived2 inherits base . 
class derived2 : public base { 
public :
       int k ;
};

//derived3 inherits both derived1 and derived1 and derived2.
//this means that there are two copies of base in derived3!.
class  derived3 : public derived1 , public derived2 {
public :
       int sum ;
};
int main ( )
{
       derived3 ob;
       ob.i = 10 ; //this is ambiguous , which  i  ??
       ob.j = 20 ;
       ob.k = 30;
// i  ambiguous here  ,too 
       ob.sum = ob.i + ob.j + ob.k ;
//also ambiguous , which i  ?
       cout <<ob.i<< " ";
       cout << ob.j << " " << ob.k <<  " " ;
       cout  << ob.sum ;
       return  0 ;
}



כפי שההערות בתוכנית מצביעות ,גם derived1 ו derived2 יורשות מbase . בכל מקרה derived3 יורש גם מ derived1 ו derived2 .זה אומר שיש שני העתקים של base בהווה מאובייקט מסוג derived3 .לכן ביטוי מהסוג הזה ob.i = 10; אשר i מיוחס ל,האחד בderived1 או לderived2 ? בגלל שיש שני עותקים של אובייקט ob מסוג base . כפי שאתה יכול לראות , ההצהרה שעוברת בירושה שנויה במחלוקת.ישנם שני דרכים להקדים תרופה לתוכנית . הפתרון הראשון להכיר את טווח ההכרה של האופרטור i ובאופן ידני לבחור i אחד.לדוגמה , גירסה לתוכנית שתתקמפל ותרוץ כמצופה.

//this program  uses explicit scope resolution to select i .
# include < iostream >
class base  {
public :
       int i ;
};

//derived1 inherits base . 
class derived1 : public base { 
public :
       int j ;
};

//derived2 inherits base . 
class derived2 : public base { 
public :
       int k ;
};

//derived3 inherits both derived1 and derived1 and derived2.
//this means that there are two copies of base in derived3!.
class  derived3 : public derived1 , public derived2 {
public :
       int sum ;
};
int main ( )
{
       derived3 ob;
       ob.derived1 :: i = 10 ; //scope resolved , use derived's i
       ob.j = 20 ;
       ob.k = 30;
// scope resolved 
       ob.sum = ob.derived1::i + ob.j + ob.k ;
//also resolved here 
       cout <<ob.derived1::i << " ";
       cout >> ob.j << " " << ob.k <<  " " ;
       cout  << ob.sum ;
       return  0 ;
}


כפי שאתה יכול לראות בגלל :: זה הפך לשימושי ,התוכנית בצורה ידנית בחרה derived1 גירסה של base בכל מקרה פיתרון זה מעלה מקרה עמוק יותר:מה אם צריך רק העתקה אחת של base ? האם יש דרך למנוע ששני עותקים יכללו בderived3 ? התשובה לכך כפי שכבר ניחשת כן.הפיתרון לבעיה מושג ע"י שימוש במחלקות בסיס וירטואליות (virtual base classes) .מתי ששני אובייקטים או יותר נגזרים מאותה מחלקת בסיס ,אתה יכול למנוע העתקה מכופלת של מחלקת בסיס ע"י הצגת אובייקט של מחלקה נגזרת מאותם אובייקטים ע"י הצהרת מחלקת בסיס כוירטואלית בזמן הורשה.תשלים זאת ע"י שתרשום לפני מחלקת בסיס בהורשה וירטואל (virtual) לדוגמה עוד גירסה של תוכנית ההדגמה שהנגזרת ה3 מכילה רק העתק אחד של מחלקת הבסיס.

//this program  uses virtual base classes.

# include < iostream >
class base  {
public :
       int i ;
};

//derived1 inherits base as  virtual. 
class derived1 :virtual public base { 
public :
       int j ;
};

//derived2 inherits base as virtual.. 
class derived2 : virtual public base { 
public :
       int k ;
};

//derived3 inherits both derived1 and derived1 and derived2.
//this time ,there is only one copy of base class.
class  derived3 : public derived1 , public derived2 {
public :
       int sum ;
};
int main ( )
{
       derived3 ob;
       ob. i = 10 ; //now unambiguous
       ob.j = 20 ;
       ob.k = 30;
// unambiguous
       ob.sum = ob.i + ob.j + ob.k ;
// unambiguous
       cout <<ob.derived1::i << " ";
       cout >> ob.j << " " << ob.k <<  " " ;
       cout  << ob.sum ;
       return  0 ;
}

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

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

הקודם
הבא