דף הבית >> פונקציות וירטואליות ופולימורפיזם>>פונקציות וירטואליות>>קריאה לפונקציות וירטואליות דרך מחלקת בסיס>>>>פונקציות וירטואליות הם הירארכיות >>פונקציות וירטואליות טהורות

 

פונקציות וירטואליות טהורות

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

 

Virtual type func-name (parameter-list) = 0;

מתי שפונקציה וירטואלית הופכת ,כל מחלקה נגזרת חייבת לספק הגדרה משלה.אם המחלקה הנגזרת נכשלת באכיפת סמכות הפונקציה הוירטואלית הטהורה ,זה יגרום בזמן הקומפלציה לטעות.התוכנית הבאה מכילה דוגמה לפונקציה וירטואלית טהורה .מחלקת הבסיס,number, מכיל אינטגר בשם val הפונקציה ( ) setval ופונקציה וירטואלית טהורה בשם ( )show .המחלקות הנגזרות hextype, dectype ו octtype מורישות מספר ומגדירות מחדש את ( ) showכל שזה פולט את הערך של val בכל מספר בסיס המתאים לו (הקסדצימלי , דצימלי ,אוקטל)

 

#include <iostream.h>

class number {
protected:
       int val ;
public:
       void setval ( int i)   {val = i ;}
//show ( ) is a pure virtual  function 
       virtual void show ( ) = 0 ;
};
class hextype : public number {
public:
       void show ( ) {
           cout << hex <<val << " \n ";
       }
};
class dectype : public number {
public:
       void show ( ) {
           cout << val << " \n ";
       }
};
class octtype : public number {
public:
       void show ( ) {
           cout << oct <<val << " \n ";
       }
};
int main ( )
{
       dectype d;
       hextype h;
       octtype o;
       d.setval (20 );
       d.show ( ) ;//displays 20 - decimal
       h.setval (20 );
       h.show ( );//displays 14 -hexdecimal
       o.setval (20 );
       o.show ( ) ;//displays 20 - octal
       return 0 ;
}


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

 

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

 

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

 

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

שימוש של פונקציות וירטואליות

אחד מהאספקטים של תיכנות מונחה עצמים זה העיקרון של " ממשק אחד, מספר שיטות " זה אומר שמחלקה כללית של פעולות מוגדרת ,זה אחד מהדרכים החזקות והגמישות ליישם "ממשק אחד ,מספר שיטות" גישה לשימוש פונקציה וירטואלית,מחלקות אבסטרקטיות ,ופולימורפיזם בזמן ריצה. להשתמש במאפיינים אלו אתה יוצר מחלקה היררכית אשר נעה מכללי לספציפי(בסיס לנגזרת). לנהוג לפי פילוסופיה זו,אתה מגדיר את כל המאפינים המשותפים וממשקים במחלקת בסיס.במקרים שיש פעולות פעולות מסויימות אשר אפשר ליישם ע"י מחלקה נגזרת ,בשימוש פונקציה וירטואלית . בתמצית במחלקת בסיס אתה יוצר ומגדיר הכל אתה יכול לקרב את זה למקרה הכללי .מחלקה נגזרת תתמלא בפרטים ספציפים.דוגמה פשוטה תדגים את הערך של פילוסופיית "ממשק אחד, מספר שיטות". מחלקה היררכית נוצרתאשר מבצעת המרות ממערכת אחת של יחידות לאחרת.(לדוגמה להפוך ליטרים לגלון). מחלקת הבסיס convert מצהירה על שני משתנים val1 ו val2 ,ומחזיקה את האות הראשונה וממירה ערכים,בהתאמה.היא גם מגדירה פונקציות ( ) getinitו ( ) getconv ,אשר מחזירה את האות הראשונה ואת הערך המומר.האלמנטים של convert הם קבועים ונגישים לכל המחלקות הנגזרות שיורשות מ convert ,בכל אופן הפונקציה אשר בעצם תבצע את ההמרה היא,( )compute , היא פונקציה וירטואלית טהורה אשר חייבת להיות מוגדרת ע"י המחלקות הגזרות מ convert הטבע הספציפי של compute יקבע ע"י איזה סוג של המרה יקח מקום .

 


//virtual function practical example 
#include <iostream.h>
class convert { protected: double val1; //initial value double val2;//converted value public: convert (double i) { vall = i ; } double getconv ( ) {return val2;} double getinit ( ) {return val1;} virtual void compute ( ) = 0; }; //liters to gallons class l_to_g : public convert { public: l_to_g(double i ) :convert (i){} void comput ( ) { val2 = val1 /3.7854; } }; fahrenheit to celsius // class f_to_c :public convert { public: f_to_c (double i) :convert (i) { } void copute ( ) { val2 = (val1-32) /1.8; } }; i int main ( ) { convert *p; //pointer to base class l_to_g lgob (4); f_to_c fcob (70); //use virtual function mechanism to convert p= &lgob; cout << p->getinit ( ) << "liters is "; p->compute ( ); cout << p-> getconv ( ) << " gallons \n ";// l_to_g p = &fcob; cout < getinit ( ) << "in fahrenheit is" ; p-> compute ( ); cout << p-> getconv ( ) << "celsius\n";// f_to_c return 0 ; }

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

 

 //feet to meters
   class f_to_m : public convert{ 
   public:
   f_to_m (double io ) : convert (i ){ }
   void compute( ){ 
   val2 = vall /3.28;
 }
};


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

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

 

הקודם
הבא