CATEGORII DOCUMENTE |
Din cauza mostenirii multiple se
poate intampla ca o clasa de baza sa fie prezenta in mai multe exemplare intr-o
clasa derivata. Sa consideram urmatorul exemplu:
Figura 1. Date membru mostenite in doua exemplare
In acest caz datele membru ale clasei animal vor fi mostenite in doua exemplare de catre clasa caine. Primul exemplar se mosteneste prin clasa domestic iar cel de al doilea prin clasa mamifer. Aceste date membru pot fi accesate folosind operatorul de rezolutie precedata de numele clasei prin care se face mostenirea. Fisierul animal1.cpp
#include <iostream.h>
#include <string.h>
#include <conio.h>
class animal ;
class mamifer : public animal ;
class domestic : public animal ;
class caine : public mamifer, public domestic ;
animal::animal(char* n)
mamifer::mamifer(char* n, int g): animal(n)
domestic::domestic(char* n, int c): animal(n)
caine::caine(char* n, int g, int c, int l): mamifer(n, g), domestic(n, c)
void caine::scrie_date()
int main()
Observam ca data membru nume s-a mostenit in doua exemplare de catre clasa caine, si referirea la aceste date s-a facut prin mamifer::nume respectiv domestic::nume. Prin executie se va afisa data membru nume de doua ori, mostenit prin cele doua clase. Deasemenea se va afisa greutatea si comportamentul cainelui, si faptul ca latra sau nu.
Ar fi de dorit insa ca numele sa fie memorat numai intr-un singur exemplar in obiectele clasei caine. Acest lucru se poate realiza cu ajutorul claselor virtuale.
Daca nu se doreste ca datele membru a unei clase de baza sa fie prezente in mai multe exemplare intr-o clasa derivata, atunci se folosesc clase virtuale. Clasele de baza devin virtuale prin mostenire, daca se specifica acest lucru prin plasarea cuvantului cheie virtual in fata numelui clasei, in lista claselor de baza. Astfel clasa de baza respectiva va deveni virtuala referitor la clasa derivata.
Exemplul de mai sus se modifica in modul urmator. Fisierul animal2.cpp
#include <iostream.h>
#include <string.h>
#include <conio.h>
class animal ;
class mamifer : virtual public animal ;
class domestic : virtual public animal ;
class caine : public mamifer, public domestic ;
animal::animal(char* n)
mamifer::mamifer(char* n, int g): animal(n)
domestic::domestic(char* n, int c): animal(n)
caine::caine(char* n, int g, int c, int l):
animal(n), //trebuie apelat constructorul clasei animal
mamifer(n, g),//in mod explicit, deoarece ea fiind virtuala
domestic(n, c)//constructorul nu se va apela prin unul din
//clasele mamifer sau domestic
void caine::scrie_date()
int main()
Intr-o ierarhie complicata de clase
unele clase de baza pot fi mostenite in mai multe exemplare intr-o clasa derivata.
Intre aceste exemplare pot fi virtuale si nevirtuale. Sa consideram urmatorul
exemplu referitor la acest lucru :
Figura 2. Ierarhie de clase
In aceasta ierarhie de obiecte clasa de baza A se mosteneste in mod virtual de catre clasele B si C si in mod nevirtual de catre clasa D. Clasele de baza ale clasei G sunt B, C, D, E si F, toate mostenirile fiind nevirtuale cu exceptia clasei F. Se pot pune atunci urmatoarele probleme. In ce ordine vor fi executate constructorii in cazul in care se creaza un obiect al clasei G? Daca o clasa de baza este mostenita in mai multe exemplare intr-o clasa derivata printre care pot fi atat virtuale cat si nevirtuale, atunci de cate ori se va apela constructorul clasei de baza? Pentru a da raspuns la aceste intrebari sa consideram urmatorul program. Fisierul virtual2.cpp
#include <iostream.h>
#include <string.h>
#include <conio.h>
class A
};
class B: virtual public A
};
class C: virtual public A
};
class D: public A
};
class E
};
class F
};
class G: public B, public C, public D, public E, virtual public F
};
int main()
Prin executie se obtine urmatorul rezultat:
Se apeleaza constructorul clasei A cu parametrul obiect
Se apeleaza constructorul clasei F cu parametrul obiect
Se apeleaza constructorul clasei B cu parametrul obiect
Se apeleaza constructorul clasei C cu parametrul obiect
Se apeleaza constructorul clasei A cu parametrul obiect
Se apeleaza constructorul clasei D cu parametrul obiect
Se apeleaza constructorul clasei E cu parametrul obiect
Se apeleaza constructorul clasei G cu parametrul obiect
Acest rezultat se datoreaza urmatoarelor reguli.
In cazul in care se creaza un obiect al clasei derivate, mai intai vor fi executate constructorii claselor de baza virtuale in ordinea din lista_claselor_de_baza (vezi declaratia claselor derivate), apoi constructorii claselor de baza nevirtuale in ordinea din lista_claselor_de_baza
Daca intr-o ierarhie de clase, o clasa de baza se mosteneste in mai multe exemplare intr-o clasa derivata, atunci la crearea unui obiect al clasei derivate se va executa constructorul clasei de baza o data pentru toate exemplarele virtuale, si inca de atatea ori cate exemplare nevirtuale exista.
Deci in cazul exemplului de mai sus, mai intai se execut constructorii claselor A si F (ele fiind virtuale), apoi constructorii claselor B, C, D si E (clase nevirtuale). Constructorul clasei D apeleaza mai intai constructorul clasei A (ea fiind nevirtuala de aceasta data). De aceea ordinea de apelare a constructorilor va fi: A, F, B, C, A, D, E si G.
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 902
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved