Motenirea claselor Programarea calculatoarelor i limbaje de programare
Moştenirea claselor Programarea calculatoarelor şi limbaje de programare II Capitolul 5
Obiective n Înţelegerea modului în care se pot crea clase noi prin moştenirea din clasele existente n Înţelegerea modului în care moştenirea promovează reutilizarea codului n Înţelegerea noţiunilor de clasă de bază şi clasă derivată
Introducere n Moştenirea este o formă de reutilizare a codului în care noile clase sunt create din clase existente prin n absorbirea atributelor şi comportamentelor n prin înlocuirea unor comportamente n prin adăgarea unor atribute şi comportamente noi n Reutilizarea codului economiseşte timp preţios în dezvoltarea software
Introducere n O clasă moşteneşte datele membre şi funcţiile membre dintr-o clasă de bază definită anterior n Noua clasă este o clasă derivată n Moştenirea se foloseşte la crearea unei noi clase asemănătoare uneia existente pentru a nu rescrie complet datele membre şi funcţiile membre n Fiecare clasă derivată poate deveni, mai departe, un candidat pentru derivări ulterioare
Introducere n Moştenirea simplă n o clasă este derivată dintr-o singură clasă de bază n Moştenirea multiplă n o clasă este derivată din mai multe clase de bază n Limbajul C++ oferă trei tipuri de moşteniri n public n fiecare obiect al unei clase derivate poate fi folosit oriunde se foloseşte un obiect al clasei de bază din care a fost derivată acea clasă n un obiect din clasa derivată este şi obiect al clasei de bază n protected n private
Introducere n O relaţie „has a” înseamnă compunere de clase n un obiect al unei clase are ca membri unul sau mai multe obiecte altor clase n O relaţie „is a” este o moştenire n obiectele unei clase derivate pot fi tratate şi ca obiecte ale clasei de bază
Sumar n Moştenirea: clase de bază şi clase derivate n Membrii protected n Cast între pointerii la clasa de bază şi pointerii la clasa derivată n Folosirea funcţiilor membre n Suprascrierea membrilor clasei de bază în clasele derivate n Moştenirea public, protected şi private n Clase de bază directe şi clase de bază indirecte
Moştenirea: clase de bază şi clase derivate n Adeseori, un obiect al unei clase este un obiect al altei clase în acelaşi timp Un dreptunghi este un patrulater, la fel ca şi un pătrat, un paralelogram sau un trapez n Clasa Dreptunghi moşteneşte clasa Patrulater n n Clasa Patrulater - clasă de bază n Clasa Dreptunghi - clasă derivată
Moştenirea: clase de bază şi clase derivate n Exemple Clasa de bază Forma Clase derivate Cerc Triunghi Dreptunghi Credit. Auto Credit. Imobiliar Cont. Curent Cont. Depozit Cont. Plati
Moştenirea: clase de bază şi clase derivate n Exemplu n Moştenirea conduce la relaţii între clase care poti fi reprezentate prin structuri arborescente n Un obiect al clasei Cerc este în acelaşi timp şi o Forma. Bidimensionala, dar şi o Forma. Bidimensionala Cerc Triunghi Forma. Tridimensionala Patrat Sfera class Forma. Bidimensionala : public Forma {. . . }; Cub
Sumar n Moştenirea: clase de bază şi clase derivate n Membrii protected n Cast între pointerii la clasa de bază şi pointerii la clasa derivată n Folosirea funcţiilor membre n Suprascrierea membrilor clasei de bază în clasele derivate n Moştenirea public, protected şi private n Clase de bază directe şi clase de bază indirecte
Membrii protected n Membrii public ai unei clase de bază pot fi accesaţi de orice funcţie din program n Membrii private al unei clase de bază sunt accesibili doar funcţiilor membre sau prietenilor clasei n Membrii protected ai unei clase de bază pot fi accesaţi doar de membrii şi de prietenii clasei de bază n de membrii şi prietenii claselor derivate n
Membrii protected n Datele protected depăşesc ideea de încapsulare pentru că o schimbare a membrilor protected din clasa de bază poate influenţa toate clasele derivate se recomandă ca datele membre să fie declarate private n protected trebuie folosit numai atunci când este strict necesar n
Sumar n Moştenirea: clase de bază şi clase derivate n Membrii protected n Cast între pointerii la clasa de bază şi pointerii la clasa derivată n Folosirea funcţiilor membre n Suprascrierea membrilor clasei de bază în clasele derivate n Moştenirea public, protected şi private n Clase de bază directe şi clase de bază indirecte
Cast între pointerii la clasa de bază şi pointerii la clasa derivată n Un obiect al unei clase derivate public poate fi tratat ca obiect al clasei ei de bază n Downcasting a pointer programatorul trebuie să folosească un cast explicit pentru a converti un pointer la clasa de bază într-un pointer la o clasă derivata n compilatorul consideră că această operaţie este una nesigură n n Upcasting a pointer n Operaţia inversă, prin care un pointer al clasei derivate este convertit la un pointer al clasei de bază
Cast între pointerii la clasa de bază şi pointerii la clasa derivată n Exemplu n Point – clasă de bază n Circle – clasă derivată class Point { friend ostream& operator<<(ostream&, const Point&); public: Point(int = 0, int = 0); void set. Point(int, int); int get. X() const { return x; } int get. Y() const { return y; } protected: int x, y; };
Cast între pointerii la clasa de bază şi pointerii la clasa derivată class Circle : public Point { friend ostream& operator<<(ostream&, const Circle&); public: Circle(double r = 0. 0, int x = 0, int y = 0); void set. Radius(double); double get. Radius() const; double area() const; protected: double radius; };
Cast între pointerii la clasa de bază şi pointerii la clasa derivată int main() { Point *point. Ptr = 0, p(30, 50); Circle *circle. Ptr = 0, c(2. 7, 120, 89); cout << "Punctul p: " << p << "n. Cercul c: " << c << 'n'; . . . } Punctul p: [30, 50] Cercul c: Centrul = [120, 89]; Raza = 2. 70
Cast între pointerii la clasa de bază şi pointerii la clasa derivată int main() {. . . //Trateaza Circle ca un Point //Este vizibila doar partea care provine //din clasa de baza Upcasting point. Ptr = &c; //asigneaza adresa //unui Circle lui point. Ptr cout << "n. Cercul c (via *point. Ptr): " << *point. Ptr << 'n'; . . . } Cercul c (via *point. Ptr): [120, 89]
Cast între pointerii la clasa de bază şi pointerii la clasa derivată int main() {. . . //Trateaza un Circle ca un Circle //cast de la pointer la clasa de baza la pointer //la clasa derivata Downcasting circle. Ptr = static_cast<Circle*>(point. Ptr); cout << "n. Cercul c (via *circle. Ptr): n" << *circle. Ptr << "n. Aria lui c (via circle. Ptr): " << circle. Ptr->area() << 'n'; . . . } Cercul c (via *circle. Ptr): Centrul = [120, 89]; Raza = 2. 70 Aria lui c (via circle. Ptr): 22. 90
Cast între pointerii la clasa de bază şi pointerii la clasa derivată int main() {. . . //PERICULOS: Trateaza Point ca un Circle point. Ptr = &p; //asigneaza adresa unui Point la point. Ptr Downcasting //cast al clasei de baza la clasa derivata circle. Ptr = static_cast<Circle*>(point. Ptr); cout << "n. Punctul p (via *circle. Ptr): n" << *circle. Ptr << "n. Aria obiectului la care pointeaza circle. Ptr: " << circle. Ptr->area() << endl; . . . } Sunt afişate valori nedefinite Punctul p (via *circle. Ptr): Centrul = [30, 50]; Raza = 0. 00 Aria obiectului la care pointeaza circle. Ptr: 0. 00
Sumar n Moştenirea: clase de bază şi clase derivate n Membrii protected n Cast între pointerii la clasa de bază şi pointerii la clasa derivată n Folosirea funcţiilor membre n Suprascrierea membrilor clasei de bază în clasele derivate n Moştenirea public, protected şi private n Clase de bază directe şi clase de bază indirecte
Folosirea funcţiilor membre n O clasă derivată nu poate accesa direct membri private ai clasei de bază n Acesta este un aspect crucial de inginerie software in C++ n Dacă o clasă derivată ar putea accesa membrii private ai clasei de bază, s-ar încălca principiul încapsulării pentru obiectele clasei de bază n Dacă o clasă derivată ar putea accesa membrii private ai clasei sale de bază, atunci clasele care sunt derivate mai departe din clasele derivate pot accesa şi ele aceşti membri şi aşa mai departe n Propagarea accesului la datele private ar anula astfel beneficiile încapsulării datelor în cadrul unei ierarhii de derivare
Sumar n Moştenirea: clase de bază şi clase derivate n Membrii protected n Cast între pointerii la clasa de bază şi pointerii la clasa derivată n Folosirea funcţiilor membre n Suprascrierea membrilor clasei de bază în clasele derivate n Moştenirea public, protected şi private n Clase de bază directe şi clase de bază indirecte
Suprascrierea membrilor clasei de bază în clasele derivate n Override n O clasă derivată poate suprascrie o funcţie membră a clasei de bază printr-o nouă versiune a acestei funcţii cu aceeaşi semnătură n Când numele acestei funcţii este menţionat în clasa derivată, este selectată automat versiunea din clasa derivată n Overload n Semnăturile sunt diferite
Suprascrierea membrilor clasei de bază în clasele derivate n Exemplu class Employee { public: Employee(const char*, const char*); void print() const; ~Employee(); private: char* first. Name; char* last. Name; };
Suprascrierea membrilor clasei de bază în clasele derivate class Hourly. Worker : public Employee { public: Hourly. Worker(const char*, double, double); double get. Pay() const; void print() const; private: Funcţia print double wage; este suprascrisă double hours; };
Suprascrierea membrilor clasei de bază în clasele derivate Apelul functiei print din clasa de baza void Hourly. Worker: : print() const { cout << "Se executa Hourly. Worker: : print()nn"; Employee: : print(); cout << " este un lucrator angajat cu ora platit cu " << setiosflags(ios: : fixed | ios: : showpoint) << setprecision(2) << get. Pay() << " EUR" << endl; } int main() { Hourly. Worker h("Bob", "Smith", 40. 0, 10. 00); h. print(); Se executa Hourly. Worker: : print() return 0; } Bob Smith este un lucrator angajat cu ora platit cu 400. 00 EUR
Sumar n Moştenirea: clase de bază şi clase derivate n Membrii protected n Cast între pointerii la clasa de bază şi pointerii la clasa derivată n Folosirea funcţiilor membre n Suprascrierea membrilor clasei de bază în clasele derivate n Moştenirea public, protected şi private n Clase de bază directe şi clase de bază indirecte
Moştenirea public, protected şi private n Pentru membrii public din clasa de bază n Moştenire public n public în clasa derivată n Poate fi accesat direct prin orice funcţie membră nestatică, funcţie friend sau funcţie nemembră n Moştenire protected n protected în clasa derivată n Poate fi accesat direct prin orice funcţie membră nestatică sau funcţie friend n Moştenire private n private în clasa derivată n Poate fi accesat direct prin orice funcţie membră nestatică sau funcţie friend
Moştenirea public, protected şi private n Pentru membrii protected din clasa de bază n Moştenire public n protected în clasa derivată n Poate fi accesat direct prin orice funcţie membră nestatică sau funcţie friend n Moştenire protected n protected în clasa derivată n Poate fi accesat direct prin orice funcţie membră nestatică sau funcţie friend n Moştenire private n private în clasa derivată n Poate fi accesat direct prin orice funcţie membră nestatică sau funcţie friend
Moştenirea public, protected şi private n Pentru membrii private din clasa de bază n Moştenire public n Inaccesibil în clasa derivată. n Poate fi accesat direct prin orice funcţie membră nestatică sau funcţie friend prin funcţii membre public sau protected din clasa de bază n Moştenire protected n Inaccesibil în clasa derivată. n Poate fi accesat direct prin orice funcţie membră nestatică sau funcţie friend prin funcţii membre public sau protected din clasa de bază n Moştenire private n Inaccesibil în clasa derivată. n Poate fi accesat direct prin orice funcţie membră nestatică sau funcţie friend prin funcţii membre public sau protected din clasa de bază
Sumar n Moştenirea: clase de bază şi clase derivate n Membrii protected n Cast între pointerii la clasa de bază şi pointerii la clasa derivată n Folosirea funcţiilor membre n Suprascrierea membrilor clasei de bază în clasele derivate n Moştenirea public, protected şi private n Clase de bază directe şi clase de bază indirecte
Clase de bază directe şi clase de bază indirecte n Clasă de bază directă a unei clase derivate n este listată explicit în header-ul clasei derivate, după semnul : n Clasă de bază indirectă n nu este listată explicit în header-ul clasei n este moştenită cu două sau mai multe nivele înainte în ierarhia de moştenire
- Slides: 34