Pagina de start a forumului Informatica
 FAQ  •  Cautare  •  Membri  •  Grupuri   •  Inregistrare  •  Profil  •  Mesaje private  •  Autentificare
Subiectul urmator
Subiectul anterior
Creaza un subiect nou   Raspunde la subiect  Pagina de start a forumului Informatica » C++
Autor Mesaj
Admin
Administrator
Administrator


Data inscrierii: 07/Dec/2013
Mesaje: 1103

MesajTrimis: 14/12/2013 19:29 Raspunde cu citat (quote) Back to top

• Legatura intre clasa derivata si clasele ei de baza comporta unele aspecte esentiale cu privire la:
a. relatiile intre constructorii, respectiv destructorii clasei derivate si ai claselor de baza;
b. conversiile obiectelor claselor derivate spre cele ale claselor de baza, respectiv a pointerilor spre aceste obiecte;
c. redeclararea datelor membre si supraincarcarea functiilor membre ale claselor de baza in clasa derivata.

• Constructorii si destructorii sunt functii membre care nu se pot mosteni, dar se pot apela de catre clasa derivata in anumite conditii de protectie. Un constructor al clasei derivate apeleaza, intotdeauna, mai intii un constructor corespunzator al clasei de baza pentru a avea certitudinea ca datele membre mostenite au fost corect confecționate si initializate.

• Apelul constructorilor claselor de baza, de catre constructorii clasei derivate, se poate realiza:
a) implicit (atunci cind este posibil);
b) explicit (prin specificarea parametrilor necesari).

• Ordinea in care se executa apelul constructorilor din clasele de baza este impusa de ordinea data prin lista claselor de baza mostenite, prezenta in definitia clasei derivate.

• Reamintim faptul, ca functia constructor se apeleaza automat la crearea fiecarui obiect al clasei (static, automatic, dinamic (cu operatorul new)), inclusiv pentru obiectele temporare. Destructorul este o functie care se apeleaza automat pentru a elimina un obiect dintr-o clasa la finele duratei sale de existenta, sau, in cazul variabilelor dinamice, el este solicitat prin program cu operatorul delete, inclusiv pentru obiecte temporare. Constructorul se apeleaza dupa alocarea memoriei necesare pentru datele membre ale obiectului in faza finala a crearii lui. Destructorul este apelat inaintea eliberarii zonei de memorie alocate datelor membre ale obiectului, in faza initiala a eliminarii obiectului.

• Ordinea de executie a functiilor constructor, respectiv destructor in procesul de mostenire reiese si din urmatorul exemplu:
#include <iostream>
#include <conio>
class B1
{
public:
B1( ){cout<<"(1)Se apeleaza constructorul pentru clasa B1\n";}
~B1( ){cout<<"(2)Se apeleaza destructorul pentru clasa B1\n";}
};
class B2
{
public:
B2( ){cout<<"(3)Se apeleaza constructorul pentru clasa B2\n";}
~B2( ){cout<<"(4)Se apeleaza destructorul pentru clasa B2\n";}
};

class B3
{
public:
B3( ){cout<<"(5)Se apeleaza constructorul pentru clasa B3\n";}
~B3( ){cout<<"(6)Se apeleaza destructorul pentru clasa B3\n";}
};
class D1:public B1,public B2
{
public:
D1( ){cout<<"(7)Se apeleaza constructorul pentru clasa D1\n";}
~D1( ){cout<<"(8)Se apeleaza destructorul pentru clasa D1\n";}
};
class D2:public D1,public B3
{
public:
D2( ){cout<<"(9)Se apeleaza constructorul pentru clasa D2\n";}
~D2( ){cout<<"(10)Se apeleaza destructorul pentru clasa D2\n";}
};
void main( )
{
D1 ob1;
D2 ob2;
}
Sa se urmareasca si sa se explice ordinea in care se tiparesc mesajele: (1),(3),(7),(1),(3),(7), (5),(9),(10),(6),(8),(4),(2),(8),(4),(2).
Ce se intimpla daca se utiliza protected?
• La instantierea unui obiect, apelul constructorului consta in transmiterea de valori parametrilor constructorului respectiv pentru initializarea datelor membre. Constructorul clasei derivate trebuie sa contina parametri corespunzatori tuturor valorilor necesare la initializarea obiectelor. #n cazul unui obiect al unei clase derivate, o parte din aceste valori se folosesc pentru initializarea datelor membre ale obiectului, specifice clasei derivate, iar o parte pentru initializarea datelor membre ale sale, care au fost mostenite din clasele de baza.

