Sunteți pe pagina 1din 41

CAPITOLUL 3

CLASE ŞI OBIECTE
CONSTRUCTORI ŞI
DESTRUCTORI
INIŢIALIZAREA OBIECTELOR UNEI CLASE -
CONSTRUCTOR

O funcţie care serveşte la crearea şi iniţializarea


obiectelor
 Are acelaşi nume ca şi clasa
 Are rolul de a permite declararea obiectelor
 Alocă spaţiul de memorie necesar obiectelor
declarate
 Se apelează de fiecare dată când se crează noi
instanţieri ale clasei
 Iniţializează datele membru ale obiectului
 Poate fi folosit pentru accesarea datelor şi
metodelor membre
 Nu returnează valori
TIPURI DE CONSTRUCTORI
1. CONSTRUCTORI IMPLICIŢI – se pot obţine:
 prin declararea de către utilizator a unui constructor simplu,
fără parametri, indiferent de instrucţiuni: clasa ();
 prin generarea implicită a constructorului de către compilator,
atunci când clasa respectivă nu are nici un constructor – caz în
care corpul său nu va conţine nici o instrucţiune
EXEMPLUL 1
class persoana
{ char *nume;
char *adresa;
int varsta;
public: persoana() //constructor implicit al clasei persoana
};
#define nr_persoane 100
void main()
{
persoana tablou [nr_persoane]; //apel implicit la constructorul
//implicit al clasei persoana
}
EXEMPLUL 2

#include <stdio.h>
class intreg //declarare clasa integ
{
public:
int a; //declarare variabilă publică a
};
intreg g; //declararea obiectului g
main() //funcţia rădăcină
{
intreg x, y, z; //declararea obiectelor x,z,y
}
Observaţie - obiectele g, x, y, z sunt instanţiate cu un
constructor implicit apelat automat la declararea obiectelor
EXEMPLUL 3
#include <iostream.h>
class intreg //declarare clasa întreg
{
public:
int a; //declarare variabila publică a
intreg () //constructor implicit fără parametri
{
cout<<“INTREG\n”; //tipăreşte cuvântul INTREG
}
};
intreg g; //declararea obiectului g
main() //funcţia rădăcină
{
intreg x, y, z; //declararea obiectelor x,z,y
}
Observaţie –programul tipăreşte de 4 ori cuvântul INTREG
deoarece se apelează constructorul de 4 ori, pentru fiecare
obiect declarat g, x, y, z
TIPURI DE CONSTRUCTORI
2. CONSTRUCTORI CU LISTĂ DE PARAMETRI –

clasa (lista parametri formali);

 Iniţializarea câmpurilor de date se face pe baza


valorilor primite ca şi parametri de către
constructor
 În cazul în care o clasă are mai mulţi constructori,
aceştia sunt apelaţi în funcţie de parametrii primiţi
 Un constructor nu poate avea un parametru
