Sunteți pe pagina 1din 4

PROGRAMAREA ORIENTATĂ PE OBIECTE - Laborator 

Lucrarea de laborator 4.

Folosirea funcţiilor prietene.


Având declarată deja o funcţie, pentru a permite accesul la membrii unei clase o vom declara în
interiorul clasei ca fiind funcţie prietenă cu specificatorul friend. Acesta va fi folosit astfel:

class nume_clasa{
…// declaram date membre
…// declaram functii membre
friend tip_returnat functie_prietena(…); // functia a devenit prietena a
//clasei
};

//se observa ca definitia functiei nu se schimba deloc
tip_returnat functie_prietena(…)
{
};

Astfel indiferent de ce specificatori de acces au membrii clasei, funcţia prietenă va avea acces
neîngrădit la toţi membrii clasei.
Se pot defini şi clase prietene unei clase nu numai funcţii prietene, cam în acelaşi mod.

class nume_clasa{
…// declaratii member
friend class nume_clasa_prietena;
}

Astfel nume_clasa_prietena are acces la toţi membrii nume_clasa, dar nume_clasa nu are acces
neapărat la toţi membrii clasei nume_clasa_prietena. Deci reciproca nu este valabilă.(decât specificat în
mod expres…)

Când lucrăm cu pointeri la obiect, iar obiectului respectiv nu i s-a alocat memorie, va trebui ca
înainte de folosire să folosim operatorul de alocare new, iar când nu mai lucrăm cu obiectul operatorul
delete. Ei au următoarea adresare:

nume_obiect=new nume_clasa;
delete nume_obiect;

Putem folosi aceşti operatori şi cu alte tipuri decât clase. În loc de nume_obiect având
nume_variabilă şi în loc de nume_clasa numele tipului.
PROGRAMAREA ORIENTATĂ PE OBIECTE - Laborator 

Când avem definiţi constructori apelarea acestora se va face în momentul alocării, respectiv
destructori la apelul operatorului delete.

Până acum nu s-a pus problema constructorilor şi destructorilor cu parametri. Aceştia sunt
declaraţi şi definiţi în modul în care sunt definite funcţiile desigur fără a returna un tip. În schimb la
declararea obiectelor va trebui specificat între paranteze după numele obiectului fiecare parametru
specificat în prototip.

nume_clasa obiect(p1,p2,p3…);

Pentru obiecte alocate dinamic :

nume_obiect = new nume_clasa(p1,p2,p3…);

Exerciţiu 1.
Modificaţi programul care conţine clasele cu numele persoana (cu următoarele date: nume,
adresa, cnp) şi angajat (nume_firma, data_angajarii) astfel încât obiectele definite să fie alocate
dinamic.
De exemplu se definesc
char*nume, *adresa,* CNP;
Pentru introducerea datelor privind persoana se va realiza o funcţie constructor de iniţializare
având prototipul:
persoana(char* n="", char *a="", char *c="");

Această funcţie va fi definită în afara clasei astfel:


persoana::persoana(char* n, char *a, char *c)
{nume=new char[strlen(n)+1];
strcpy(nume,n);
adresa=new char[strlen(a)+1];
strcpy(adresa,a);
CNP=new char[strlen(c)+1];
strcpy(CNP,c);
}
Functia destructor persoana va fi definită astfel:
persoana::~persoana()
{
delete[] nume;
delete [] adresa;
delete[] CNP;
}

Apelul constructorilor de iniţializare se va face astfel:

persoana a=persoana("NumeXX", "Calea Marasesti", "157");


angajat b = angajat("Universitatea din Bacau", "24.03.2009");

Pentru a ne referi strict la o instanţă a unui membru al clasei, adică cea declarată şi folosită într-
un obiect anume, pentru a avea acces la datele şi funcţiile din memoria alocată acestuia vom folosi
PROGRAMAREA ORIENTATĂ PE OBIECTE - Laborator 

pointerul this (trad. acesta). Acesta returnează adresa obiectului. Pentru a ne referi la un membru al
clasei din interiorul unei funcţii membru vom folosi apelare:

this->membru=…;
this->functie_membru();
…=this->membru;