• Transferul valorilor de initializare a datelor membre ale unui obiect, ce corespund mostenirii de la clasele de baza, se pune in evidenta cu susținerea antetului constructorului clasei derivate.
Exemplu:
class D:public B_1, public B_2, public B_3
{
…………………………………….
D(...); // constructor in clasa derivata (prototip)
………………………………
};
Antetul constructorului D(…) are forma urmatoare:

D::D(…):B_1(…),B_2(…),B_3(…)

O expresie de forma B_k(…)(k=1,2,3) va contine intre paranteze o lista de expresii care definesc valori initiale pentru datele membre corespunzatoare clasei B_k. O astfel de expresie va lipsi din antetul constructorului D(…) daca:
a) clasa B_k nu are constructor;
b) datele membre ale clasei B_k se initializeaza cu valori implicite (exista constructor cu parametri impliciti);
c) clasa B_k nu are date membre.
Expresia B_k(…) constituie un apel explicit al unui constructor al clasei B_k.

• Constructorii claselor de baza se pot apela din clasa derivata, daca protectia lor este de tip public sau protected.

• Lista apelurilor constructorilor claselor de baza nu se afla in prototipurile constructorilor clasei derivate, ci numai in antetele lor.

• Exista urmatoarele situatii diferite cu privire la existenta constructorilor in clasele de baza, respectiv clasa derivata din acestea:
a) Nu exista constructori atit in clasa derivata cit si in clasele de baza mostenite.
In acest caz, la instantierea obiectelor clasei derivate se apeleaza constructorii impliciti generati de compilator.
Exemplu:
Sa notam cu B clasa de baza, iar cu D clasa derivata.
Un obiect d al clasei derivate D se instantiaza fara initializari.
O instantiere in acest caz este de forma:
D d; // se apeleaza constructorul implicit generat de compilator

b) Cel putin una din clasele de baza are constructori, iar clasa derivata nu are constructori.
Atunci:
1) toti constructorii, care exista in clasele de baza, vor fi impliciti, sau cu toti parametrii cu valori implicite (parametri impliciti);
2) nu se pot face initializari la instantierea obiectelor clasei derivate;
3) la o instantiere a clasei derivate, se apleleaza constructorul implicit al clasei derivate generat de compilator, si constructorii claselor de baza cu parametri impliciti.
Exemplu:
class B{
protected:
int u,z; //date membre in clasa de baza
public:
B(int p=5, int q=5){u=p; z=q;}
// constructor cu parametrii impliciti in clasa de baza
…………………………………………
};
class D:public B{
protected:
int alfa;
public:
…………….
};

O declaratie de forma
D d;
arata ca obiectul d se creeaza apelind constructorul cu parametrii impliciti al clasei B. Datele membre u si z se vor initializa cu valoarea 5, iar data membra alfa nu este initializata.

c) Nu exista constructori definiti de programator in nici-o clasa de baza mostenita, dar exista astfel de constructori in clasa derivata.

Atunci:
1) este necesar sa existe acces al clasei derivate la toate datele membre ale claselor de baza care comporta initializari;
2) constructorul clasei derivate va initializa toate datele membre specifice clasei derivate cit si pe cele provenite din clasele de baza;
Exemplu:
class B
{
protected:
int u,z;
public:
…………………
// nu exista constructor definit de programator
};
class D:public B
{
protected:
int alfa,i,j;
public:
D(int p=0, int q=0, int lu=200, int lz=250)
{ u=p;
z=q;
i=lu;
j=lz;
if(p>=0 && p<lu>=0 && q<=lz)
alfa =1;
else
alfa=0;
}
……………….
};