formal de tipul clasei din care face parte
EXEMPLUL 4
class persoana
{ char *nume;
char *adresa;
int varsta;
//constructor cu parametri al clasei persoana
public: persoana(char *n, char *adr, int v);
};
persoana :: persoana(char *n, char *adr, int v) //definire constructor
{
strcpy (nume, n);
strcpy (adresa, adr);
varsta = v;
}
void main()
{
persoana eu (“Mirela Pater”, “Oradea”, 40); //apel constructor
persoana tu ( “Ioan Popescu”, “Timisoara”, 33); //apel constructor
}
EXEMPLUL 5 – FIŞIERUL HEADER TIME.H
// Fişierul header “time2.h” va conţine declararea clasei Time
#ifndef TIME2_H //se previne definirea multiplă a fişierului
#define TIME2_H
class Time { // definirea clasei Time
public:
Time( int = 0, int = 0, int = 0); // constructor implicit
// specifică (iniţializează) toate argumentele cu 0
void setTime( int, int, int ); // set ora, minute, secunde
void printUniversal(); // tipăreşte în formatul universal
void printStandard(); // tipăreşte în formatul standard
private:
int hour; // 0 - 23
int minute; // 0 – 59
int second; // 0 – 59
}; // sfârşit clasa Time
#endif
EXEMPLUL 5 – FIŞIERUL TIME.CPP
// Fişierul “time2.cpp” conţine
// definiţia funcţiei membru a clasei Time
#include <iostream.h>
// includem definiţia clasei Time din fişierul “time2.h”
#include "time2.h"
// Constructorul Time iniţializează fiecare dată membru cu 0
Time::Time( int hr, int min, int sec )
{
setTime( hr, min, sec ); // constuctorul aplează funcţia
//setTime care validează
//şi setează timpul
} // sfârşit constructor Time
EXEMPLUL 5 – FIŞIERUL TIME.CPP – CONT.
// funcţia setTime foloseşte şi validează formatul universal
// verifică valorile datelor şi setează valorile invalide cu zero
void Time::setTime( int h, int m, int s )
{
hour = ( h >= 0 && h < 24 ) ? h : 0;
minute = ( m >= 0 && m < 60 ) ? m : 0;
second = ( s >= 0 && s < 60 ) ? s : 0;
} // sfârşit funcţie setTime
// funcţia printUniversal afişează timpul în format universal
void Time::printUniversal()
{
cout <<hour << ":“<< minute << ":“<< second;
} // sfârşit funcţie printUniversal
// funcţia printStandard afişează timpul în format standard
void Time::printStandard()
{
cout << ( ( hour == 0 || hour == 12 ) ? 12 : hour % 12 )
<< ":“ << minute << ":“ << second
<< ( hour < 12 ? " AM" : " PM" );
} // sfârşit funcţie printStandard
EXEMPLUL 6
// Crearea unui constructor implicit pentru clasa Time.
#include <iostream.h>
// includem definiţia clasei Time din fişierul header “time2.h”
#include "time2.h“
int main()
{
Time t1; // toţi prametrii sunt impliciţi
Time t2( 2 ); // parametrii minute şi second sunt impliciţi
Time t3( 21, 34 ); // parametrii second sunt impliciţi
Time t4( 12, 25, 42 ); // toate valorile sunt specificate
Time t5( 27, 74, 99 ); // toate valorile sunt specificate eronat
cout << "Constructor cu:\n\n“<< " toţi prametrii impliciţi :\n ";
t1.printUniversal(); // 00:00:00
cout << "\n ";
t1.printStandard(); // 12:00:00 AM
cout << "\n\n Ora specificată; implicit minute şi secunde:\n ";
t2.printUniversal(); // 02:00:00
cout << "\n ";
t2.printStandard(); // 2:00:00 AM
EXEMPLUL 6 - CONTINUARE
cout << "\n\n Ora şi minute specificate; implicit secunde:\n ";
t3.printUniversal(); // 21:34:00
cout << "\n ";
t3.printStandard(); // 9:34:00 PM
cout << "\n\n Ora, minute, şi secunde specificate:\n ";
t4.printUniversal(); // 12:25:42
cout << "\n ";
t4.printStandard(); // 12:25:42 PM
cout << "\n\n Toate valorile specificate eronat:\n ";
t5.printUniversal(); // 00:00:00
cout << "\n ";
t5.printStandard(); // 12:00:00 AM
cout << endl;
return 0;
} // sfârşit main
EXEMPLUL 6 – REZULTAT AFIŞAT
Constructor cu :

Toti parametrii impliciti:


00:00:00
12:00:00 AM

Ora specificată ; implicit minute şi second:


02:00:00
2:00:00 AM

Ora şi minute specificate; implicit second:


21:34:00
9:34:00 PM

Ora, minute, şi secunde specificate:


12:25:42
12:25:42 PM

Toate valorile specificate eronat :


00:00:00
12:00:00 AM
TIPURI DE CONSTRUCTORI
3. CONSTRUCTORI DE COPIERE

clasa :: clasa (clasa &);

 Iniţializează noul obiect pe baza unui alt obiect, deja


