Polygon base class width height setvalues Rectangle rect
ירושה Polygon • מנגנון הירושה מאפשר גישה אחידה לאובייקטים מטיפוסים שונים שלהם base class באמצעות מצביע ל width height set_values Rectangle rect; Triangle trgl; Rectangle Triangle Polygon * ppoly 1 = ▭ Polygon * ppoly 2 = &trgl; ppoly 1 ppoly 2 rect trgl
base class גישה לאובייקט באמצעות מצביע ל Polygon width height set_values Rectangle class Polygon { protected: int width, height; public: void set_values (int a, int b) { width=a; height=b; } }; Rectangle rect; Triangle trgl; Triangle Polygon * ppoly 1 = ▭ Polygon * ppoly 2 = &trgl; ppoly 1 ->set_values(4, 5); ppoly 2 ->set_values(4, 5); ppoly 1 ppoly 2 rect trgl
Polygon width height set_values חישוב השטח בפוליגונים שונים • משולש ומרובע נגזרים מפוליגון (height, width) • שניהם יורשים את נתוני הרוחב והגובה (area) • אך לכל אחד מימוש שונה לחישוב השטח Rectangle Triangle area class Rectangle: public Polygon { public: int area() { return width*height; } }; class Rectangle: public Polygon { public: int area() { return width*height/2; } };
base class - ב area() מימוש ( במחלקה היורשת override) ודריסה class Polygon { … int area () { return 0; } } class Rectangle : public Polygon { … int area() { return (width * height); } } class Triangle : public Polygon { … int area() { return (width * height / 2); } } Polygon poly; Rectangle rect; Triangle trgl; Polygon * ppoly 1 = &poly; Polygon * ppoly 2 = ▭ Polygon * ppoly 3 = &trgl; ppoly 1 ->set_values (4, 5); ppoly 2 ->set_values (4, 5); ppoly 3 ->set_values (4, 5); cout << ppoly 1 ->area() << 'n'; cout << ppoly 2 ->area() << 'n'; cout << ppoly 3 ->area() << 'n'; : פלט 0 0 0
Virtual function Polygon poly; Rectangle rect; Triangle trgl; Polygon * ppoly 1 = &poly; Polygon * ppoly 2 = ▭ Polygon * ppoly 3 = &trgl; ppoly 1 ->set_values (4, 5); ppoly 2 ->set_values (4, 5); ppoly 3 ->set_values (4, 5); class Polygon { … virtual int area () { return 0; } } class Rectangle : public Polygon { … int area() { return (width * height); } } פונקציה וירטואלית cout << ppoly 1 ->area() << 'n'; cout << ppoly 2 ->area() << 'n'; cout << ppoly 3 ->area() << 'n‘; class Triangle : public Polygon { … int area() { return (width * height / 2); } } : פלט 0 20 | 4*5 10 | 4*5/2
Abstract base class מחלקת אם מופשטת • מחלקה שיכולה לשמש כבסיס להורשה בלבד • לא ניתן ליצור ממנה אובייקטים ממשיים • קיימת בה לפחות פונקציה וירטואלית טהורה אחת abstract class Polygon width height set_values virtual area()=0; class Polygon { protected: int width, height; public: void set_values (int a, int b) { width=a; height=b; } }; virtual int area () =0; Pure virtual function
Abstract base class מחלקת אם מופשטת Polygon poly; Rectangle rect; Triangle trgl; Polygon * ppoly 1 = ▭ Polygon * ppoly 2 = &trgl; ppoly 1 ->set_values (4, 5); ppoly 2 ->set_values (4, 5); cout << ppoly 1 ->area() << 'n'; cout << ppoly 2 ->area() << 'n'; compilation ERROR • לא ניתן ליצור מחלקה מופשטת משמשים כדי לפנות Abstract base class • מצביעים ל לאובייקטים הממשיים האם - המוגדרת במחלקת area • שניהם קוראים ל אך הממומשת בצורה שונה : פלט 20 | 4*5 10 | 4*5/2
Interface - ממשק • הגדרה של פעולות ללא התייחסות למימושן Abstract base class • מקובל לממש ממשק באמצעות • ניתן לשלב אובייקטים שונים בעלי אותו ממשק באותו מבנה נתונים ולהתייחס אליהם באופן אחיד Polygon name color area rotate flip expand class Polygon_IF { pubic: virtual string name()=0; virtual string color()=0; virtual double area()=0; virtual void rotate(double degree)=0; virtual void flip(bool horizontal)=0; virtual void expand(double)=0; }
מחיקה של מחלקות פולימורפיות class Base{ public: Base(){ cout << "Constructing Base"; } ~Base(){ cout << "Destroying Base"; } }; class Derive : public Base{ public: Derive(){ cout << "Constructing Derive"; } ~Derive(){ cout << "Destroying Derive"; } }; void main(){ Base *base. Ptr = new Derive(); delete base. Ptr; } : הפלט Constructing Base Constructing Derive ? האומנם Destroying Derive Destroying Base
מחיקה של מחלקות פולימורפיות class Base{ public: Base(){ cout << "Constructing Base"; } ~Base(){ cout << "Destroying Base"; } }; class Derive : public Base{ public: Derive(){ cout << "Constructing Derive"; } ~Derive(){ cout << "Destroying Derive"; } }; void main(){ Base *base. Ptr = new Derive(); delete base. Ptr; } : הפלט שמתקבל Constructing Base Constructing Derive Destroying Base ! לא השתחרר Derive • הזיכרון של Memory leak • נוצר
Virtual destructor : הפתרון לבעיה class Base{ public: Base(){ cout << "Constructing Base"; } virtual ~Base(){ cout << "Destroying Base"; } }; class Derive : public Base{ public: Derive(){ cout << "Constructing Derive"; } ~Derive(){ cout << "Destroying Derive"; } }; void main(){ Base *base. Ptr = new Derive(); delete base. Ptr; } : הפלט Constructing Base Constructing Derive Destroying Base השתחרר Derive • הזיכרון של מוגדר כ base class - ב Destructor • אם ה בעת מחיקת האובייקט הממשי תקרא virtual Destructors כל שרשרת ה
pure virtual methods ללא abstract base class Base {. Base • מצד אחד נרצה לממש את כל המתודות ב public: . abstract יהיה Base • מצד שני נרצה ש Base(); virtual ~Base(); // all Base methods, none is pure virtual… … }; void main() { Not a compilation ERROR Base *base. Ptr = new Base(); delete base. Ptr; }
Pure virtual destructor : הפתרון לבעיה class Base { base class - ב Destructor • הכרזה על public: הופכת את המחלקה pure virtual כ Base(); ! למופשטת virtual ~Base() = 0 {} // must provide a body // all Base methods, none is pure virtual… … }; , עדיין ייקרא Base של destructor • ה . לכן חייבים לממש אותו void main() תגרום Base • יצירת אובייקט מטיפוס { לשגיאת קומפילציה Base *base. Ptr = new Base(); compilation ERROR delete base. Ptr; }
- Slides: 27