Inheritance (הורשה) מאפשרת פיתוח של class חדש בהתבסס על class קיים. למה צריך את זה? code reuse! נראה את התהליך בעזרת דוגמא.
נגדיר תחילה שני מושגים: 
base class: זה ה-class הקיים, ממנו נרצה לרשת (inherit).
derived class: זה ה-class היורש.
ה-derived class יורש את כל מרכיבי ה-base class, ומוסיף להם חברי class חדשים. למעשה הוא יורש את כל מרכיבי ה-base class, חוץ מ-3 ההסתיגויות הבאות:
1. ה-constructor וה-destructor לא עוברים בירושה.
2. friends - (ראה פוסט בנושא) - לא עוברים בירושה.
3. לגבי operator overloading - כל האופרטורים חוץ מ = מועברים בירושה.
1. ה-constructor וה-destructor לא עוברים בירושה.
2. friends - (ראה פוסט בנושא) - לא עוברים בירושה.
3. לגבי operator overloading - כל האופרטורים חוץ מ = מועברים בירושה.
והנה תאור הדוגמא:
נניח שיש לנו class בשם Citizen. ה-class הזה מכיל את בסיסי הנתונים הקשורים לאזרח רגיל: 
ת"ז, 
כתובת מגורים,
תאריך לידה, 
שם האב,
שם האם. 
ה-class מכיל גם מתודות לעדכון כתובת ולהצגה של הנתונים.
כעת ברצוננו לצור class בשם Policeman. ה-class הזה יכיל את הנתונים הבסיסיים של כל אזרח, ובנוסף יכיל:
דרגה, 
מתודה לעידכון הדרגה.
אז ניגש לעבודה ונתחיל בהצגת ה-base class. 
הנה הגדרת ה-class:
- /*
 - * citizen.h
 - *
 - * Created on: Mar 14, 2012
 - * Author: ronen halevy
 - */
 
- #ifndef CITIZEN_H_
 - #define CITIZEN_H_
 
- #include <string>
 - using namespace std;
 - class Citizen{
 - protected:
 - std::string address;
 - string birth_date;
 - int id;
 - string father_name;
 - string mother_name;
 - public:
 - Citizen(string address, string birth_date, int id, string father_name, string Mother_name);
 - void show();
 - void change_address(string new_address);
 - };
 - #endif /* CITIZEN_H_ */
 
נעבור על הנקודות המעניינות בקובץ הנ"ל:
 שורה 11: header file עבור string.
שורה 12: using namespace - עפ"י פקודה זו התוכנה תדע לגשת לספריית std ולמצוא את האובייקט. בלי שורה זו, הסוג string לא ימצא, אלא אם יכתב כ: std:string - כמו בשורה 15.
שורה 14-19: הגדרת חברי ה-class שהם עם access level ברמת protected. מה המשמעות של protected? נסביר: עד עתה נתקלנו ב-access level משני סוגים: public ו-private.
לחבר ב-class מסוג public, ניתן לגשת גם מתוך ה-אובייקט וגם מבחוץ. לחבר class מסוג private ניתן לגשת רק מתוך האובייקט. עד כאן, protected מתנהג כמו private. ההבדל בין protected ל-private קשור בדיוק לעניין ה-inheritance. אל חבר class מסוג private לא ניתן לגשת ישירות מתוך ה-derived class. אל חבר class מסוג protected, ניתן לגשת מתוך ה-derived class. 
בהמשך נראה גישה לחברי ה-class הנ"ל מתוך ה-derived class.
שורה 20: זה ה- constructor/
שורות 21-22: מתודות של ה-class.
נציג את מימוש המתודות של ה-class:
- /*
 - * citizen.cpp
 - *
 - * Created on: Mar 14, 2012
 - * Author: ronen halevy
 - */
 
- #include "citizen.h"
 
- #include <iostream>
 - #include <string>
 - using namespace std;
 
- Citizen::Citizen(string address, string birth_date, int id, string father_name, string mother_name){
 - Citizen::address = address;
 - Citizen::birth_date = birth_date;
 - Citizen::id = id;
 - Citizen::father_name = father_name;
 - Citizen::mother_name = mother_name;
 - cout << "\nCitizen constructor. address: " << address << "birth_date: "<<birth_date<<"id: "<<id<<"father's name: "<< father_name<<"mother's name: "<<mother_name;
 
- }
 
- void Citizen::show(){
 - cout << "\naddress = " << address << "\nbirth_date: "<<birth_date<<"\nid: "<<id<<"\nfather's name: "<< father_name<<"\nmother's name: "<<mother_name;
 
- }
 
- void Citizen::change_address(string new_address){
 - Citizen::address = new_address;
 - }
 
התוכנית הנ"ל כוללת שלוש מתודות - מודגשות בצבעם שונים:
המתודה הראשונה (שורה 14): זהו ה- constructor. הוא מקבל את כל הפרמטר לאתחול רשומת הנתונים של Citizen.
המתודה השניה (שורה 24): show מדפיס לפלט את רשימת הנתונים.
המתושה השלישית (שורה 29): מתודה לעדכון כתובת.
עד כאן תאור ה-base class. מיד נצור ממנו derived class.
הנה ה-policeman: נציג את הגדרת ה-class ואח"כ את מימוש המתודות.
הנה הגדרת ה-class:
- /*
 - * policeman.h
 - *
 - * Created on: Mar 14, 2012
 - * Author: ronen halevy
 - */
 
- #ifndef POLICEMAN_H_
 - #define POLICEMAN_H_
 
- #include "citizen.h"
 