Exemple de instantieri:
D d; // d.u=0, d.z=0, d.i=200, d.j=250, d.alfa =1
D d(100,500); // continuati si comentati !

d) Atit clasa derivata cit si cel putin o clasa de baza mostenita au constructori definiti de programator.
Atunci:
1) constructorul clasei derivate contine parametri pentru toate datele membre ce comporta initializari;
2) valorile parametrilor ce corespund datelor membre specifice clasei derivate sunt utilizate pentru initializarea datelor respective in mod obisnuit (prin constructorul clasei derivate), iar restul de valori sunt utilizate la apelul explicit al constructorilor claselor de baza.
Exemplu:
class zona
{protected:
int u;
int v;
public:
zona(int ui, int vi); //constructor al clasei de baza
…………………
};
class punct:public zona
{ //clasa punct este derivata din clasa zona
………………….
public:
punct(int Ui, int Vi); // constructor al clasei derivate
………………………
};

zona::zona(int ui, int vi)
{ //def. constructorului clasei de baza
u=ui;
v=vi;
}
punct::punct(int Ui, int Vi):zona(Ui,Vi){…} //apel explicit al constructorului clasei de baza

Se observa ca la apelul constructorului clasei de baza se utilizeaza aceeasi sintaxa ca la listele de initializare. Se poate privi "cantitatea" mostenita ca un penis ascuns care se initializeaza printr-un apel al unui constructor. In apelul constructorului, vom folosi identificatorul clasei, pentru ca un astfel de membru ascuns nu are identificator.

• Atunci, cind cel putin o clasa din lista claselor de baza mostenite are un constructor care nu este implicit si nici cu toti parametrii impliciti, clasa derivata trebuie sa aiba cel putin un constructor definit de programator.

• Se stie ca daca nu exista un constructor de copiere intr-o clasa, compilatorul, cind este necesar, genereaza in mod automat un constructor de copiere implicit. Apelul acestuia conduce la copierea bit cu bit a datelor membre ale unui obiect sursa (obiect care se copiaza) in datele membre corespunzatoare unui obiect destinatie (obiect care se creeaza).

• Necesitatea unui constructor de copiere definit de programator se impune atunci cind:
a) copierea bit cu bit devine insuficienta;
b) clasele contin date membre pointeri spre zone de memorie alocate dinamic in heap;
c) folosind date membre mostenite din clasa de baza, procesul de copiere bit cu bit conduce la anumite erori.

• Utilitatea constructorului de copiere consta in:
a) initializarea unui obiect printr-un alt obiect;
b) transfer de obiecte prin parametri;
c) returnarea obiectelor la revenirea din functii.

• Apelul unui constructor de copiere se face in situatii de genul urmator:
a) Clasa derivata si clasele de baza mostenite nu au constructori de copiere definiti de programator.

In acest caz, copierea se va face bit cu bit, apelindu-se constructorii de copiere impliciti generati de compilator.

b) Cel putin o clasa de baza are un constructor de copiere definit de programator, dar un astfel de constructor nu exista in clasa derivata corespunzatoare.
In aceasta situatie, daca este nevoie de un constructor de copiere, pentru a crea un obiect alclasei derivate D (vezi utilitatea sa), se va apela constructorul de copiere implicit al clasei D, generat de compilator. Aceasta inseamna copierea bit cu bit a datelor membre specifice clasei D si a datelor membre mostenite de la clasele de baza care nu au un astfel de constructor. Celelalte date membre se initializeaza prin apelul automat al constructorilor de copiere ce exita in clasele de baza.
c) Clasa derivata are constructor de copiere definit de programator.
Apelul constructorului de copiere al clasei derivate D se face cind este nevoie. Folosirea constructorilor din clasele de baza corespunzatoare se face in functie de definitia constructorului de copiere al clasei derivate. Apelul constructorului de copiere al clasei derivate nu apeleaza automat constructorii de copiere ai claselor de baza. Un astfel de apel al constructorului de copiere al clasei derivate se va face conform anumitor reguli.
1) Daca clasa derivata D poseda un constructor de copiere de antet:
D(const D& d) // antetul constructorului de copiere al clasei derivate atunci clasa de baza B, fie ca nu are nici un constructor definit de programator, fie ca are un constructor implicit, sau cu toti parametrii impliciti.
O instantiere de forma:
D d_1=d; // d este un obiect al clasei derivate anterior declarat apeleaza constructorul de copiere al clasei derivate D cu antetul precizat anterior. Un astfel de apel conduce la apelarea automata a constructorului prezent in clasa de baza B (generat de compilator sau cel definit de programator).

2) Daca clasa de baza B are constructori definiti de programator dar nici unul nu este implicit sau cu toti parametrii impliciti, atunci constructorul de copiere al clasei derivate D trebuie sa contina apelul explicit al unui constructor al clasei de baza B.

Antetul constructorului de copiere al clasei derivate D va fi de forma:
D(const D& d):B(…).

• Destructorii opereaza in in sens invers fata de constructori. Fiindcă destructorii nu au parametri, apelurile lor se realizeaza in mod implicit de catre compilator. Ordinea de apel ar fi urmatoarea:

- destructorul clasei derivate (cind un obiect "derivat" iese din domeniul sau);
- destructori pentru membrii specifici clasei derivate;
- destructorul clasei de baza;
- destructori pentru membrii clasei de baza.

Aplicatie:
Sa se defineasca clasa derivata "segment" avand clasa de baza "punct_1". Sa se puna in evidenta modul de întrebuințare al constructorilor in procesul de derivare.

#include<iostream> #include<conio> #include<math> class punct_1{ protected: double x,y; public: punct_1(){;}

punct_1(double x1, dublu y1) {x=x1;y=y1;}
punct_1(punct_1*a){x=a->x; y=a->y;}
void afis_punct()
{
cout<<"Abscisa punctului:"<<x;
cout<<"Ordonata punctului:"<<y;
}
double dist(punct_1 p_2)
{
return (sqrt((x-p_2.x)*(x-p_2.x)+(y-p_2.y)*
(y-p_2.y)));
}
double& ret_x(){return x;}
double& ret_y(){return y;}
};
class segment: public punct_1
{
punct_1 varf,p_1;
public:
segment(double x_0,double y_0,double xv,double yv): punct_1(x_0,y_0)
{
punct_1 varf;
varf.ret_x()=p_1.ret_x();
varf.ret_y()=p_1.ret_y();
}
punct_1 ret_orig()
{
punct_1 p;
p.ret_x()=x;
p.ret_y()=y;
return p;
}
};
void main(void)
{
punct_1 p_1(5,6), p_2(7,8);
clrscr();
cout<<"Distanta:\n"<<p_1.dist(p_2);
cout<<"\n";
segment s_1(5,6,7,8);
cout<<"Originea:"<<s_1.ret_orig().ret_x();
cout<<"\n"; cout<<"Extremitatea:"<<s_1.ret_orig().ret_y();
getch();
}
Vezi profilul utilizatorului Trimite mesaj privat
Afiseaza mesajele pentru a le previzualiza:   
Creaza un subiect nou   Raspunde la subiect

Subiectul urmator
Subiectul anterior
Nu puteti crea un subiect nou in acest forum
Nu puteti raspunde in subiectele acestui forum
Nu puteti modifica mesajele proprii din acest forum
Nu puteti sterge mesajele proprii din acest forum
Nu puteti vota in chestionarele din acest forum


Powered by phpBB © 2001, 2002 phpBB Group