existent, pe care îl primeşte ca şi parametru
 Are rolul de a atribui datele obiectului existent
(argument) celui nou creat, copiind membru cu
membru toate câmpurile de date ale obiectului
argument în cele ale obiectului nou
 Poate fi apelat chiar la definire obiectului
 Dacă nu este definit un altul, constructorul de copiere
este adăugat automat clasei
EXEMPLUL 7
class persoana
{ char *nume;
char *adresa;
int varsta;
public:
persoana(char *n, char *adr, int v); //constructor cu parametri al clasei persoana
persoana (persoana &); //constructor de copiere al clasei persoana
};
persoana :: persoana(char *n, char *adr, int v) //definire constructor cu parametri
{
strcpy (nume, n);
strcpy (adresa, adr);
varsta = v;
}
persoana :: persoana(persoana &p) //definire constructor de copiere
{
strcpy (nume, p.nume);
strcpy (adresa, p.adresa);
varsta = p.varsta;
}
void main()
{
persoana eu (“Mirela Pater”, “Oradea”, 47); //apel constructor cu parametri
persoana tot_eu = eu; //apel constructor de copiere
tot_eu = eu; //copiere bit cu bit a tuturor membrilor clasei persoana
}
EXEMPLUL 8
#include <iostream.h>
class intreg //declarare clasa întreg
{
public:
int a; //declarare variabila publică a
intreg (int v=0) //constructor cu parametri
{
cout<<“INTREG\n”<<v;
a=v;
}
intreg (intreg &v) //constructor de copiere
{
cout<<“COPIERE\n”;
a=v.a;
}
};
main() //funcţia rădăcină
{
intreg x=1, y=x;
}
PROPRIETĂŢI SPECIFICE CONSTRUCTORILOR
 Asigură iniţializarea corectă a tuturor variabilelor membru ale unui
obiect
 Oferă o garanţie în plus că iniţializarea unui obiect se va efectua o
singură dată
 Poarta numele clasei căreia aparţin
 Nu pot returna valori (nici la declararea lor nici la definire nu se
specifică void ca tip returnat)
 Adresa lor nu este accesibilă programatorilor (ex. &x::x() este ilegal)
 Sunt apelaţi implicit de câte ori este nevoie
 Dacă o clasă nu are nici un constructor definit de programator,
compilatorul va genera implicit unul (public, fără parametri, cu o listă
vidă de instrucţiuni)
 Pot avea parametri luând valori implicite
 Pot conţine operatorii new şi delete
 Asemeni funcţiilor obişnuite, pot conţine orice fel de acţiuni
 Obţinerea unui constructor inline este identic cu a funcţiilor membru
obişnuite
DESTRUCTOR
 Poate fi privit ca şi complement al constructorului
 Dacă constructorul este folosit pentru a aloca memorie şi a
efectua anumite operaţii, destructorul este folosit pentru a
elibera memoria alocată de primiul
 Dacă programatorul nu a definit un destructor, se generează
unul implicit
 Numele destructorului coincide cu cel al clasei căreia aparţine
precedat de caracterul “~” ( ~clasa)
 Destructorul nu are parametri şi nu returnează nici o valoare
(antetul nu conţine cuvântul cheie void, iar în corpul
destructorului nu apare instrucţiunea return;)
 O clasă are un singur destructor
 Destructorul se apelează implicit când viaţa unui obiect
încetează (la sfârşitul programului)
 În general obiectele se distrug în ordine inversă creării lor
EXEMPLUL 9
#include <iostream.h>
class intreg //declarare clasa întreg
{
public:
int a; //declarare variabila publică a
intreg (int v=0) //constructor cu parametri
{
cout<<“CREAT\n”<<v;
a=v;
}
~intreg () //destructor
{
cout<<“DISTRUS\n”;
}
};
intreg a; //declarare obiect
main() //funcţia rădăcină
{
intreg x=1, y=2;
}
MEMBRII STATICI
În cadrul unei clase se pot defini membrii statici
 Toate instanţele claselor respective împart acelaşi membru
 Se alocă o singură dată memorie, o singură zonă comună