- #include <string>
 - using namespace std;
 - class Policeman : public Citizen{
 - private:
 - string rank;
 - public:
 - Policeman(string rank, string address, string birth_date, int id, string father_name, string mother_name);
 
- };
 - #endif /* POLICEMAN_H_ */
 
כאן נתייחס לשלושת החלקים המודגשים בצבע:
חלק ראשון - שורה 15: זה המקום בו מוגדירים את ה-base class. ההכרזה:
 : public Citizen
קובעת שני דברים:
1. Citizen הוא ה-base class של Policeman.
2. public היא דרגת ה-access level המקסימלית ב-base class.
נקודה 2 הנ"ל דורשת הסבר. קיימות שלוש דרגות אפשרויות של access. הנה הן  בסדר עולה:
א. private.
ב. protected.
ג. public.
בהגדרת ה-base class, מגדירים את דרגת ה-access המקסימלית. נבחן את התוצאה עבור כל אחת מ-3 הדרגות.
1. נניח שההגדרה ב-class הנ"ל היתה: 
 : private Citizen
במקרה הזה כל חברי ה-base class היו הופכים להיות private.
2. נניח שההגדרה של ה-base class היתה:
 : protected Citizen
במקרה זה, חברי ה-base class עם access level ברמת public היו הופכים ל-protected.
3. ובמקרה שלנו, בו ההגדרה היא (ראה שורה 15):
 : public Citizen
ה-access level של חברי ה-base class נשאר ללא שינוי.
חלק שני - שורה 16-17: הגדרה של חברי ה-derived class מסוג protected. כאן הוספנו משתנה דרגה (rank).
החלק השלישי- שורות 18-21: כולל הגדרת ה-constructor של ה-derived class ועוד מתודה שמאפשרת שינוי הדרגה.
נעבור כעת למימוש ה-constructor והמתודה של ה-class.
- /*
 - * policeman.cpp
 - *
 - * Created on: Mar 14, 2012
 - * Author: ronen halevy
 - */
 - #include "policeman.h""
 - #include <iostream>
 - #include <string>
 - using namespace std;
 
- Policeman::Policeman(string rank, string address, string birth_date, int id, string father_name, string mother_name) : Citizen(address, birth_date, id, father_name, mother_name){
 - //Policeman::Policeman(string rank){
 
- Policeman::rank = rank;
 - cout << "\n Policeman constructor rank is: " << rank;
 - }
 
- void change_rank(string rank){
 - Policeman:rank = rank;
 - }
 
החלק המעניין כאן הוא ה-constructor - מודגש בצהוב.
נשאת השאלה: מי מפעיל את ה-constructor של ה-base class, ואיך זה מתבצע?
התשובה: ה-constructor של ה-base class מופעל לפני הפעלת ה-constructor של ה-derived class.
* אם לא מוגדר constructor ב-base class, יופעל ה-default constructor.
* אם מוגדר constructor שלא מקבל פרמטרים - הוא יופעל.
* אם מוגדר constructor שמקבל פרמטרים, אפשר להפעיל אותו, כפי שמודגם בשורה 13 כאן למעלה.
הפרמטרים שמועברים ל-base class constructor צריכים להיות מועברים גם ל derived class constructor.
במקרה שלנו לדוגמא, הconstructor נראה כך:
Citizen(string address, string birth_date, int id, string father_name, string mother_name);
הוא מקבל 5 פרמטרים. לכן הגדרתי את ה-constructor של ה-derived class כך:
:Policeman(string rank, string address, string birth_date,  int id,  string father_name,  string mother_name)
הערה - העברת הפרמטרים ל-constructor של ה-base class נעשית על פי הפורמט של ה-initialization list. ראה פוסט בנושא.
זהו ההסבר על ה-constructors.
זהו ההסבר על ה-constructors.
נציג את main, ונדגים את ההפעלה של מערכת ה-classes הנ"ל.
- /*
 - * my_inheritance.cpp
 - *
 - * Created on: Mar 14, 2012
 - * Author: ronen halevy
 - */
 
- #include "citizen.h"
 - #include "policeman.h""
 
- #include <iostream>
 - using namespace std;
 - int main(){
 - Policeman policeman("sergeant", "levanon st. tel aviv", "22.2.`1922", 77777777, "yosef", "rivka");
 - policeman.change_address("11, habonim st. Jerusalem");
 - policeman.show();
 - }
 
שורה 14: יצירת אובייקט מסוג Policeman והפעלת ה-constructor תוך הכנסת 6 הפרמטרים. כמו שהוסבר קודם, רק אחד מהפרמטרים ("sergant") באמת דרוש לderived class constructor. שאר 5 הפרמטרים דרושים עבור ה-base class constructor.
שורה 15: כאן ניתן לראות שהמתודה change_address השייכת ל-base class, הועברה בירושה ל-derived class.
16: גם המתודה show שייכת במקור ל-Citizen, אבל העברה בירושה ל-Policeman.
הנה הפלט שהודפס על הצג:
- Citizen constructor. address: levanon st. tel avivbirth_date: 22.2.`1922id: 77777777father's name: yosefmother's name: rivka
 - Policeman constructor rank is: sergeant
 - address = 11, habonim st. Jerusalem
 - birth_date: 22.2.`1922
 - id: 77777777
 - father's name: yosef
 - mother's name: rivka
 
שורה 1 הודפסה ע"י ה-base class constructor.
שורה 2 הודפסה ע"י ה-derived class constructor
שורות 3-7 הודפסן על ידי המתודה show.
זהו המבוא ל-inheritance.
קישור לקבצי המקור להורדה.
אין תגובות:
הוסף רשומת תגובה