הפוסט הזה עוסק בהבטים של -inheritance ו-polymorphism. הוא מציע איך להתמודד עם מצב בו ה-derived class יורש את ה-base class, והוא מממש מתודות הקיימות ב-base class.
נרצה למנוע מצב בו המערכת תפנה להפעיל את המתודה ב-class המקורי, בעוד אנו רוצים להפעיל את המתודה החדשה. מצב כזה אכן יתכן, והשימוש ב-virtual method מונע אותו ופותר את הבעיה.
נרצה למנוע מצב בו המערכת תפנה להפעיל את המתודה ב-class המקורי, בעוד אנו רוצים להפעיל את המתודה החדשה. מצב כזה אכן יתכן, והשימוש ב-virtual method מונע אותו ופותר את הבעיה.
כרגיל, נלמד בעזרת דוגמא פשוטה. נציג שני classes, האחד base והשני derived. נדגים קביעה של אחת המתודות כ-virtual. ובפרוט רב יותר:
נציג class שנותן הערכה למחיר תפוזים.
הנוסחאות בהן משתמש ה-class:
price = weight * price_per_kg
כאשר
weight = num_of_items/oranges_in_kg
ההנחה היא כי: 4=oranges_in_kg, כלומר 1קג = 4 תפוזים.
הנוסחאות בהן משתמש ה-class:
price = weight * price_per_kg
כאשר
weight = num_of_items/oranges_in_kg
ההנחה היא כי: 4=oranges_in_kg, כלומר 1קג = 4 תפוזים.
לאחר מכן ניצור class דומה עבור תפוחים תוך שימוש ב-inheritance ו-virtual methods.
הנה ה-class שמחשב מחיר התפוזים. הוא יהיה ה-base class שבקרוב נצור ממנו את ה-Apples class:
- /*
- * oranges.h
- *
- * Created on: Mar 15, 2012
- * Author: ronen halevy
- */
- #ifndef ORANGES_H
- #define ORANGES_H
- class Oranges{
- protected :
- static double const oranges_in_kg = 4;
- double num_of_items;
- double price_per_kg;
- public:
- Oranges(double inum_of_oranges, double iprice_per_kg){num_of_items=inum_of_oranges;price_per_kg=iprice_per_kg;}
- virtual double estimate_weight(){return (num_of_items/oranges_in_kg);}
- double estimated_price(){return(estimate_weight()* price_per_kg);}
- };
- #endif /* ORANGES_H */
נעבור על מספר נקודות ב-class הנ"ל:
ה-class מכיל constructor (שורה 16) ושתי מתודות (שורות 17-18). כולם ממומשים inline.
במימוש inline המתודה ממומשת יחד עם ההגדרה שלה. מתאים למתודות קטנות.
שורה 18 מחשבת את המחיר. הנוסחה לחישוב המחיר היא:
calculated price oranges= 5
calculated price apples= 2.5
הערה: למען הסר ספק, בחלק גדול מהמקרים בהם מתודה נכתבה מחדש ב-dervied class, המתודה החדשה תקרא גם ללא שימוש ב-virtual fuction.
דוגמא: - להוסיף דוגמא----
ה-class מכיל constructor (שורה 16) ושתי מתודות (שורות 17-18). כולם ממומשים inline.
במימוש inline המתודה ממומשת יחד עם ההגדרה שלה. מתאים למתודות קטנות.
שורה 18 מחשבת את המחיר. הנוסחה לחישוב המחיר היא:
estimate_weight()* price_per_kg
המתודה estimate_weight מוגדרת כ-virtual. למה virtual? כי זו המתודה שנממש שוב ב-derived class.
והנה דוגמא ל-main שיוצר אובייקט מסוג Oranges:
- int main(){
- Oranges orange(4,5);
- cout << " calculated price oranges= "<<orange.estimated_price()<<"\n";
- }
שורה 2: יצירת האובייקט, כאשר הפרמטאים עבור ה-constructor הם 4 ו-5 המתייחסים לכמות התפוזים ומחיר לק"ג בהתאמה.
הפלט שהתקבל:
calculated price oranges= 5
כלומר המחיר שחושב עבור 4 תפוזים, כשהמחיר לק"ג הוא 5, ומספר התפוזים בק"ג הוא 4
(static double const oranges_in_kg = 4;)
הוא: 5 ש"ח.
כעת ניצור class המחשב מחיר של תפוחים.
ה-class זהה לזה של Oranges מלבד המתודה לחישוב ה-weight. במקרה של תפוזים החישוב נעשה לפי 4 תפוזים לק"ג. עבור התפוחים החישוב יהיה לפי 8 תפוחים לק"ג. נכתוב לשם כך מחדש את המתודה לחישוב ה-weight.
הנה ה-Apples class:
- #include "oranges.h"
- #include <iostream>
- #include <string>
- using namespace std;
- class Apples: public Oranges{
- static double const apples_in_kg = 8;
- public:
- Apples(double inum_of_items, double iprice_per_kg):Oranges(inum_of_items, iprice_per_kg){};
- double estimate_weight(){return(num_of_items/apples_in_kg);}
- };
שורה 5: ה-class יורש את Oranges.
שורה 9: הגדרת הקבוע שמשמש לחישוב המשקל, (או יותר נכון הערכת המשקל): כל 8 תפוחים שוקלים ק"ג.
שורה 11: ה-constructor, שדואג להעביר את הפרמטרים גם ל- Oranges constructor.
שורה 12: כאן estimate_weight נכתבה מחדש. היות שהיא הוגדרה ב-base class כ-virtual, מובטח לנו שהיא תרוץ מכן - מה-derived class, ולא מה-base.
והנה הmain:
- int main(){
- Oranges orange(4,5);
- cout << " calculated price oranges= "<<orange.estimated_price()<<"\n";
- Apples apple(4,5);
- cout << " calculated price apples= "<<apple.estimated_price()<<"\n";
- }
בשורה 2 יוצרים אובייקט מסוג Orange כשערכי ההתחלה הם 4 תפוזים במחיר של 5 שח ל ק"ג.
בשורה 3 מחשבים את המחיר ומציגים אותו.
בשורה 4 ו-5 חוזרים על אותו תהליך עם אובייקט מסוג Apples. שוב: 4 תפוחים במחיר של 5 ש"ח לק"ג.
איך יראה הפלט?
הנה:
calculated price apples= 2.5
יש שם 8 תפוזים, והנחנו שבק"ג יש 4 תפוזים. מכאן, משקל התפוזים 1 ק"ג והמחיר 5 שח.
יש שם 4 תפוחים, והנחנו שבק"ג יש 8 תפוחים. מכאן, משקל התפוחים0.5 ק"ג והמחיר 2.5 שח.
מה היה הפלט אם estimate_weight לא היה מוגדר כ virtual function ? במקרה זה, היה נעשה שימוש ב:
Oranges:estimate_weight גם עבור התפוחים והתוצאה היתה:
calculated price oranges= 5
calculated price apples= 5
הערה: למען הסר ספק, בחלק גדול מהמקרים בהם מתודה נכתבה מחדש ב-dervied class, המתודה החדשה תקרא גם ללא שימוש ב-virtual fuction.
דוגמא: - להוסיף דוגמא----
קישור להורדת קבצי המקור.
זה היה מועיל מאוד, תודה רבה!
השבמחקתודה! שמח לשמוע.
השבמחקתודה רבה על הפרסום, עזר לי בהבנת Virtual Function.
השבמחק