tuturor obiectelor clasei
 Reprezintă soluţia optimă în cazul în care obiectele unei
clase folosesc date în comun – se reduce astfel numărul de
variabile globale
 Prin asocierea explicită a datelor statice unei anumite clase
este posibilă realizarea controlului accesului la aceste date
 Deoarece există un singur exemplar al datelor statice pentru
întreaga clasă, iniţializarea şi alocarea memoriei se fac
separat
⇒ membrii statici pot fi iniţializaţi chiar dacă nu există încă
obiecte instanţiate (dacă nu sunt publici se aplică regulile
generale de acces)
CÂMPURI DE DATE/VARIABILE STATICE
Sintaxa:
static tip nume;
 Pot fi publice, private sau protejate

Ex.
class ex
{
static float a; //declarare variabilă statică
public:
static float b; //declarare variabilă statică
};
float ex::a=10; //iniţializare corectă
float ex::b=12; //iniţializare corectă
CÂMPURI DE DATE/VARIABILE STATICE
Accesarea variabilelor statice se face prin
intermediul oricărui obiect al clasei
 Variabile statice publice
 Pot fi accesate folosind operatorul de rezoluţie (::)
Ex. Angajat::contor
 Variabile statice private
 Când nu există obiecte ale clasei
 Pot fi accesate doar prin intermediul funcţiilor

membru statice publice


 Pentru a apela funcţii membru statice publice se

combină numele clasei, operatorul de rezoluţie (::) şi


numele funcţiei
Ex. Angajat::getContor()
FUNCŢII MEMBRU STATICE

 Apelul unei funcţii membru /metode statice se face exact


la fel ca şi aceea a variabilelor membru statice
 Dacă într-o metodă statică dorim să operăm cu variabile
membru nestatice, vom fi obligaţi să furnizăm un
parametru explicit de genul obiect, pointer sau referinţă
la obiect
 Dacă domeniul de existenţă al clasei este local,
iniţializarea variabilelor membru nu mai este permisă
 Toţi membrii statici ai unei clase sunt doar declaraţi în
cadrul clasei, ei urmând a fi obligatoriu iniţializaţi.
 Este obligatoriu ca parametrii constructorilor unor
obiecte statice să fie expresii constante
 în corpul funcţiilor statice, nu pot fi accesate decât
datele membre statice.
APELAREA CONSTRUCTORILOR ŞI DESTRUCTORILOR

 Pentru obiecte globale


 Constructori
 Înaintea oricăror alte funcţii (inclusiv funcţia main)
 Destructor
 La terminarea funcţiei main (sau la apelul funcţiei exit)
 Nu este apelat dacă programul se termină forţat (abort)

 Pentru obiecte locale automate


 Constructori
 La definirea obiectelor
 La fiecare execuţie a scopului lor

 Destructor
 Când obiectele abandonează scopul lor
 Nu este apelat dacă programul se termină cu exit sau
abort
APELAREA CONSTRUCTORILOR ŞI DESTRUCTORILOR

 Pentru obiecte locale statice


 Constructori
 Exact o dată
 Când execuţia ajunge în punctul în care este definit

obiectul
 Destructor
 Când funcţia main se termină sau este apelată funcţia exit
 Nu este apelat dacă programul se termină cu abort
CLASE IMBRICATE
 În cazul în care o clasă are ca membri obiecte (instanţieri) ale
altor clase spunem că avem clase imbricate
 În acest caz este foarte important modul în care se face apelul
constructorilor obiectelor membru.
 Pentru a ilustra folosirea acestor tipuri de clase vom analiza