Un alt element al programării pe obiecte este utilizarea funcţiilor virtuale. Declararea virtuală a
unei funcţii are utilitate în procesul de moştenire (sau derivare). Astfel o funcţie declarată virtuală în
clasa de bază este moştenită ca virtuală în clasele derivate. Cu toate că avem funcţia definită în clasa de
bază dacă ea este redefinită în clasa derivată această funcţie va face când va fi apelată ceea ce s-a
precizat în clasa derivată şi nu ceea ce făcea în clasa de bază. Deci faptul că o funcţie este virtuală
permite suprascrierea ei în toate clasele ce vor rezulta prin derivarea clasei de bază (prin utilizarea
aceluiaşi nume).

Exemplu:

class animal_vertebrat{public:
…//caracteristici generale specifice oricarui animal vertebrat
virtual void mod_de_deplasare() {cout<<”Inoata!”<<endl;}
};
class peste:public animal_vertebrat{
…//caracterisitici specifice
// nu redeclaram functia pt ca este valabila afirmatia „Inoata!”
};
class patruped:public animal_vertebrat{
public:
void mod_de_deplasare(){cout<<”Merge!” <<endl;;}
};
class pasare: public animal_vertebrat{
public:
void mod_de_deplasare(){cout<<”Zboara!” <<endl;;}
};

void main()
{
animal_vertebrat somon;
peste rechin;
patruped elefant;
pasare vultur;
cout<<"somon - >";
somon.mod_de_deplasare();
cout<<"elefant - > ";
elefant.mod_de_deplasare();
cout<<"rechin - > ";
rechin.mod_de_deplasare();
cout<<"vultur - > ";
PROGRAMAREA ORIENTATĂ PE OBIECTE - Laborator 

vultur.mod_de_deplasare();}

Programul va afişa:

somon -> Inoata!

etc.

Se observă că-n toate clasele derivate în afară de peste funcţia mod_de_deplasare() a fost
suprascrisă.

Exerciţiu 2. Creaţi modificând exemplul de mai sus o clasă reptila derivată din pasare, iar în
această clasă modificaţi funcţia virtuală astfel încât să afişeze „merge si inoata”.
Declaraţi un obiect de tip reptila şi verificaţi dacă funcţia virtuală a fost suprascrisă şi programul
funcţionează corect. De remarcat că în toate celelalte clase derivate funcţia declarată virtual în clasa de
bază nu mai trebuie precedată de virtual, acest atribut fiind subînţeles.
Obs. Se pare că programul nu funcţionează. Problema apare pentru că la suprascrierea
funcţiilor virtuale se suprascrie şi specificatorul de acces, şi pentru că nu este precizat este luat implicit
private. Asta înseamnă că accesul la funcţia membru mod_de_deplasare nu vă este permis. Rezolvaţi
problema. După ce aţi rezolvat problema adăugaţi un constructor clasei de bază şi prin acesta
transmiteţi un şir de caractere cu numele efectiv al speciei animalului pe care îl păstraţi într-un şir de
caractere. Pentru copierea şirului de caractere în alt şir folosiţi funcţia strcpy(dest,sursa) din biblioteca
string.h.
Funcţiile constructor şi destructor pentru clasa vertebrat vor fi:
animal_vertebrat(char*n="")
{nume=new char[strlen(n)+1];
strcpy(nume,n);
}
~animal_vertebrat()
{delete nume;}

Aceste nume îl veţi afişa înainte de a spune cum se deplasează animalul făcând o modificare în
funcţiile virtuale din fiecare clasă preferabil la aceeaşi apelare a cout.
Veţi constata erori deoarece constructorii nu se moştenesc în mod implicit. Chiar şi derivarea
trebuie din nou specificată pentru constructori în mod obligatoriu.(sintaxa este nume_clasa(char
*numeanimal):clasa_baza(numeanimal){};
Funcţiile constructor şi destructor în acest caz vor fi:
peste(char*n=""):animal_v(n){};
~peste(){};

Iniţializare obiectului rechin de tip peste se va face astfel:


peste rechin=peste("rechin");
Redefinirea se va face pentru fiecare clasă derivată. Trebuie reţinut că la rularea unui program
mai întâi sunt apelaţi în ordinea derivării mai întâi constructorul clasei de baza, apoi cei ai clasei
derivate pe urmă cei ai clasei derivate din aceasta ş.a.m.d., ultimul apelat fiind cel al clasei din care
face parte obiectul. Pentru destructori aceeaşi regulă numai că ordinea este inversată.

S-ar putea să vă placă și