exemplul următor în care:
 Vom defini tipul punct, cu datele membre x şi y (abscisa şi ordonata
unui punct). Operaţiile care pot fi realizate asupra obiectelor de tip
punct, sunt: afişare (afişează coordonatele unui punct), deplasare
(deplasează un punct, noile coordonate ale punctului fiind obţinute prin
adunarea unor valori transmise ca parametri, la valorile anterioare ale
coordonatelor), abscisa (returnează valoarea abscisei), ordonata
(returnează valoarea ordonatei).
 Vom defini tipul segment, cu datele membre A şi B, de tip punct,
reprezentând capetele unui segment (originea şi vârful). Operaţiile care
pot fi realizate asupra obiectelor de tip segment, sunt: afişare (afişează
coordonatele capetellor segmentului), deplasare (translatează un
segment, deplasând capetele acestuia cu valorile transmise ca
parametri), origine (returnează originea segmentului), vârf (returnează
vârful segmentului).
EXEMPLUL 10
#include <iostream.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>

class punct //CLASA PUNCT


{ double x,y;
public:
punct()
{x=0;y=0;cout<<"Constr. implicit pentru punct("<<x<<","<<y<<")\n";}
punct(double,double); //constructor initializare
punct(punct&); //constructor copiere
~punct(); //destructor
double abscisa(){return x;}
double ordonata(){return y;}
void afisare();
void deplasare(double,double);
};
EXEMPLUL 10 - CONTINUARE
class segment //CLASA SEGMENT
{ private:
punct A,B;
public:
segment(punct&,punct&); //constructor
segment(segment&); //constructor de copiere
~segment(); //destructor
punct origine();
punct varf();
void afisare();
void translatie(double,double);
};
EXEMPLUL 10 - CONTINUARE
//METODELE CLASEI PUNCT
punct::punct(double valx,double valy)
{ x=valx; y=valy;
cout<<"Constructor punct ("<<x<<","<<y<<")\n"; }
punct::~punct()
{ cout<<"Destructor punct ("<<x<<","<<y<<")\n";}
punct::punct( punct &P)
{ x=P.x; y=P.y;
cout<<"Constructor copiere pct ("<<x<<","<<y<<")\n";}
void punct::deplasare(double dx,double dy)
{ x+=dx; y+=dy;}
void punct::afisare()
{ cout<<"Punct ("<<x<<','<<y<<')';}
EXEMPLUL 10 - CONTINUARE
//METODELE CLASEI SEGMENT
segment::segment(punct &A1,punct &B1)
{ A=A1;B=B1;
cout<<"Constructor segment[";
A.afisare(); B.afisare(); cout<<"]\n";}
segment::segment(segment &AB)
{ A=AB.A; B=AB.B;
cout<<"Constructor copiere segment [";
A.afisare(); B.afisare(); cout<<"]\n";}
punct segment::origine()
{ return A;}
punct segment::varf()
{ return B;}
void segment::afisare()
{ cout<<"[";A.afisare(); cout<<','; B.afisare(); cout<<"]"<<'\n'; }
segment::~segment()
{ cout<<"Destructor segment ["; A.afisare();
cout<<","; B.afisare(); cout<<"]\n";}
void segment::translatie(double dx,double dy)
{ A.deplasare(dx,dy); B.deplasare(dx,dy);}
EXEMPLUL 10 - CONTINUARE
void main()
{clrscr();
punct P(7.8,-20.4),Q(-4.82,8.897),A,B;
/* Constructor punct (7.8,-20.4) (Pentru punctul P)
Constructor punct (-4.82,8.897) (Pentru punctul Q)
Constr. implicit pentru punct(0,0)
Constr. implicit pentru punct(0,0) (pentru punctele A, B)*/
punct P3, Q3;
/* Constr. implicit pentru punct(0,0)
Constr. implicit pentru punct(0,0) (pentru punctele P3, Q3)*/
segment S(P,Q);
/* Constr. implicit pentru punct(0,0) Constr. implicit pentru punct(0,0)
(pentru membrii A, B ai obiectului S, deci pentru S.A şi S.B)
Constructor segment[Punct (7.8,-20.4)Punct (-4.82,8.897)]
(pentru obiectul S, de tip segment) */
segment S1(P3,Q3);
/* Constr. implicit pentru punct(0,0) Constr. implicit pentru punct(0,0)
(pentru membrii A, B ai obiectului S1, deci pentru S1.A şi S1.B)
Constructor segment[Punct (0,0)Punct (0,0)]
(pentru obiectul S1, de tip segment) */
EXEMPLUL 10 - CONTINUARE
cout<<" Apasa un car. ptr. continuare!\n"; getch();
cout<<"Punctele:\n";
P.afisare(); cout<<'\n'; Q.afisare();cout<<'\n';
P3.afisare(); cout<<'\n'; Q3.afisare();cout<<'\n';
A.afisare(); cout<<'\n'; B.afisare();cout<<'\n';
cout<<"\nSegment:"; S.afisare(); cout<<'\n';
punct D(1,2); // Constructor punct (1,2)
punct C; // Constr. implicit pentru punct (0,0)
C=D; //operaţie de atribuire
C.afisare(); // Punct (1,2) (pentru punctul C)
getch();
punct CC=C; //Constructor copiere pct (1,2)
cout<<"In urma copierii:";
CC.afisare(); // În urma copierii:Punct (1,2) (pentru punctul CC)
EXEMPLUL 10 - CONTINUARE
cout<<"Se deplaseaza punctul CC cu valorile 10, 20. Noile coord.=";
CC.deplasare(10, 20); CC.afisare();
// Se deplaseaza punctul CC cu valorile 10, 20. Noile coord.=Punct (11,22)
cout<<"Abscisa CC="<<CC.abscisa()<<"Ordonata CC=“
<<CC.ordonata()<<'\n';
//Abscisa CC=11 Ordonata CC=22
cout<<"Varf segment S=";
(S.varf()).afisare();
/* Varf segment S=Constructor copiere pct (-4.82,8.897)
(metoda varf returneaza un punct, copiere)
Punct (-4.82, 8.897)
Destructor punct (-4.82,8.897)*/
cout<<"Origine segment S="; CC=S.origine();
/* Origine segment S=Constructor copiere pct (7.8,-20.4)
(metoda origine returneaza un punct, copiere)
Destructor punct (7.8,-20.4) */
EXEMPLUL 10 - CONTINUARE
CC.afisare(); // Punct (-4.82, 8.897)
S1=S; //operatie de atribuire
S1.afisare();
// Punct (7.8,-20.4)[Punct (7.8,-20.4), Punct (-4.82,8.897)]
cout<<"Translatie S1 cu 100,1000. S1 translatat este:";
S1.translatie(100, 1000); S1.afisare();
/* Translatie S1 cu 100,1000. S1 translatat este:
[Punct (107.8,979.6),Punct (95.18,1008.897)] */
segment S2=S1;
/* Constr. implicit pentru punct(0,0) (pentru S2.A)
Constr. implicit pentru punct(0,0) (pentru S2.B)
Constructor copiere segment [Punct (107.8,979.6)Punct (95.18,1008.897)]
Destructor segment [Punct (107.8,979.6),Punct (95.18,1008.897)]*/
cout<<"Segment S2 obtinut prin copiere:";
S2.afisare();
/* Segment S2 obtinut prin copiere:
[Punct (107.8,979.6),Punct (95.18,1008.897)] */
cout<<"Iesire din main\n"; // Iesire din main
}
DECLARAŢII FRIEND (PRIETEN)
 Fac posibil ca un obiect sau o funcţie din cadrul unui obiect să
aibă acces la membrii altui obiect, fără a fi legat în vreun fel de
acesta
 Cuvântul cheie FRIEND dă acces complet funcţiei sau
obiectului respectiv

FUNCŢII FRIEND (PRIETEN)

 Sunt funcţii ne-membre ale unei clase, care au acces la datele


membre private ale unei clase.
 Funcţiile prietene ale unei clase trebuie precizate în definiţia
clasei.
 Implementarea lor nu se face în interiorul obiectului ci undeva
în afara lui
 Prototipurile unor astfel de funcţii sunt precedate de cuvântul
cheie friend.
Situaţii în care pot fi utilizate declaraţii friend:

O funcţie independentă este prietenă a unei clase


 O funcţie membru a unei clase este prietenă a
altei clase
 O funcţie, în general, este prietenă a mai multor
clase
 Toate funcţiile membru ale unei clase sunt
prietene ale altei clase ⇒ aceasta este o situaţie
posibilă dar mai puţin întâlnită sub această formă
(situaţia de clase prietene poate fi evitată prin
declararea clasei friens ca fiind derivată din clasa
iniţială – moştenire)
SINTAXA GENERALĂ:
1. Clase friend
class A
{
…… //date şi metode ale clasei A
friend B;
};
class B
{
…… //date şi metode ale clasei B
};
Observaţie
 În acest caz, clasa B este o clasă prietenă a clasei A
SINTAXA GENERALĂ:
2. Funcţii friend
class A
{
…… //date şi metode ale clasei A
friend B :: functie_friend(...);
};
class B
{
…… //date şi metode ale clasei B
functie_friend(...)
};
Observaţie
 În acest caz, nu toată clasa B este prietenă a clasei A ci
doar metoda functie_friend este o funcţie prietenă a
clasei A
EXEMPLUL 11A REALIZAT CU CLASĂ FRIEND
#include <iostream.h>
#include <string.h>
class Carte
{ public: Carte*char *titlu)
{ strcpy(Carte :: titlu, titlu);}
void afiseaza_carte(void)
{ cout<<titlu; }
friend Cititor; //clasa Cititor este prietena clasei Carte
private: char titlu[60]; };
class Cititor
{ public: Cititor (char *nume)
{ strcpy(Cititor :: nume, nume); }
void afiseaza_cititor(class Carte carte)
{ cout<<“Cititor: “<<nume<<“ “<<“Carte: “<<Carte.titlu;}
private: char nume[60]; };
void main ()
{ Cititor cititor (“Popescu Ion”);
Carte carte_favorita ( “Morometii”);
cititor.afiseaza_cititor (carte_favorita);
}
EXEMPLUL 11B REALIZAT CU FUNCŢIE FRIEND
#include <iostream.h>
#include <string.h>
class Carte
{ public: Carte*char *titlu)
{ strcpy(Carte :: titlu, titlu);}
void afiseaza_carte(void)
{ cout<<titlu; }
friend Cititor :: afiseaza_ciititor *Carte carte); /*functia Citiror::afiseaza_cititor
este functie prietena a clasei Carte*/
private: char titlu[60]; };
class Cititor
{ public: Cititor (char *nume)
{ strcpy(Cititor :: nume, nume); }
void afiseaza_cititor(class Carte carte)
{ cout<<“Cititor: “<<nume<<“ “<<“Carte: “<<Carte.titlu;}
private: char nume[60]; };
void main ()
{ Cititor cititor (“Popescu Ion”);
Carte carte_favorita ( “Morometii”);
cititor.afiseaza_cititor (carte_favorita);
}
OBSERVAŢII
 Utilizarea declaraţiilor friend poate duce la conflicte de nume,
în cazul în care în ambele clase există date sau metode membru
care au acelaşi nume – se vor evita pe cât posibil astfel de
situaţi
 Relaţia de clasa prietenă nu este tranzitivă. Astfel, dacă clasa
cls1 este clasa prietenă a clasei cls2, iar clasa cls2 este clasă
prietenă a clasei cls3, aceasta nu implică faptul că cls1 este
clasă prietenă pentru cls3.
 Utilizarea declaraţiei friend trebuie să constituie o excepţie şi
nu o regulă în programare – ea distruge structurarea corectă a
programului
 Practic, mecanismul friend permite abateri controlate de la
ideea de protecţie a datelor în interiorul claselor prin încapsulare
 Utilitatea funcţiilor friend este evidentă, reducând timpul de
execuţie al programului însă ea nu reprezintă o tehnică pur
obiectuală

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