Sunteți pe pagina 1din 116

PROGRAMARE PE OBIECT IN Visual C++.

net
Executarea unui program in mod simplu se face cu combinatia de taste CTRL si F5
COSTRUCTIA PROGRAMELOR IN Visual C++.Net
1)Intru in Visual studio.net
2)File/new project
3)Visual C++ si aleg Window Command Apas PE
4)dau numele proiectului OBJECT
5) BROWSER

APAS PE
ACEASTA
OPTIUNE

SCRIU PROGRAMUL SI O SA–


L RULEZ cu CTRL si F5

1
Il rulez
apasand
dublu clic

asa am vazut executia

2
APLICATII
PROGRAMAREA PE OBIECTE
ASPECTE INTRODUCTIVE
Notiunea de structura
Abordarea orientată pe obiecte (AOO)

A. Un obiect poate fi considerat o entitate care încorporează atît structuri de date


(denumite atribute) cît şi comportament (operaţii). Un obiect trebuie să aibă precizate
mai multe caracteristici :

 identitate : obiectul are o identitate discretă, care se distinge dintre alte


entităţi.

Exemple de obiecte particulare :

 căciula studentului
 o fereastră deschisă pe un calculator
 un triunghi desenat pe hîrtie

Se observă că obiectele la care ne referim se referă la modelarea


realităţii imediate (v. fereastra)

 clasificare: obiectele cu aceleaşi atribute şi operaţii se grupează în clase.


Fiecare obiect poate fi considerat ca o instanţă a unei clase.

Exemple de clase :

 căciulă
 fereastră
 triunghi

 polimorfism: aceeaşi operaţie (cu acelaşi nume) poate să aibă


comportament diferit în clase diferite

Exemple: a muta

 o căciulă
 o fereastră
 un triunghi

Implementarea concretă a unei operaţii într-o anumită clasă se numeşte


metodă (method)

 moştenire: atributele şi operaţiile se transmit de-a lungul claselor bazate pe


o relaţie ierarhică

3
Exemple: se pot defini clasele Triunghi_Isoscel şi Triunghi_Echilateral ca
şi clase derivate din clasa Triunghi şi care moştenesc din această clasă poziţia pe
hîrtie, respectiv operaţia a muta.

În realitatea imediată să ne imaginăm că un fiu moşteneşte de la părinte o casă,


avînd aceasta anumite caracteristici. Fiul mai adaugă încăperi noi casei. Ca urmare,
casa dobîndeşte, pe lîngă caracteristicile existente, altele noi. Aşa şi în ierarhia de
clase: există, dependent de direcţia de parcurgere a ierarhiei, clase-părinte şi clase-fiu.
Clasele-fiu moştenesc trăsăturile claselor-părinte (deci toate structurile şi
comportamentele) la care pot fi adăugate altele noi.

B. Abordarea orientată spre obiecte foloseşte nişte concepte de bază:

 abstractizarea constă în focalizarea pe aspectele esenţiale ale unei entităţi.


Accentul, pentru un obiect, se pune pe ce este acesta şi pe ce trebuie să
facă, înainte de a stabili concret detaliile de implementare. De aceea, etapa
esenţială în crearea unei aplicaţii orientate spre obiecte este analiza şi nu
implementarea, care trebuie să devină aproape mecanică.

 încapsularea (ascunderea) informaţiei - constă în separarea aspectelor


externe ale unui obiect, care sunt accesibile altor obiecte, de aspectele de
implementare internă, care sunt ascunse celorlalte obiecte. Utilizatorul
poate accesa doar anumite atribute şi operaţii ale obiectului, numite publice,
în timp ce alte operaţii îi rămîn inaccesibile (numite private). Încapsularea
este foarte importantă atunci cînd se doreşte schimbarea implementării
pentru anumite operaţii, în scopul perfecţionării unui algoritm sau
eliminării unor erori. Încapsularea ne va împiedica să modificăm toate
caracteristicile obiectului, iar aplicaţiile nu vor avea de suferit

 "împachetarea" datelor şi a comportamentului în acelaşi obiect se referă la


faptul că un obiect conţine atît structuri de date cît şi operaţii şi este utilă
întrucît vom şti totdeauna cărei clase aparţine o metodă, chiar dacă există
mai multe operaţii cu aceaşi denumire, în clase diferite.

Existenţa unor operaţii (metode) diferite, cu acelaşi nume, dar cu


comportament diferit, se numeşte polimorfism. Utilizatorul nu trebuie
să se preocupe care anume operaţie este apelată, întrucît compilatorul
va face această identificare, în funcţie de argumentele metodei apelate.
Astfel, a muta o Căciulă este diferit de a muta o Fereastră pe ecran,
sau de a muta un Triunghi pe hîrtie, de aceea nu poate exista confuzie:
în funcţie de ce anume trebuie mutat, operaţia îşi va cunoaşte clasa,
deci şi implementarea.

 partajarea (sharing): aici înseamnă transmiterea aceloraşi structuri de date şi


respectiv operaţii, de-a lungul unor clase dintr-o ierarhie de clase, şi aceasta
are un efect benefic asupra economisirii de spaţiu (dacă o clasă moşteneşte
o altă clasă, atunci ea moşteneşte toate atributele şi operaţiile clasei de bază,
iar din punctul de vedere al codului, acestea sunt aceleaşi cu cele ale clasei
de bază şi nu copii ale lor).

4
Partajarea oferă posibilitatea reutilizării proiectării, în proiecte ulterioare.
Reutilizarea însă trebuie avută în vedere de la începutul proiectării, chiar
dacă implică un efort ceva mai mare. Beneficiile însă se recuperează din
plin, în timp.

 accentul pe structura de obiect, nu pe cea de procedură: în tehnicile


orientate spre obiecte, accentul cade pe înţelegerea sistemului din punctul
de vedere al descompunerii acestuia în entităţi (obiecte) şi al stabilirii
relaţilor dintre acestea, deci pe ce este un obiect (spre deosebire de analiza
funcţională - sau procedurală - care pune accentul pe ce trebuie să facă).
Mai important decît a stabili ce face sistemul, în acest caz trebuie precizat
cine face şi care sunt relaţiile între cei care fac.
Structuri şi clase

C++ a crescut rolul structurii standard din C la acela al unui mod mai subtil, de
specificare a unei clase. De fapt, diferenţa imediat vizibilă dintre o structură şi o clasă este
aceea că implicit toţi membrii unei structuri sînt publici pe cînd cei ai unei clase sînt implicit
privaţi. În celelalte privinţe, structurile şi clasele sînt similare. Aceasta înseamnă că în C++ o
structură defineşte de asemenea un tip special de clasă
Deoarece o structură (declarată cu cuvîntul cheie struct) în C++ defineşte un tip de clasă,
obiectele de acel tip pot fi declarate folosind doar numele generic al structurii, fără a mai folosi
cuvîntul cheie struct, aşa cum trebuie făcut în C (dar nu este o eroare dacă se precedă declaraţia
cu struct).
//Sa se defineasca o structura
#include "stdafx.h"
#include <iostream>
using namespace std;
#include <string.h>

// declararea structurii
struct sir_exemplu{
void face_sir(char *); // implicit va fi sectiune public
void arata_sir();
private: // iar sectiunea privata trebuie declarata explicit
char sir[80];
};

// urmeaza definirile functiilor


void sir_exemplu::face_sir(char *s)
{
if (! *s) *sir ='\n'; // initializare sir
else strcat(sir, s);
}

void sir_exemplu::arata_sir()
{
cout << sir << "\n";
}
Notiunea de uniune
Uniuni şi clase

Ca şi o structură, union poate fi folosită de asemenea pentru a defini o clasă.În C++,


uniunile pot conţine şi acestea, atît funcţii emmbre cît şi variabile membre. Ele pot să mai
includă şi funcţii constructor şi destructor. În C++ union păstrează toate capacităţile din C, cea

5
mai importantă fiind aceea că toate elementele de date împart aceeaşi locaţie de memorie. Ca şi
structura, membrii unei union sînt implicit publici.
La fel ca şi o structură, o declaraţie a unei union în C++ defineşte un tip special de clasă, deci
se păstrează principiul încapsulării. Iată acum cîteva restricţii asupra folosirii union în C++ :

 nu poate moşteni nici un alt tip de clasă


 nu poate fi clasă de bază
 nu poate avea funcţii virtuale membre (vom vedea mai departe ce înseamnă funcţii
virtuale)
 nu poate avea ca membre variabile de tip static
 nu poate avea ca membru nici un obiect care are supraîncărcat operatorul =
 nu poate avea ca membri obiecte care conţin funcţii constructor sau destructor

Uniuni anonime

În C++ există un tip special de union numit uniune anonimă. Aceasta nu conţine un nume de
tip şi nici o variabilă nu poate fi declarată ca fiind de acel tip de uniune. În schimb, ea comunică
compilatorului că variabilele membre ale uniunii vor împărţi aceeaşi locaţie. Dar variabilele în
sine pot if utilizate direct, fără sintaxa cu operator punct.
Mai mult, chiar dacă ele sînt definite într-o declaraţie union, ele sînt la acelaşi nivel al
domeniului de existenţă ca şi oricare alte variabile locale din acelaşi bloc. Membrii unei uniuni
anonime nu pot de altfel să aibă acelaşi nume cu al nici unui alt identificator cunoscut în
domeniul curent. Aceasta înseamnă că numele membrilor unei uniuni anonime nu trebuie să
intre în conflict cu alţi identificatori cunoscuţi din domeniul uniunii. Toate restricţiile pentru o
union se aplică şi celor anonime, cu următoarele completări :

 elementele care pot fi conţinute într-o uniune anonimă trebuie să fie de tip date (nu
sînt permise funcţii membre)
 uniunile anonime nu pot conţine elemente de tip private sau protected
 uniunile globale anonime trebuie să fie specificate ca fiind de tip static.

#include "stdafx.h"
#include <iostream>
using namespace std;
#include <string.h>

main()
{
// urmeaza definirea uniunii anonime
union {
long l;
double d;
char s[10];
};
// accesul la membrii uniunii anonime este direct
l=150000;
cout << l << endl;
d=123.456;
cout << d <<endl;
strcpy(s, "abcdefghij");
cout << s << endl;

return 0;

6
}
//sa se creeze o uniune in care sa se puna in evidenta urmatoarele:
//• nu poate mosteni nici un alt tip de clasa
//• nu poate avea functii virtuale membre (vom vedea mai departe ce
înseamna functii virtuale)
//• nu poate avea ca membre variabile de tip static
//• nu poate avea ca membru nici un obiect care are supraîncarcat
operatorul =
//• nu poate avea ca membri obiecte care contin functii constructor
sau destructor

#include "stdafx.h"
#include <iostream>
using namespace std;
// declararea union
union schimbare_octeti {
void schimba();
void pune_octeti(unsigned );
void arata_cuvint();

unsigned u;
unsigned char c[2];
};

// definirile functiilor membre


void schimbare_octeti::schimba()
{
unsigned char tmp,t;
t=c[0];
c[0]=c[1];
c[1]=t;
}
void schimbare_octeti::pune_octeti(unsigned i)
{
u=i;
}
void schimbare_octeti::arata_cuvint()
{
cout << u;
}

main()
{
schimbare_octeti sch;
sch.pune_octeti(34567);
sch.schimba();
sch.arata_cuvint();

return 0;
}
Clasele

Clasele sînt create utilizîndu-se cuvîntul cheie class. O declarare a unei clase defineşte
un nou tip care uneşte cod şi date. Acest nou tip este apoi folosit pentru a declara obiecte din
acea clasă. De aceea, o clasă este o abstractizare logică, dar un obiect are o existenţă fizică.
Altfel spus, un obiect este un exemplar (o instanţă) al unei clase.
O declarare de classă este similară sintactic cu cea a unei structuri. În capitolul
precedent a fost prezentată (simplificat) această declarare. Iată forma generală completă
a unei declaraţii de clasă care nu este un descendent al vreunei alte clase :

7
class nume_clasa {
date si functii particulare (fara specificator de acces, implicit)
specificator_de_acces:
date si functii
specificator_de_acces:
date si functii
...
specificator_de_acces:
date si functii
} lista de obiecte;

Lista de obiecte este opţională şi ea declară obiecte din acea clasă.


Specificator_de_acces este unul din următoarele cuvinte-cheie din C++ : public, protected
sau private. Implicit, funcţiile şi datele declarate într-o clasă sînt proprii acelei clase şi doar
membrii săi pot să aibă acces la ele (sînt deci private). Totuşi, folosind specificatorul de acces
public, accesul la funcţiile şi datele din secţiunea respectivă devin accesibile altor secţiuni ale
programului. O dată utilizat un specificator de acces, efectul său durează pînă cînd se întîlneşte
alt specificator de acces sau se ajunge la sfîrşitul declaraţiei clasei. Pentru întoarcerea la
declararea particulară (deci acces numai pentru membrii clasei) se poate folosi specificatorul de
acces private. Specificatorul protected este folosit în cazul moştenirii (se va vedea mai
departe).
Există cîteva restricţii care se aplică membrilor clasei :

 O variabilă membru care nu este de tip static nu poate să aibă o iniţializare;


 Nici un membru nu poate fi obiect al clasei care se declară (deşi un membru poate
fi un pointer către clasa care este declarată);
 Nici un membru nu poate fi declarat auto, extern sau register.

În general, trebuie să faceţi variabilele membre ale unei clase să fie


particulari acelei clase (deci de tipul private). Aceasta este şi ea un aspect al
încapsulării. Totuşi, pot exista situaţii în care se simte nevoia accesului la unele
variabile membre (de exemplu, poate fi necesar ca o variabilă folosită intens să fie
accesibilă global, pentru a obţine timpi de rulare mai mici sau chiar economie de
memorie). Cînd o variabilă este public, ea poate fi accesată direct de oricare secţiune a
programului. Sintaxa pentru accesul la o variabilă membră de tipul public este aceeaşi
ca pentru apelarea unei funcţii.
În rezumat : în C++ class creează un nou tip de date care pot fi
folosite pentru a construi obiecte de acel tip. De aceea, un obiect este o
instanţiere (un exemplar) a unei clase exact în acelaşi fel în care altă
variabilă este de exemplu un exemplar al tipului de date int. Altfel spus, o
clasă este o abstractizare logică, iar un obiect este real, clasa constituie
modelul după care se generează obiecte concrete (care există în memoria
calculatorului).

Forma generală a declarării unei clase este :

class nume_clasa {
date si functii private
public:

8
date si functii publice
} lista de obiecte;

Desigur, lista de obiecte poate fi vidă.


:: este numit operatorul de specificare a domeniului (operator de rezoluţie). Mai
multe clase pot folosi acelaşi nume de funcţie, iar compilatorul ştie care funcţie
aparţine fiecărei clase datorită operatorului de rezoluţie
6) Atenţie ! Variabilele private ale unui obiect sînt accesibile doar funcţiilor membre
ale obiectului. Deşi nu există de fapt o regulă care să dicteze ordinea de definire a
diverselor module de program, cel mai uzual funcţiile membre ale claselor sînt
definite înainte de main() iar funcţiile uzuale (nemembre) sînt definite după main().
În aplicaţiile uzuale, se foloseşte includerea claselor asociate unui program în
fişiere antet.
Supraîncărcarea funcţiilor

Un mod în care C++ realizează polimorfismul este supraîncărcarea funcţiilor


(overloading). În C++, două sau mai multe funcţii pot să aibă acelaşi nume atît timp
cît declaraţiile lor de parametri sînt diferite. În această situaţie, se spune că funcţiile cu
acelaşi nume sînt supraîncărcate iar procesul este numit supraîncărcarea funcţiilor.

Functii prietene
Este posibil să permitem unei funcţii care nu este membru să aibă acces la membrii particulari
ai clasei folosind cuvîntul cheie friend (prieten). O funcţie friend are acces la membrii private
şi protected ai clasei căreia îi este prietenă. Pentru a declara o funcţie friend, trebuie inclus
prototipul ei în acea clasă, precedat de cuvîntul cheie friend, există condiţii cînd funcţiile
prietene îşi dovedesc din plin utilitatea :
 la supraîncărcarea anumitor tipuri de operatori (se va vedea mai încolo)
 la crearea anumitor tipuri de operatori de intrare/ieşire
 în unele cazuri, două sau mai multe clase pot conţine membri care sînt corelaţi cu
alte secţiuni ale programului.
Pentru funcţiile friend se aplică următoarele restricţii :

 O clasă derivată nu poate moşteni funcţii friend;


 o funcţie friend nu poate avea un specificator de clasă de memorare, adică nu
poate fi declarată static sau extern.
Clase prietene

Chiar şi clasele pot fi declarate friend una pentru alta. În această situaţie, clasa friend
are acces la numele private definite în cadrul celeilalte. Aceste nume pot cuprinde nume de
tipuri şi enumerări de date. Trebuie reţinut că o clasă friend are acces doar la numele definite în
interiorul celeilalte. Ea nu moşteneşte cealaltă clasă, deci membrii primei clase nu devin
membri ai clasei friend.

//sa permitem unei functii care nu este membru sa aiba acces la


membrii particulari ai clasei folosind
//cuvîntul cheie friend (prieten)
#include "stdafx.h"
#include <iostream>

9
using namespace std;
class clasa_exemplu{
int a,b;
public:
friend int suma(clasa_exemplu ); // iata o functie
// prietena
void furniz_ab(int, int );
};

void clasa_exemplu::furniz_ab(int i, int j)


{
a=i;
b=j;
}

// acum urmeaza definirea functiei prietene suma, dar aceasta


// nu e membra a vreunei clase
int suma(clasa_exemplu cl){
return cl.a + cl.b; // functia are acces la a si b
}

main(){
clasa_exemplu c;
c.furniz_ab(1,2);
cout << suma(c);
return 0;
}

//folosirea unei functii friend in cadrul unei clase


#include "stdafx.h"
#include <iostream>
using namespace std;
#define IDLE 0
#define IN_USE 1

// declarari de clase
class C2; // vezi mai jos
class C1 {
int stare; // valorile IN_USE daca este pe ecran,
// IDLE daca nu e
// …
public:
void setare_stare(int );
int idle(C2 ); // nu mai este friend ci pur si
// simplu membru al clasei C1 de aceea nu mai
// trebuie C1 in lista de parametri
};
class C2{
int stare; // IN_USE daca e pe ecran, IDLE daca nu e
// …
public:
void setare_stare(int );
friend int C1::idle(C2 ); //diferenta e ca apare C1::
// (deci se marcheaza apartenenta la C1)
};

// definiri de functii membre


void C1::setare_stare(int cond)
{
stare=cond;
}

10
void C2::setare_stare(int cond)
{
stare=cond;
}

// functie membra C1 si prietena pentru C2


int C1::idle(C2 b)
{
if(stare || b.stare) return 0; // nu mai trebuie a.stare
else return 1; // ci e suficient direct
// stare
}

// programul principal
main()
{
C1 x;
C2 y;

x.setare_stare(IDLE);
y.setare_stare(IDLE); // initial ambele sint IDLE

if(x.idle(y)) cout << "Ecranul poate fi folosit.\n";


// referirea e ca functie membra pentru x
else cout << "In curs de folosire.\n";

x.setare_stare(IN_USE); // acum setam un ecran pe


// "folosire"
if(x.idle(y)) cout << "Ecranul poate fi folosit.\n";// si
else cout << "In curs de folosire.\n"; // si iata
// rezultatul
return 0;
}

// In programul principal folosim clasa definita de structura


main()
{
sir_exemplu sir;

sir.face_sir(""); // initializare
sir.face_sir("Acesta"); // construim
sir.face_sir("este"); // un sir mai lung in etape
sir.face_sir("exemplu.");

sir.arata_sir(); // si il afisam

return 0;
}

//sa se scrie o clasa cu date publice ce se refera la salariul


//unui angajat
#include "stdafx.h"
#include <iostream>
using namespace std;
#include <string.h>
// declararea clasei angajat
class angajat{
char nume[80];

11
public:
void pune_nume(char *);
void scoate_nume(char *);
private: // iar sectiune private
double salar;
public: // iar sectiune public
void pune_salar(double );
double furnizeaza_salar();
};

// urmeaza definirile functiilor membre


void angajat::pune_nume(char *num)
{
strcpy(nume, num);
}
void angajat::scoate_nume(char *num)
{
strcpy(num, nume);
}
void angajat::pune_salar(double suma)
{
salar=suma;
}
double angajat::furnizeaza_salar()
{
return salar;
}

// urmeaza programul principal


main()
{
angajat gheorghe; // se generaza un obiect de tip angajat
char nume[80];

gheorghe.pune_nume("Gheorghe Popescu");
gheorghe.pune_salar(860000); // i se adauga salariul pe
// luna curenta
gheorghe.scoate_nume(nume); // in nume va fi transferat
// numele
cout << nume << " are atitia lei ";
cout << gheorghe.furnizeaza_salar() << "pe luna.\n";

return 0;
}
//accesul la date publice se face direct in orice sectiune a
programului
#include "stdafx.h"
#include <iostream>
using namespace std;
class clasa_exemplu{
public:
int i,j,k; //acestea vor fi accesibile intregului program
};

main()
{
clasa_exemplu a,b; // se definesc doua obiecte de tipul
// clasa_exemplu
a.i=100;
a.j=4; // se lucreaza la fel ca si cu oricare
a.k=a.i*a.j; // variabila

12
b.i=a.j;
b.k=11; // a.k si b.k sint evident diferite
cout << a.k << " " <<b.k;
return 0;
}

Functii inline
O importantă caracteristică în C++, posibilitatea de a utiliza funcţii inline, eset
adeseori asociată cu folosirea claselor. În C++ pot fi create funcţii scurte care nu sînt apelate
efectiv ci codul respectivelor funcţii este inserat la fiecare folosire a acestora. Aceasta seamănă
cu utilizarea macro-urilor. Pentru a determina această modalitate de lucru, definirea funcţiei
respective trebuie precedată de cuvîntul-cheie inline.
Funcţiile inline sînt utilizate din motive de eficienţă. Astfel, pentru clase este adeseori necesar
să se solicite executarea frecventă a funcţiilor de interfaţă, care asigură accesul la datele private.
Prin utilizarea funcţiilor inline, eficienţa creşte prin aceea că astfel este înlocuit mecanismul
relativ complex al apelului şi transmiterii parametrilor (prin folosirea stivei şi salvarea
regiştrilor), prin folosirea directă a codului executabil a funcţiilor, fără să se mai folosească acel
mecanism. Bineînţeles prin acest procedeu codul executabil creşte în dimensiuni, de aceea se
recomandă utilizarea funcţiilor inline doar pentru coduri foarte scurte (puţine linii-sursă). Mai
mult decît atît, se recomandă alegerea acelor funcţii care au un impact puternic asupra
îmbunătăţirii performanţelor programului.
Asemenea specificatorului register, inline este pentru compilator o solicitare, nu o
comandă. Acesta poate chiar să o ignore. De asemenea, unele compilatoare nu pot insera inline
orice funcţie. De exemplu nu poate fi inline o funcţie recursivă (uşor de înţeles de ce).
Funcţiile inline pot fi membre ale unei clase.
Este posibilă definirea funcţiilor inline şi direct într-o declarare de clasă. Cînd o funcţie este
definită într-o declarare a unei clase, ea este automat transformată într-o funcţie inline, dacă e
posibil (dacă permite compilatorul). Nu este necesară declararea cu cuvîntul cheie inline (dar
bineînţeles nu constituie o greşeală).
// Sa se foloseasca o functie inline(codul respectivelor funcţii este
inserat la fiecare folosire a acestora)

#include "stdafx.h"
#include <iostream>
using namespace std;

inline int max(int a, int b)


{
return a>b ? a: b;
}

main()
{
cout << max(100,200);
cout << " " << max (300, 299);
return 0;
}

//destructorii sunt invers ca ordine apelati fata de constructori


#include "stdafx.h"
#include <iostream>
using namespace std;

13
class ordine{
public:
int cine;
ordine(int );
~ordine();
} glob_ob1(10), glob_ob2(20); // doua obiecte globale

ordine::ordine(int valinit)
{
cout << "Initializare " << valinit << "\n";
cine=valinit;
}
ordine::~ordine()
{
cout << "Distrugere " << cine << "\n";
}

main()
{
ordine local_ob1(30); // obiect local

cout << "Vedeti ? Aceasta nu e prima linie afisata !\n";

ordine local_ob2(40); // alt obiect local

return 0;
}

//Un alt exemplu de utilizare a funcţiei constructor cu parametri se


referă la o clasă care
//păstrează informaţiile despre cărţile dintr-o bibliotecã :
#include "stdafx.h"
#include <iostream>
using namespace std;
#include <string.h>

#define IN_BIBLIO 1
#define IMPRUMUTAT 0

class carte{
char autor[40];
char titlu[40];
int stare;
public:
carte(char *, char *, int );
int furniz_stare() {return stare;}
void pozit_stare(int s) {stare=s;}
void arata();
};
// constructorul initializeaza autor, titlu, stare
// transmisi ca parametri
carte::carte(char *aut, char *tit, int s)
{
strcpy(autor, aut);
strcpy(titlu, tit);
stare=s;
}
void carte::arata()
{
cout << titlu << " de " << autor <<" este ";

14
if (stare== IN_BIBLIO) cout << "aici.\n";
else cout << "imprumutata.\n";
}

main()
{
carte carte1("Cartarescu","Orbitor",IMPRUMUTAT);
carte carte2("Dinescu", "Democratia naturii", IN_BIBLIO);

carte1.arata();
carte2.arata();

return 0;
}
Membrii de tip static ai claselor
Membrii de tip static ai claselor

Atît funcţiile membre cît şi datele membre ale unei clase pot fi declarate static. În
continuare, să vedem ce înseamnă aceasta pentru fiecare tip de membru.

Membri statici de tip date

O dată care este precedată de cuvîntul static va exista doar într-un singur exemplar (o
singură copie) şi va fi folosită de toate obiectele de acea clasă. Spre deosebire de variabilele
membre obişnuite, nu sînt create copii individuale ale variabilelor membre static, pentru fiecare
obiect. Nu are importanţă cîte obiecte de acea clasă sînt create, va exista doar o singură copie a
membrilor de tip static. Cînd este creat primul obiect de acel tip, toate variabilele de tip static
sînt automat iniţializate cu zero.
În cadrul unei clase, declararea unei variabile static nu alocă memorie pentru aceasta.
Din acest motiv, trebuie dată a definire globală pentru membrii de tip static, în afara clasei,
folosind specificatorul de domeniu, pentru a preciza clasa de apartenenţă. Doar astfel se asigură
existenţa fizică a variabilei, prin alocarea de memorie pentru aceasta (este şi normal, declararea
clasei nu este altceva decît definirea unei structuri abstracte, a unui model după care pot fi
create obiecte; din acest motiv, variabilele statice nu pot fi alocate prin simpla includere într-un
model abstract). O variabilă membră de tip static există înainte de a fi creat orice obiect din
acea clasă. Mai mult, dacă respectiva variabilă este public şi întrucît există înainte de crearea
unui obiect din clasa în a cărei declarare apare variabila ca membră, aceasta poate dobîndi
valoare (care nu va fi modificată de crearea vreunui obiect din acea clasă) şi poate fi utilizată în
domeniul său de valabilitate, oricînd. Trebuie reţinut modul de acces la variabilele statice,
atunci cînd sînt accesate independent de obiecte: prin folosirea numelui clasei, urmat de
operatorul de rezoluţie şi apoi numele vaiabilei statice.
Uzual, variabilele membre statice sînt folosite la controlul accesului la unele resurse
comune. Fiecare obiect va putea să controleze valoarea variabilei statice membre pentru a
verifica posibilitatea accesului, deoarece există un singur exemplar al acestei variabile, care
poate fi văzut de toate instanţele clasei şi care va juca rolul unui semafor.
Funcţii membre statice

Şi funcţiile membre pot fi declarate static. Există mai multe restricţii relativ la funcţiile
astfel declarate :

15
 pot să aibă acces doar la alţi membri de tip static ai clasei (şi bineînţeles la funcţiile
şi datele globale);
 nu pot avea un pointer de tip this (se va vedea mai departe ce înseamnă acesta);
 nu pot coexista versiuni statice şi ne-statice ale aceleiaşi funcţii
De fapt, funcţiile membre de tip static au o arie de aplicatibilitate destul de limitată. O
utilizare potrivită a acestora este iniţializarea datelor private de tip static, înainte de
crearea vreunui obiect al clasei respective.
Operatorul de specificare a domeniului

Operatorul :: este folosit la asocierea unui nume de clasă cu un nume de


membru pentru a transmite astfel compilatorului cărei clase aparţine acel membru. Dar
operatorul de specificare a domeniului (operator de rezoluţie) are şi o altă utilizare
asemănătoare : permite accesul la un nume dintr-un domeniu, dublat de un acelaşi
nume printr-o declarare locală.

//Cînd este creat primul obiect de acel tip, toate variabilele de tip
static sînt automat iniţializate cu zero.
//În cadrul unei clase, declararea unei variabile static nu
alocă memorie pentru aceasta. Din acest motiv, trebuie dată a
definire globală pentru membrii de tip static, în afara clasei,
folosind
//specificatorul de domeniu, pentru a preciza clasa de
apartenenţă.
#include "stdafx.h"
#using <mscorlib.dll>
#include <stdlib.h>
#include <iostream>
using namespace std;
class exemplu_static{
static int a; // aici e o variabila membra de tip static
int b; // aceasta nu e de tip static
public:
void seteaza(int i, int j) {a=i; b=j; }
void arata();
};

int exemplu_static::a; // iata si definirea globala


// pentru variabila de tip static
void exemplu_static::arata()
{
cout << "Acesta este a static: " << a;
cout << "\nAcesta este b ne-static: " << b;
cout << "\n";
}

main()
{
exemplu_static ob1, ob2; // doua obiecte de tipul clasei
// exemplu_static

ob1.seteaza(1,2); // a va fi 1, b va fi 2
ob1.arata(); // sa vedem daca e asa

ob2.seteaza(3,4); // acum setam in celalalt obiect, dar


// diferit
ob2.arata(); // si verificam

16
ob1.arata(); // dar vedem ca a s-a modificat si
// pentru ob1, firesc deoarece a este
// acelasi pentru ambele obiecte
return 0;
}
//Trebuie reţinut modul de acces la variabilele statice, atunci cînd
sînt accesate independent de obiecte: prin folosirea numelui clasei,
urmat de
//operatorul de rezoluţie şi apoi numele vaiabilei statice.
#include "stdafx.h"

#using <mscorlib.dll>

#include <stdlib.h>
#include <iostream>
using namespace std;
class comun{
public:
static int a; // static si public totodata
};

int comun::a; // iata si definirea variabilei statice

main()
{
// initializam variabila statica inainte de crearea
// vreunui obiect folosind operatorul ::
comun::a=789;
cout << "Valoarea initiala a lui a: " << comun::a <<"\n";
comun c1; // abia acum se creaza un obiect de tip comun
cout << "Valoarea lui a din c1: " << c1.a;

return 0;
}
//Exemplul următor ilustrează cum poate fi controlat accesul la o
astfel de resursă comună (care
//poate fi un fişier, un buffer partajat etc.):
#include "stdafx.h"
#using <mscorlib.dll>
#include <stdlib.h>
#include <iostream>
using namespace std;
class semafor{
static int resursa;
public:
int ocupa_resursa();
void elibereaza_resursa() {resursa=0; }
};

int semafor::resursa; // aceasta este variabila statica care


// marcheaza ocuparea
int semafor::ocupa_resursa()
{
if (resursa) return 0; // resursa ocupata
else {
resursa=1;
return 1; // resursa atribuita obiectului
// apelant
}
}

17
main()
{
semafor s1, s2; // doua obiecte de tip semafor
if(s1.ocupa_resursa())
cout << "Obiectul 1 a ocupat resursa.\n";
if(!s2.ocupa_resursa())
cout << "Obiectul 2 nu are acces la resursa.\n";
s1.elibereaza_resursa(); // eliberare resursa
if(s2.ocupa_resursa())
cout << "Obiectul 2 poate acum folosi resursa.\n";

return 0;
}
//Se observă că accesul la funcţia statică ocupa_resursa()
//este permis fie independent de vreun obiect, utilizînd numele
clasei şi operatorul de specificare
//a domeniului (operatorul de rezoluţie) fie în legătură
//cu un obiect (operatorul de apartenenţă cu punct).
#include "stdafx.h"
#using <mscorlib.dll>
#include <stdlib.h>
#include <iostream>
using namespace std;
class semafor{
static int resursa;
public:
static int ocupa_resursa();
void elibereaza_resursa() {resursa=0; }
};

int semafor::resursa; // aceasta este variabila statica


// care indica ocuparea
int semafor::ocupa_resursa()
{
if (resursa) return 0; // resursa ocupata
else {
resursa=1;
return 1; // resursa atribuita obiectului
// apelant
}
}

main()
{
semafor s1, s2; // doua obiecte de tip semafor
// in plus fata de programul precedent, ocupa_resursa()
// poate fi apelat independent de orice obiect
if(semafor::ocupa_resursa())
cout << "Obiectul 1 a ocupat resursa.\n";
if(!semafor::ocupa_resursa())
cout << "Obiectul 2 nu are acces la resursa.\n";
s1.elibereaza_resursa(); // eliberare resursa
if(s2.ocupa_resursa()) // se poate folosi si apelul
// cu obiect
cout << "Obiectul 2 poate acum folosi resursa.\n";

return 0;
}

18
Clase imbricate, clase locale
Se poate defini o clasă în interiorul altei clase. Procedînd astfel, se crează clase
imbricate. Deoarece o declarare a unei clase defineşte de fapt un domeniu de delimitare, ("de
influenţă", de valabilitate, potrivit principiului încapsulării), o clasă imbricată este validă doar
în interiorul clasei ce o conţine. Clasele imbricate sînt rareori folosite, deoarece moştenirea
oferă suficientă flexibilitate şi putere pentru a acoperi necesităţile care ar fi acoperite de
folosirea claselor imbricate.
Cînd declarăm o clasă în definirea unei funcţii, respectiva clasă este cunoscută doar acelei
funcţii. Nu putem să facem referiri la ea în afara funcţiei.
Există mai multe restricţii care se aplică acestui gen de clase :

 Toate funcţiile membre trebuie definite în interiorul declaraţiei clasei respective;


 Clasa locală nu poate să folosească sau să acceseze variabile locale ale funcţei în
care este declarată, cu excepţia variabilelor locale de tip static declarate în interiorul
funcţiei;
 În interiorul unei clase locale nu pot fi declarate variabile de tip static.

Din aceste motive, nu se folosesc prea des clase locale.


O clasă poate fi definită în interiorul unei funcţii, caz în care se numeşte clasă locală.
Transmiterea obiectelor către funcţii

Obiectele pot fi pasate către funcţii exact ca oricare alt tip de variabilă (de altfel,
această posibilitate a fost folosită la un exemplu anterior, care folosea o funcţie friend pentru
controlul accesului la o resursă comună). Obiectele sînt pasate funcţiilor prin utilizarea
mecanismului standard de apelare prin valoare, adică prin copiere. Aceasta ar implica de fapt
crearea unui alt obiect. În aceste circumstanţe, se pune întrebarea dacă la crearea acestei copii
mai este apelat constructorul, respectiv, dacă această copie este distrusă apoi cu destructorul
clasei. Răspunsul la această întrebare este interesant şi uşor de justificat : constructorul nu este
apelat la realizarea copiei pentru pasarea către funcţie, deoarece astfel valorile care dau
atributele obiectului (deci valorile variabilelor membre) ar fi iniţializate, iar noi dorim să
transmitem spre funcţia apelantă chiar starea curentă a obiectului. În schimb destructorul este
executat la încheierea funcţiei, întrucît copia folosită nu mai e necesară
Cînd un obiect este returnat de o funcţie, este creat automat un obiect temporar, care conţine
valoarea returnată. Acesta este de fapt obiectul returnat. După ce valoarea a fost returnată, acest
obiect temporar este distrus. Această distrugere poate avea uneori efecte secundare neaşteptate.
Astfel, dacă obiectul care este returnat are un destructor care eliberează memorie alocată
dinamic, acea memorie va fi eliberată chiar dacă obiectul care primeşte valoarea returnată încă
o mai foloseşte. Apariţia acestei probleme poate fi prevenită prin supraîncărcarea operatorului
de atribuire şi definirea constructorului de copii, amintit anterior.

Atribuirea obiectelor
Presupunînd că două obiecte sînt de acelaşi tip, se poate realiza operaţia de atribuire
între acestea. Aceasta determină copierea datelor obiectelor din membrul drept în datele
obiectului din membrul stîng al operaţiei de atribuire.

//O clasă poate fi definită în interiorul unei funcţii,


//caz în care se numeşte clasă locală.
#include "stdafx.h"
#using <mscorlib.dll>
#include <stdlib.h>

19
#include <iostream>
using namespace std;
void f();

main()
{
f();
// aici inca nu cunoastem clasa clas_local
return 0;
}
void f()
{
// aici definim clasa locala clas_local
class clas_local{
int i;
public:
void setare_i(int val) {i=val; }
int furniz_i() {return i; }
} ob; // si iata si un obiect de clasa respectiva
ob.setare_i(77);
cout << ob.furniz_i();
}
//Obiectele pot fi pasate către funcţii exact ca oricare
//alt tip de variabilă (de altfel, această posibilitate a
//fost folosită la un exemplu anterior, care folosea o
//funcţie friend pentru controlul accesului la o resursă
//comună). Obiectele sînt pasate funcţiilor prin utilizarea
mecanismului standard de apelare prin valoare, adică prin copiere.

#include "stdafx.h"
#using <mscorlib.dll>
#include <stdlib.h>
#include <iostream>
using namespace std;

class ex_apel{
int i;
public:
ex_apel(int );
~ex_apel();
void set_i(int val) {i=val;}
int ret_i() {return i;}
};

ex_apel::ex_apel(int init)
{
i=init;
cout << "Construirea pentru " << i << "\n";
}
ex_apel::~ex_apel()
{
cout << "Distrugerea pentru " << i << "\n";
}

void f(ex_apel );

main()
{
ex_apel ex1(1); // un obiect de tip ex_apel
f(ex1); // aici, apel de functie cu parametru obiect
cout << "Valoarea i din main : " << ex1.ret_i() << "\n";

20
return 0;
}

void f(ex_apel ex)


{
ex.set_i(2); // setam pe alta valoare
cout <<"Valoarea i din functie : " << ex.ret_i() << "\n";
}
//O funcţie poate returna un obiect
//în modulul de program apelant
#include "stdafx.h"
#using <mscorlib.dll>
#include <stdlib.h>
#include <iostream>
using namespace std;
class retur_ob{
int i;
public:
void set_i(int val) {i=val;}
int ret_i() {return i;}
};

retur_ob f(); //prototipul unei functii care returneaza un


// obiect

main()
{
retur_ob o; // se creaza un obiect

o=f(); // obiectul dobindeste valoarea returnata de


// functie
cout << o.ret_i() << "\n";
return 0;
}

retur_ob f()
{
retur_ob interior; // obiect din functie
interior.set_i(1); // setam ca sa ne convingem ca e
// transmis in afara
return interior; // si returnam un obiect
}
//Sa se prezinte atribuirea a doua obiecte
#include "stdafx.h"
#using <mscorlib.dll>
#include <stdlib.h>
#include <iostream>
using namespace std;
class atribuire{
int i;
public:
void set_i(int val) {i=val; }
int ret_i() {return i; }
};

main()
{
atribuire a1, a2; // cele doua obiecte

a1.set_i(33); // setam i pentru primul obiect


a2=a1; // atribuirea

21
cout << "Valoarea i din a2 : " << a2.ret_i() << "\n";
return 0;
}
//sa se defineasca o functie in 3 feluri
//adica se supraincarca
#include "stdafx.h"
#using <mscorlib.dll>
#include <stdlib.h>
#include <iostream>
using namespace std;
// aici definim functia noastra in trei feluri

int abs(int );
double abs(double );
long abs(long );

// acum vine programul principal

main()
{
cout << abs(-10) << "\n";
cout << abs(-22.5) << "\n";
cout << abs(-5L) << "\n";

return 0;
}

// iar aici definim cele trei functii (diferite)

int abs(int i)
{
cout << "ABS pentru intregi\n";
return i<0 ? -i : i ;
}

double abs(double d)
{
cout << "ABS pentru double\n";
return d<0 ? -d : d ;
}

long abs(long l)
{
cout << "ABS pentru intregi lungi\n";
return l<0 ? -l : l ;
}

//Cu ajutorul constructorilor si destructorilor


//sa se implementeze notiunea de stiva
#include "stdafx.h"
#using <mscorlib.dll>
#include <stdlib.h>
#include <iostream>
using namespace std;
#define SIZE 100

// intii definim clasa


class stiva {
int stiv[SIZE];
int virf_stiva;
public:

22
stiva(); // constructor
~stiva(); // destructor
void pune(int );
int scoate();
};

// urmeaza definitiile functiilor membre

// functia constructor
stiva::stiva(){
virf_stiva=0;
cout << "In regula, stiva este initializata\n";
}

// functia destructor
stiva::~stiva()
{
cout << "In regula, stiva e distrusa\n";
}

// celelalte functii membre


void stiva::pune(int i){
if(virf_stiva==SIZE) {
cout << "Stiva este plina\n";
return;
}
stiv[virf_stiva]=i;
virf_stiva++;
}

int stiva::scoate(){
if (virf_stiva==0) {
cout << "Depasire inferioara\n";
return 0;
}
virf_stiva--;
return stiv[virf_stiva];
}

// Programul principal
main()
{
stiva stiv1, stiv2; // crearea a doua obiecte de tip stiva
stiv1.pune(1); // punem ceva in stive
stiv2.pune(2);
stiv1.pune(3);
stiv2.pune(4);

cout << stiv1.scoate() << " "; // acum scoatem din stive
si
cout << stiv1.scoate() << " "; // afisam
cout << stiv2.scoate() << " ";
cout << stiv2.scoate() << "\n ";

return 0; // gata
}

// Exercitiul 11.3.1.txt
// Acest program testeaza clasa Fraction prin initializarea unei
serii de

23
// fractii si afisarea fiecarei valori.
//
// Nota: Desi eu sugerez sa folositi combinatia copy-si-paste pentru
a genera
// o parte a acestui cod, folosirea unor matrice este probabil cea
mai buna
// modalitate de a economisi timpul. Dar aceasta abordare este
lasata pentru
// dumneavoastra, ca un alt exercitiu.

#include "stdafx.h"

#using <mscorlib.dll>

#include <stdlib.h>
#include <iostream>
using namespace std;

class Fraction {
private:
int num, den;
public:
void set(int n, int d) {num = n; den = d; normalize();}
int get_num() {return num;}
int get_den() {return den;}
private:
void normalize();
int gcf(int a, int b);
int lcm(int a, int b);
};

int main() {

Fraction f1, f2, f3, f4, f5;

f1.set(2, 2); // 2/2


f2.set(4, 8); // 4/8
f3.set(-9, -9); // -9/-9
f4.set(10, 50); // 10/50
f5.set(100, 25); // 100/25

cout << f1.get_num() << "/" << f1.get_den() << endl;


cout << f2.get_num() << "/" << f2.get_den() << endl;
cout << f3.get_num() << "/" << f3.get_den() << endl;
cout << f4.get_num() << "/" << f4.get_den() << endl;
cout << f5.get_num() << "/" << f5.get_den() << endl;
}

void Fraction::normalize(){

if (den == 0 || num == 0) {
num = 0;
den = 1;

24
}

if (den < 0) {
num *= -1;
den *= -1;
}

int n = gcf(num, den);


num = num / n;
den = den / n;
}

int Fraction::gcf(int a, int b) {


if (a % b == 0)
return abs(b);
else
return gcf(b, a % b);
}

int Fraction::lcm(int a, int b){


return (a / gcf(a, b)) * b;
}

// Folosind POO sa se creze clasa punct GEOMETRIC si sa se afiseze

#include "stdafx.h"

#using <mscorlib.dll>

#include <iostream>
using namespace std;

class Point {
private:
int x, y;
public:
void set(int new_x, int new_y);
int get_x();
int get_y();
};

int main() {
Point pt1, pt2;

pt1.set(10, 20);
cout << "pt1 is " << pt1.get_x();
cout << ", " << pt1.get_y() << endl;
pt2.set(-5, -25);
cout << "pt2 is " << pt2.get_x();
cout << ", " << pt2.get_y() << endl;
return 0;
}

25
void Point::set(int new_x, int new_y) {
if (new_x < 0)
new_x *= -1;
if (new_y < 0)
new_y *= -1;
x = new_x;
y = new_y;
}

int Point::get_x() {
return x;
}

int Point::get_y() {
return y;
}

// Exercitiul 11.1.1.txt
// Acest program declara o clasa Point ca in scriptul din point1.cpp,
// dar, in aceasta versiune, este stabilita o limita superioara
pentru
// valorile din membrii x si y.

#include "stdafx.h"

#using <mscorlib.dll>

#include <iostream>
using namespace std;

class Point {
private: // Data members (private)
int x, y;
public: // Member functions
void set(int new_x, int new_y);
int get_x();
int get_y();
};

int main() {
Point pt1, pt2;

pt1.set(10, 20);
cout << "pt1 is " << pt1.get_x();
cout << ", " << pt1.get_y() << endl;
pt2.set(-5, -25);
cout << "pt2 is " << pt2.get_x();
cout << ", " << pt2.get_y() << endl;

pt1.set(200, 500);
cout << "pt1 is " << pt1.get_x();
cout << ", " << pt1.get_y() << endl;

return 0;
}

void Point::set(int new_x, int new_y) {


if (new_x < 0)

26
new_x *= -1;
if (new_y < 0)
new_y *= -1;
if (new_x > 100)
new_x = 100;
if (new_y > 100)
new_y = 100;
x = new_x;
y = new_y;
}

int Point::get_x() {
return x;
}

int Point::get_y() {
return y;
}
//sa se scrie doua functii care seteaza punctul X si Punctul Y
diferite
#include "stdafx.h"

#using <mscorlib.dll>

#include <iostream>
using namespace std;

class Point {
private:
int x, y;
public:
void set(int new_x, int new_y);
int get_x();
int get_y();
void set_x(int new_x);
void set_y(int new_y);
};

int main() {
Point pt1, pt2;

pt1.set(10, 20);
cout << "pt1 is " << pt1.get_x();
cout << ", " << pt1.get_y() << endl;
pt2.set(-5, -25);
cout << "pt2 is " << pt2.get_x();
cout << ", " << pt2.get_y() << endl;

pt1.set_x(-50);
pt1.set_y(-10);
cout << "pt1 is " << pt1.get_x();
cout << ", " << pt1.get_y() << endl;
return 0;
}

void Point::set_x(int new_x) {


if (new_x < 0)

27
new_x *= -1;
x = new_x;
}

void Point::set_y(int new_y) {


if (new_y < 0)
new_y *= -1;
y = new_y;
}

void Point::set(int new_x, int new_y) {


if (new_x < 0)
new_x *= -1;
if (new_y < 0)
new_y *= -1;
x = new_x;
y = new_y;
}

int Point::get_x() {
return x;
}

int Point::get_y() {
return y;
}
// Sa se adune doua fractii cu POO

#include "stdafx.h"

#using <mscorlib.dll>

#include <iostream>
using namespace std;

class Fraction {
private:
int num, den;
public:
void set(int n, int d)
{num = n; den = d; normalize();}
int get_num() {return num;}
int get_den() {return den;}
Fraction add(Fraction other);
Fraction mult(Fraction other);
private:
void normalize();
int gcf(int a, int b);
int lcm(int a, int b);
};

int main() {
Fraction fract1, fract2, fract3;

fract1.set(1, 2);
fract2.set(1, 3);
fract3 = fract1.add(fract2);
cout << "1/2 plus 1/3 = ";
cout << fract3.get_num() << "/" << fract3.get_den();

28
}

void Fraction::normalize(){

if (den == 0 || num == 0) {
num = 0;
den = 1;
}

if (den < 0) {
num *= -1;
den *= -1;
}

int n = gcf(num, den);


num = num / n;
den = den / n;
}

int Fraction::gcf(int a, int b) {


if (a % b == 0)
return abs(b);
else
return gcf(b, a % b);
}

int Fraction::lcm(int a, int b){


return (a / gcf(a, b)) * b;
}

Fraction Fraction::add(Fraction other) {


Fraction fract;
int lcd = lcm(den, other.den);
int quot1 = lcd/den;
int quot2 = lcd/other.den;
fract.set(num * quot1 + other.num * quot2, lcd);
return fract;
}

Fraction Fraction::mult(Fraction other) {


Fraction fract;
fract.set(num * other.num, den * other.den);
return fract;
}
// Exercitiul 11.4.1.txt
// Acest program aduna oricare doua fractii introduse si
// afiseaza rezultatele.
#include "stdafx.h"

#using <mscorlib.dll>

#include <iostream>

29
using namespace std;

class Fraction {
private:
int num, den;
public:
void set(int n, int d)
{num = n; den = d; normalize();}
int get_num() {return num;}
int get_den() {return den;}
Fraction add(Fraction other);
Fraction mult(Fraction other);
private:
void normalize();
int gcf(int a, int b);
int lcm(int a, int b);
};

int main() {
Fraction fract1, fract2, fract3;
int n, d;

cout << "Enter numerator for first fraction: ";


cin >> n;
cout << "Enter denominator for first fraction: ";
cin >> d;
fract1.set(n, d);
cout << "Enter numerator for second fraction: ";
cin >> n;
cout << "Enter denominator for second fraction: ";
cin >> d;
fract2.set(n, d);

fract3 = fract1.add(fract2);

cout << "The sum of the fraction is: ";


cout << fract3.get_num() << "/" << fract3.get_den() << endl;
}

void Fraction::normalize(){

if (den == 0 || num == 0) {
num = 0;
den = 1;
}

if (den < 0) {
num *= -1;
den *= -1;
}

int n = gcf(num, den);


num = num / n;
den = den / n;
}

30
int Fraction::gcf(int a, int b) {
if (a % b == 0)
return abs(b);
else
return gcf(b, a % b);
}

int Fraction::lcm(int a, int b){


return (a / gcf(a, b)) * b;
}

Fraction Fraction::add(Fraction other) {


Fraction fract;
int lcd = lcm(den, other.den);
int quot1 = lcd/den;
int quot2 = lcd/other.den;
fract.set(num * quot1 + other.num * quot2, lcd);
return fract;
}

Fraction Fraction::mult(Fraction other) {


Fraction fract;
fract.set(num * other.num, den * other.den);
return fract;
}
// Exercitiul 11.4.2.txt
// Acest program inmulteste oricare doua fractii introduse si
// afiseaza rezultatele.
#include "stdafx.h"

#using <mscorlib.dll>
#include <iostream>
using namespace std;

class Fraction {
private:
int num, den;
public:
void set(int n, int d)
{num = n; den = d; normalize();}
int get_num() {return num;}
int get_den() {return den;}
Fraction add(Fraction other);
Fraction mult(Fraction other);

private:
void normalize();
int gcf(int a, int b);
int lcm(int a, int b);
};

int main() {
Fraction fract1, fract2, fract3;
int n, d;

cout << "Enter numerator for first fraction: ";


cin >> n;

31
cout << "Enter denominator for first fraction: ";
cin >> d;
fract1.set(n, d);
cout << "Enter numerator for second fraction: ";
cin >> n;
cout << "Enter denominator for second fraction: ";
cin >> d;
fract2.set(n, d);

fract3 = fract1.mult(fract2);
cout << "fract1 * fract2 is: ";
cout << fract3.get_num() << "/" << fract3.get_den() << endl;

void Fraction::normalize(){

if (den == 0 || num == 0) {
num = 0;
den = 1;
}

if (den < 0) {
num *= -1;
den *= -1;
}

int n = gcf(num, den);


num = num / n;
den = den / n;
}

int Fraction::gcf(int a, int b) {


if (a % b == 0)
return abs(b);
else
return gcf(b, a % b);
}

//
int Fraction::lcm(int a, int b){
return (a / gcf(a, b)) * b;
}

Fraction Fraction::add(Fraction other) {


Fraction fract;
int lcd = lcm(den, other.den);
int quot1 = lcd/den;
int quot2 = lcd/other.den;
fract.set(num * quot1 + other.num * quot2, lcd);
return fract;
}

Fraction Fraction::mult(Fraction other) {


Fraction fract;
fract.set(num * other.num, den * other.den);

32
return fract;
}

// Exercitiul 11.4.3.txt
// Acest program extinde clasa Point prezentata in capitolul 11
// prin includerea unei functii noi, Point::add.

#include<stdafx.h>
#include <iostream>
using namespace std;

class Point {
private:
int x, y;
public:
void set(int new_x, int new_y);
int get_x();
int get_y();
Point add(Point other);
};

int main() {
Point pt1, pt2, pt3;

pt1.set(10, 20);
cout << "pt1 is " << pt1.get_x();
cout << ", " << pt1.get_y() << endl;
pt2.set(-5, -25);
cout << "pt2 is " << pt2.get_x();
cout << ", " << pt2.get_y() << endl;

pt3 = pt1.add(pt2);
pt2.set(-5, -25);
cout << "pt3 is " << pt3.get_x();
cout << ", " << pt3.get_y() << endl;

return 0;
}

void Point::set(int new_x, int new_y) {


if (new_x < 0)
new_x *= -1;
if (new_y < 0)
new_y *= -1;
x = new_x;
y = new_y;
}

int Point::get_x() {
return x;
}

int Point::get_y() {
return y;
}

33
Point Point::add(Point other) {
Point new_pt;
int new_x = x + other.get_x();
int new_y = y + other.get_y();
new_pt.set(new_x, new_y);
return new_pt;
}

#include "stdafx.h"

// Exercitiul 11.4.4.txt
// Acest program include functiile sub (scadere) si div (impartire)
// pentru clasa Fraction.

#include <iostream>
using namespace std;

class Fraction {
private:
int num, den;
public:
void set(int n, int d)
{num = n; den = d; normalize();}
int get_num() {return num;}
int get_den() {return den;}
Fraction add(Fraction other);
Fraction mult(Fraction other);
Fraction sub(Fraction other);
Fraction div(Fraction other);

private:
void normalize();
int gcf(int a, int b);
int lcm(int a, int b);
};

int main() {
Fraction fract1, fract2, fract3;
int n, d;

cout << "Enter numerator for first fraction: ";


cin >> n;
cout << "Enter denominator for first fraction: ";
cin >> d;
fract1.set(n, d);
cout << "Enter numerator for second fraction: ";
cin >> n;
cout << "Enter denominator for second fraction: ";
cin >> d;
fract2.set(n, d);

fract3 = fract1.sub(fract2); // TEST NEW SUB FUNCTION


cout << "fract1 - fract2 is: ";
cout << fract3.get_num() << "/" << fract3.get_den() << endl;

fract3 = fract1.div(fract2); // TEST NEW DIV FUNCTION


cout << "fract1 / fract2 is: ";
cout << fract3.get_num() << "/" << fract3.get_den() << endl;

34
}

void Fraction::normalize(){

// Handle cases involving 0

if (den == 0 || num == 0) {
num = 0;
den = 1;
}

if (den < 0) {
num *= -1;
den *= -1;
}

int n = gcf(num, den);


num = num / n;
den = den / n;
}

//
int Fraction::gcf(int a, int b) {
if (a % b == 0)
return abs(b);
else
return gcf(b, a % b);
}

int Fraction::lcm(int a, int b){


return (a / gcf(a, b)) * b;
}

Fraction Fraction::add(Fraction other) {


Fraction fract;
int lcd = lcm(den, other.den);
int quot1 = lcd/den;
int quot2 = lcd/other.den;
fract.set(num * quot1 + other.num * quot2, lcd);
return fract;
}

Fraction Fraction::mult(Fraction other) {


Fraction fract;
fract.set(num * other.num, den * other.den);
return fract;
}

Fraction Fraction::sub(Fraction other) {


Fraction fract;

35
fract.set(-1 * other.num, other.den);
return add(fract);
}

Fraction Fraction::div(Fraction other) {


Fraction fract;
fract.set(num * other.den, den * other.num);
return fract;
}

CONSTRUCTORI IN VISUAL C++.NET


Funcţii constructor cu parametri

Se pot transmite parametri către funcţiile constructor. Aceştia sînt folosiţi mai ales
pentru iniţializarea unui obiect la creare. Pentru aceasta, trebuie pur şi simplu adăugaţi
parametri în modul în care acest lucru se realizează pentru orice funcţie. Iar parametrii transmişi
vor fi folosiţi pentru iniţilizarea obiectului.
Funcţiile constructor cu parametri sînt utile deoarece permit evitarea unui aple suplimentar
pentru iniţializarea valorilor unor variabile din obiecte.
Un caz special al funcţiilor constructor cu parametri este constituit de funcţiile
constructor cu un parametru. În acest caz, există o altă cale de a-i pasa acestuia o valoare
iniţială. În cazul cînd constructorul are un singur argument, se poate folosi pur şi simplu forma
de iniţializare "naturală". Compilatorul va atribui automat valoarea din dreapta semnului "=",
parametrului constructorului.
Despre execuţia constructorilor şi destructorilor

Un constructor este de obicei apelat la declararea obiectului, iar un destructor este


apelat cînd este distrus obiectul. Însă momentele exacte ale acestor acţiuni trebuie puţin
comentate deoarece se întîlnesc situaţii diverse :

1. O funcţie constructor de obiecte este executată cînd este întîlnită instrucţiunea de


declarare a obiectului. Mai mult, cînd două sau mai multe obiecte sînt declarate în aceeaşi
instrucţiune, constructorii sînt apelaţi în ordinea în care sînt ele întîlnite, de la stînga la dreapta.
Funcţiile destructor pentru obiecte locale sînt executate în ordine inversă faţă de cele
constructor.

2. Funcţiile constructor pentru obiecte globale sînt executate înaintea lui main(). Constructorii
globali din acelaşi fişier sînt executaţi în rodinea în care au fost întîlniţi, de la stînga la dreapta
şi de sus în jos. E greu de depistat ordinea execuţiei constructorilor împrăştiaţi în mai multe
fişiere. Destructorii globali se execută în ordine inversă, după încheierea funcţiei main().

//sa se adauge niste contructori pentru clasa PUNCT

#include "stdafx.h"

#include <iostream>
using namespace std;

class Point {
private:
int x, y;
public: // Constructori
Point() {set(0,0);};
Point(int new_x, int new_y) {set(new_x, new_y);}

36
// functii membre

void set(int new_x, int new_y);


int get_x();
int get_y();
};

int main() {
Point pt1, pt2;
Point pt3(5, 10);

cout << "The value of pt1 is ";


cout << pt1.get_x() << ", ";
cout << pt1.get_y() << endl;

cout << "The value of pt3 is ";


cout << pt3.get_x() << ", ";
cout << pt3.get_y() << endl;
return 0;
}

void Point::set(int new_x, int new_y) {


if (new_x < 0)
new_x *= -1;
if (new_y < 0)
new_y *= -1;
x = new_x;
y = new_y;
}

int Point::get_x() {
return x;
}

int Point::get_y() {
return y;
}
// Exercitiul 12.1.1.txt
// Aceasta versiune a lui point2.cpp raporteaza ce constructori vor
fi utilizati.

//sa se defineasca doi constructori ,unul pentru un mesaj altul cu


parametrii pentru alt mesaj

#include "stdafx.h"

#include <iostream>
using namespace std;

class Point {
private: // Data members (private)
int x, y;
public: // Constructors
Point()
{set(0,0); cout << "Using default constructor" << endl; }

Point(int new_x, int new_y)


{set(new_x, new_y); cout << "Using (int, int) constructor" <<
endl;}

37
// Other member functions

void set(int new_x, int new_y);


int get_x();
int get_y();
};

int main() {
Point pt1, pt2;
Point pt3(5, 10);

cout << "The value of pt1 is ";


cout << pt1.get_x() << ", ";
cout << pt1.get_y() << endl;

cout << "The value of pt3 is ";


cout << pt3.get_x() << ", ";
cout << pt3.get_y() << endl;
return 0;
}

void Point::set(int new_x, int new_y) {


if (new_x < 0)
new_x *= -1;
if (new_y < 0)
new_y *= -1;
x = new_x;
y = new_y;
}

int Point::get_x() {
return x;
}

int Point::get_y() {
return y;
}

// Exercitiul 12.1.2.txt
// Aceasta versiune a programului Point2 adauga constructorul
Point(int)
// (un constructor care preia un singur argument intreg).

#include "stdafx.h"

#include <iostream>
using namespace std;

class Point {
private: // Data members (private)
int x, y;
public: // Constructors
Point() {set(0, 0);}
Point(int new_x, int new_y) {set(new_x, new_y);}

Point(int n) {set(n, 0);} // NEW CONSTRUCTOR

// Other member functions

void set(int new_x, int new_y);

38
int get_x();
int get_y();
};

int main() {
Point pt1(6); // THIS TESTS THE NEW CONSTRUCTOR
Point pt2;
Point pt3(5, 10);

cout << "The value of pt1 is ";


cout << pt1.get_x() << ", ";
cout << pt1.get_y() << endl;

cout << "The value of pt3 is ";


cout << pt3.get_x() << ", ";
cout << pt3.get_y() << endl;
return 0;
}

void Point::set(int new_x, int new_y) {


if (new_x < 0)
new_x *= -1;
if (new_y < 0)
new_y *= -1;
x = new_x;
y = new_y;
}

int Point::get_x() {
return x;
}

int Point::get_y() {
return y;
}
//sa se defineasca constructori pentru clasa Fractie

#include "stdafx.h"

#include <iostream>
using namespace std;

class Fraction {
private:
int num, den; // Numerator and denominator.
public:
Fraction() {set(0, 1);}
Fraction(int n, int d) {set(n, d);}

void set(int n, int d) {num = n; den = d; normalize();}


int get_num() {return num;}
int get_den() {return den;}
Fraction add(Fraction other);
Fraction mult(Fraction other);
private:
void normalize(); // Put fraction into standard form.
int gcf(int a, int b); // Greatest Common Factor.
int lcm(int a, int b); // Lowest Common Denominator.
};

int main() {

39
Fraction f1, f2;
Fraction f3(1, 2);

cout << "The value of f1 is ";


cout << f1.get_num() << "/";
cout << f1.get_den() << endl;

cout << "The value of f3 is ";


cout << f3.get_num() << "/";
cout << f3.get_den() << endl;
return 0;
}

void Fraction::normalize(){

// Handle cases involving 0

if (den == 0 || num == 0) {
num = 0;
den = 1;
}

// Put neg. sign in numerator only.

if (den < 0) {
num *= -1;
den *= -1;
}

// Factor out GCF from numerator and denominator.

int n = gcf(num, den);


num = num / n;
den = den / n;
}

// Greatest Common Factor


//
int Fraction::gcf(int a, int b) {
if (a % b == 0)
return abs(b);
else
return gcf(b, a % b);
}

// Lowest Common Multiple


//
int Fraction::lcm(int a, int b){
return (a / gcf(a, b)) * b;
}

Fraction Fraction::add(Fraction other) {


Fraction fract;
int lcd = lcm(den, other.den);
int quot1 = lcd/den;
int quot2 = lcd/other.den;
fract.set(num * quot1 + other.num * quot2, lcd);
fract.normalize();
return fract;
}

40
Fraction Fraction::mult(Fraction other) {
Fraction fract;
fract.set(num * other.num, den * other.den);
fract.normalize();
return fract;
}

// Exercitiul 12.2.1.txt
// Aceasta versiune a clasei Fraction revizuieste constructorul
prestabilit
// astfel incat sa stabileasca direct valoarea membrilor de date num
si den.
//
// Apelarea functiei normalize nu este strict necesara, dar este
putin mai precaut,
// in particular, daca functia normalize va fi rescrisa de subclase
// (cum se va explca mai tarziu in acest capitol).
//
// Setarea directa a functiilor num si den este putin mai eficienta,
deoarece ocoleste
// ap
#include "stdafx.h"
elarea unei functii; totusi, aceasta este un foarte mica
imbunatatire.

#include <iostream>
using namespace std;

class Fraction {
private:
int num, den; // Numerator and denominator.
public:
Fraction() {num = 0; den = 0; normalize();} // <-- NEW VERSION

Fraction(int n, int d) {set(n, d);}

void set(int n, int d) {num = n; den = d; normalize();}


int get_num() {return num;}
int get_den() {return den;}
Fraction add(Fraction other);
Fraction mult(Fraction other);
private:
void normalize(); // Put fraction into standard form.
int gcf(int a, int b); // Greatest Common Factor.
int lcm(int a, int b); // Lowest Common Denominator.
};

int main() {
Fraction f1, f2;
Fraction f3(1, 2);

cout << "The value of f1 is ";


cout << f1.get_num() << "/";
cout << f1.get_den() << endl;

cout << "The value of f3 is ";


cout << f3.get_num() << "/";
cout << f3.get_den() << endl;

41
return 0;
}

void Fraction::normalize(){

// Handle cases involving 0

if (den == 0 || num == 0) {
num = 0;
den = 1;
}

// Put neg. sign in numerator only.

if (den < 0) {
num *= -1;
den *= -1;
}

// Factor out GCF from numerator and denominator.

int n = gcf(num, den);


num = num / n;
den = den / n;
}

// Greatest Common Factor


//
int Fraction::gcf(int a, int b) {
if (a % b == 0)
return abs(b);
else
return gcf(b, a % b);
}

// Lowest Common Multiple


//
int Fraction::lcm(int a, int b){
return (a / gcf(a, b)) * b;
}

Fraction Fraction::add(Fraction other) {


Fraction fract;
int lcd = lcm(den, other.den);
int quot1 = lcd/den;
int quot2 = lcd/other.den;
fract.set(num * quot1 + other.num * quot2, lcd);
fract.normalize();
return fract;
}

Fraction Fraction::mult(Fraction other) {


Fraction fract;
fract.set(num * other.num, den * other.den);
fract.normalize();
return fract;
}

// Exercitiul 12.2.2.txt
// Aceasta versiune a clasei Fraction adauga un constructor
Fraction(int),

42
// care creeaza o fractie de forma n/1.

#include "stdafx.h"

#include <iostream>
using namespace std;

class Fraction {
private:
int num, den; // Numerator and denominator.
public:
Fraction() {set(0, 1);}
Fraction(int n, int d) {set(n, d);}
Fraction(int n) {set(n, 1);} // NEW CONSTRUCTOR ADDED

void set(int n, int d) {num = n; den = d; normalize();}


int get_num() {return num;}
int get_den() {return den;}
Fraction add(Fraction other);
Fraction mult(Fraction other);
private:
void normalize(); // Put fraction into standard form.
int gcf(int a, int b); // Greatest Common Factor.
int lcm(int a, int b); // Lowest Common Denominator.
};

int main() {
Fraction f1(6); // THIS TESTS THE NEW CONSTRUCTOR
Fraction f2;
Fraction f3(1, 2);

cout << "The value of f1 is ";


cout << f1.get_num() << "/";
cout << f1.get_den() << endl;

cout << "The value of f3 is ";


cout << f3.get_num() << "/";
cout << f3.get_den() << endl;
return 0;
}

void Fraction::normalize(){

// Handle cases involving 0

if (den == 0 || num == 0) {
num = 0;
den = 1;
}

// Put neg. sign in numerator only.

if (den < 0) {
num *= -1;
den *= -1;
}

// Factor out GCF from numerator and denominator.

int n = gcf(num, den);

43
num = num / n;
den = den / n;
}

// Greatest Common Factor


//
int Fraction::gcf(int a, int b) {
if (a % b == 0)
return abs(b);
else
return gcf(b, a % b);
}

// Lowest Common Multiple


//
int Fraction::lcm(int a, int b){
return (a / gcf(a, b)) * b;
}

Fraction Fraction::add(Fraction other) {


Fraction fract;
int lcd = lcm(den, other.den);
int quot1 = lcd/den;
int quot2 = lcd/other.den;
fract.set(num * quot1 + other.num * quot2, lcd);
fract.normalize();
return fract;
}

Fraction Fraction::mult(Fraction other) {


Fraction fract;
fract.set(num * other.num, den * other.den);
fract.normalize();
return fract;
}
CONSTRUCTOR DE COPIERE
// SA se defineasca un constructor de COPIERE

#include "stdafx.h"

#include <iostream>
using namespace std;

class Fraction {
private:
int num, den; // Numerator and denominator.
public:
Fraction() {set(0, 1);}
Fraction(int n, int d) {set(n, d);}
Fraction(Fraction const &src);

void set(int n, int d) {num = n; den = d; normalize();}


int get_num() {return num;}
int get_den() {return den;}
Fraction add(Fraction other);
Fraction mult(Fraction other);
private:
void normalize(); // Put fraction into standard form.
int gcf(int a, int b); // Greatest Common Factor.

44
int lcm(int a, int b); // Lowest Common Denominator.
};

int main() {
Fraction f1(3, 4);
Fraction f2(f1);

Fraction f3 = f1.add(f2);

cout << "The value of f3 is ";


cout << f3.get_num() << "/";
cout << f3.get_den() << endl;
return 0;
}

// ---------------------------------------------------
// FRACTION CLASS FUNCTIONS

Fraction::Fraction(Fraction const &src) {


cout << "Now executing copy constructor." << endl;
num = src.num;
den = src.den;
}

// Normalize: put fraction into a standard form, unique


// for each mathematically different value.
//
void Fraction::normalize(){

// Handle cases involving 0

if (den == 0 || num == 0) {
num = 0;
den = 1;
}

// Put neg. sign in numerator only.

if (den < 0) {
num *= -1;
den *= -1;
}

// Factor out GCF from numerator and denominator.

int n = gcf(num, den);


num = num / n;
den = den / n;
}

// Greatest Common Factor


//
int Fraction::gcf(int a, int b) {
if (a % b == 0)
return abs(b);
else
return gcf(b, a % b);
}

// Lowest Common Multiple


//

45
int Fraction::lcm(int a, int b){
return (a / gcf(a, b)) * b;
}

Fraction Fraction::add(Fraction other) {


Fraction fract;
int lcd = lcm(den, other.den);
int quot1 = lcd/den;
int quot2 = lcd/other.den;
fract.set(num * quot1 + other.num * quot2, lcd);
fract.normalize();
return fract;
}

Fraction Fraction::mult(Fraction other) {


Fraction fract;
fract.set(num * other.num, den * other.den);
fract.normalize();
return fract;
}

// Exercitiul 12.3.1.txt
// Aceasta versiune a programului fract4.cpp rescrie un constructor
de copiere
// sub forma unei functii in linie.
#include "stdafx.h"

#include <iostream>
using namespace std;

class Fraction {
private:
int num, den; // Numerator and denominator.
public:
Fraction() {set(0, 1);}
Fraction(int n, int d) {set(n, d);}

Fraction(Fraction const &src) {num = src.num; den = src.den;}

void set(int n, int d) {num = n; den = d; normalize();}


int get_num() {return num;}
int get_den() {return den;}
Fraction add(Fraction other);
Fraction mult(Fraction other);
private:
void normalize(); // Put fraction into standard form.
int gcf(int a, int b); // Greatest Common Factor.
int lcm(int a, int b); // Lowest Common Denominator.
};

int main() {
Fraction f1(3, 4);
Fraction f2(f1);

Fraction f3 = f1.add(f2);

46
cout << "The value of f3 is ";
cout << f3.get_num() << "/";
cout << f3.get_den() << endl;
return 0;
}

void Fraction::normalize(){

// Handle cases involving 0

if (den == 0 || num == 0) {
num = 0;
den = 1;
}

// Put neg. sign in numerator only.

if (den < 0) {
num *= -1;
den *= -1;
}

// Factor out GCF from numerator and denominator.

int n = gcf(num, den);


num = num / n;
den = den / n;
}

// Greatest Common Factor


//
int Fraction::gcf(int a, int b) {
if (a % b == 0)
return abs(b);
else
return gcf(b, a % b);
}

// Lowest Common Multiple


//
int Fraction::lcm(int a, int b){
return (a / gcf(a, b)) * b;
}

Fraction Fraction::add(Fraction other) {


Fraction fract;
int lcd = lcm(den, other.den);
int quot1 = lcd/den;
int quot2 = lcd/other.den;
fract.set(num * quot1 + other.num * quot2, lcd);
fract.normalize();
return fract;
}

Fraction Fraction::mult(Fraction other) {


Fraction fract;
fract.set(num * other.num, den * other.den);
fract.normalize();
return fract;
}

47
// Exercitiul 12.3.2.txt
// Aceasta versiune a programului fract4.cpp revizuieste
constructorul de copiere
// astfel incat sa faca apel la functia set in loc sa stabileasca
direct valoarea
// membrilor de date num si den.
//
// Aceasta abordare isi pierde putin din eficienta fata de situatia
cand constructorul
// este setat ca o functie in linie. Cu toate acestea, el apeleaza
functia normalize,
// lucru care nu este neaparat necesar. (Cand copiati o fractie
existenta, puteti
// presupune ca valoarea sa a fost deja normalizata.)

#include "stdafx.h"

#include <iostream>
using namespace std;

class Fraction {
private:
int num, den; // Numerator and denominator.
public:
Fraction() {set(0, 1);}
Fraction(int n, int d) {set(n, d);}
Fraction(Fraction const &src);

void set(int n, int d) {num = n; den = d; normalize();}


int get_num() {return num;}
int get_den() {return den;}
Fraction add(Fraction other);
Fraction mult(Fraction other);
private:
void normalize(); // Put fraction into standard form.
int gcf(int a, int b); // Greatest Common Factor.
int lcm(int a, int b); // Lowest Common Denominator.
};

int main() {
Fraction f1(3, 4);
Fraction f2(f1);

Fraction f3 = f1.add(f2);

cout << "The value of f3 is ";


cout << f3.get_num() << "/";
cout << f3.get_den() << endl;
return 0;
}

// ---------------------------------------------------
// FRACTION CLASS FUNCTIONS

Fraction::Fraction(Fraction const &src) {


cout << "Now executing copy constructor." << endl;
set(src.num, src.den);
normalize();
}

48
void Fraction::normalize(){

// Handle cases involving 0

if (den == 0 || num == 0) {
num = 0;
den = 1;
}

// Put neg. sign in numerator only.

if (den < 0) {
num *= -1;
den *= -1;
}

// Factor out GCF from numerator and denominator.

int n = gcf(num, den);


num = num / n;
den = den / n;
}

// Greatest Common Factor


//
int Fraction::gcf(int a, int b) {
if (a % b == 0)
return abs(b);
else
return gcf(b, a % b);
}

// Lowest Common Multiple


//
int Fraction::lcm(int a, int b){
return (a / gcf(a, b)) * b;
}

Fraction Fraction::add(Fraction other) {


Fraction fract;
int lcd = lcm(den, other.den);
int quot1 = lcd/den;
int quot2 = lcd/other.den;
fract.set(num * quot1 + other.num * quot2, lcd);
fract.normalize();
return fract;
}

Fraction Fraction::mult(Fraction other) {


Fraction fract;
fract.set(num * other.num, den * other.den);
fract.normalize();
return fract;
}

SUPRAINCARCAREA(DEFINIREA NOUA) A
OPERATORILOR

49
//Sa se defineasca operatorul care aduna coordonatele unor puncte
//si care face diferenta intre coordonatele unor puncte

#include "stdafx.h"

#include <iostream>
using namespace std;

class Point {
private: // Data members (private)
int x, y;
public: // Constructors
Point() {};
Point(int new_x, int new_y) {set(new_x, new_y);}
Point(const Point &src) {set(src.x, src.y);}

// Operations

Point add(const Point &pt);


Point sub(const Point &pt);
Point operator+(const Point &pt) {return add(pt);}
Point operator-(const Point &pt) {return sub(pt);}

// Other member functions

void set(int new_x, int new_y);


int get_x() const {return x;}
int get_y() const {return y;}
};

int main() {

Point point1(20, 20);


Point point2(0, 5);
Point point3(-10, 25);
Point point4 = point1 + point2 + point3;

cout << "The point is " << point4.get_x();


cout << ", " << point4.get_y() << "." << endl;

return 0;
}

void Point::set(int new_x, int new_y) {


if (new_x < 0)
new_x *= -1;
if (new_y < 0)
new_y *= -1;
x = new_x;
y = new_y;
}

Point Point::add(const Point &pt) {


Point new_pt;
new_pt.x = x + pt.x;
new_pt.y = y + pt.y;
return new_pt;
}

50
Point Point::sub(const Point &pt) {
Point new_pt;
new_pt.x = x - pt.x;
new_pt.y = y - pt.y;
return new_pt;
}

// Exercitiul 13.1.1.txt
// Aceasta versiune a programului point3.cpp indica de cate ori sunt
apelati
// constructorul predefinit si constructorul de copiere.

#include "stdafx.h"

#include <iostream>
using namespace std;

class Point {
private: // Data members (private)
int x, y;
public: // Constructors
Point()
{set(0, 0); cout << "Inside default constructor" << endl; } //
ALTERED CODE

Point(int new_x, int new_y) {set(new_x, new_y);}

Point(const Point &src)


{set(src.x, src.y); cout << "Inside copy constructor" << endl;
// ALTERED CODE
}

// Operations

Point add(const Point &pt);


Point sub(const Point &pt);
Point operator+(const Point &pt) {return add(pt);}
Point operator-(const Point &pt) {return sub(pt);}

// Other member functions

void set(int new_x, int new_y);


int get_x() const {return x;}
int get_y() const {return y;}
};

int main() {

Point point1(20, 20);


Point point2(0, 5);
Point point3(-10, 25);
Point point4 = point1 + point2 + point3;

cout << "The point is " << point4.get_x();


cout << ", " << point4.get_y() << "." << endl;

return 0;
}

51
void Point::set(int new_x, int new_y) {
if (new_x < 0)
new_x *= -1;
if (new_y < 0)
new_y *= -1;
x = new_x;
y = new_y;
}

Point Point::add(const Point &pt) {


Point new_pt;
new_pt.x = x + pt.x;
new_pt.y = y + pt.y;
return new_pt;
}

Point Point::sub(const Point &pt) {


Point new_pt;
new_pt.x = x - pt.x;
new_pt.y = y - pt.y;
return new_pt;
}

// Exercitiul 13.1.2.txt
// Acest program creeaza si testeaza operatii de inmultire (*) intre
// clasa Point si tipul de date int.

#include "stdafx.h"

#include <iostream>
using namespace std;

class Point {
private: // Data members (private)
int x, y;
public: // Constructors
Point() {};
Point(int new_x, int new_y) {set(new_x, new_y);}
Point(const Point &src) {set(src.x, src.y);}

// Operations

Point add(const Point &pt);


Point sub(const Point &pt);
Point operator+(const Point &pt) {return add(pt);}
Point operator-(const Point &pt) {return sub(pt);}

friend Point operator*(const Point &pt, const int &n); // FRIEND


DECL.
friend Point operator*(const int &n, const Point &pt);

// Other member functions

void set(int new_x, int new_y);


int get_x() const {return x;}
int get_y() const {return y;}
};

int main() {

52
Point point1(20, 20);
Point point2 = point1 * 4; // TEST
MULTIPLICATION WITH INT'S

cout << "The point is " << point2.get_x();


cout << ", " << point2.get_y() << "." << endl;

return 0;
}

void Point::set(int new_x, int new_y) {


if (new_x < 0)
new_x *= -1;
if (new_y < 0)
new_y *= -1;
x = new_x;
y = new_y;
}

Point Point::add(const Point &pt) {


Point new_pt;
new_pt.x = x + pt.x;
new_pt.y = y + pt.y;
return new_pt;
}

Point Point::sub(const Point &pt) {


Point new_pt;
new_pt.x = x - pt.x;
new_pt.y = y - pt.y;
return new_pt;
}

// POINT CLASS FRIEND FUNCTIIONS

Point operator*(const Point &pt, const int &n) {


Point new_pt;
new_pt.set(pt.x * n, pt.y * n);
return new_pt;
}

Point operator*(const int &n, const Point &pt) {


Point new_pt;
new_pt.set(pt.x * n, pt.y * n);
return new_pt;
}
//sa se defineasca operatori personalizati pentru
//lucrul cu fractiile

#include "stdafx.h"

#include <iostream>
using namespace std;

class Fraction {
private:
int num, den; // Numerator and denominator.
public:
Fraction() {set(0, 1);}

53
Fraction(int n, int d) {set(n, d);}
Fraction(const Fraction &src);

void set(int n, int d) {num = n; den = d; normalize();}


int get_num() const {return num;}
int get_den() const {return den;}
Fraction add(const Fraction &other);
Fraction mult(const Fraction &other);
Fraction operator+(const Fraction &other)
{return add(other);}
Fraction operator*(const Fraction &other)
{return mult(other);}

private:
void normalize(); // Put fraction into standard form.
int gcf(int a, int b); // Greatest Common Factor.
int lcm(int a, int b); // Lowest Common Denominator.
};

int main() {
Fraction f1(1, 2);
Fraction f2(1, 3);

Fraction f3 = f1 + f2;

cout << "1/2 + 1/3 = ";


cout << f3.get_num() << "/";
cout << f3.get_den() << "." << endl;
return 0;
}

// ---------------------------------------------------
// FRACTION CLASS FUNCTIONS

Fraction::Fraction(Fraction const &src) {


num = src.num;
den = src.den;
}

// Normalize: put fraction into a standard form, unique


// for each mathematically different value.
//
void Fraction::normalize(){

// Handle cases involving 0

if (den == 0 || num == 0) {
num = 0;
den = 1;
}

// Put neg. sign in numerator only.

if (den < 0) {
num *= -1;
den *= -1;
}

// Factor out GCF from numerator and denominator.

int n = gcf(num, den);

54
num = num / n;
den = den / n;
}

// Greatest Common Factor


//
int Fraction::gcf(int a, int b) {
if (a % b == 0)
return abs(b);
else
return gcf(b, a % b);
}

// Lowest Common Multiple


//
int Fraction::lcm(int a, int b){
return (a / gcf(a, b)) * b;
}

Fraction Fraction::add(const Fraction &other) {


Fraction fract;
int lcd = lcm(den, other.den);
int quot1 = lcd/den;
int quot2 = lcd/other.den;
fract.set(num * quot1 + other.num * quot2, lcd);
fract.normalize();
return fract;
}

Fraction Fraction::mult(const Fraction &other) {


Fraction fract;
fract.set(num * other.num, den * other.den);
fract.normalize();
return fract;
}
// Exercitiul 13.2.1.txt
// Acest program solicita o serie de valori fractionare, le aduna pe
toate
// si afiseaza suma.

#include "stdafx.h"

#include <iostream>
using namespace std;

class Fraction {
private:
int num, den; // Numerator and denominator.
public:
Fraction() {set(0, 1);}
Fraction(int n, int d) {set(n, d);}
Fraction(const Fraction &src);

void set(int n, int d) {num = n; den = d; normalize();}


int get_num() const {return num;}
int get_den() const {return den;}
Fraction add(const Fraction &other);
Fraction mult(const Fraction &other);
Fraction operator+(const Fraction &other)
{return add(other);}

55
Fraction operator*(const Fraction &other)
{return mult(other);}

private:
void normalize(); // Put fraction into standard form.
int gcf(int a, int b); // Greatest Common Factor.
int lcm(int a, int b); // Lowest Common Denominator.
};

int main() {
Fraction fraction_sum(0, 0);
Fraction fraction_new;
int numerator, denominator;

while (1) { // MAIN LOOP


cout << "Enter numerator (0 to exit): ";
cin >> numerator;
if (numerator == 0) // BREAK ON ZERO
break;
cout << "Enter denominator: ";
cin >> denominator;
fraction_new.set(numerator, denominator);
fraction_sum = fraction_sum + fraction_new;
}
cout << "The sum of the fractions is: ";
cout << fraction_sum.get_num() << "/";
cout << fraction_sum.get_den() << "." << endl;

return 0;
}

// ---------------------------------------------------
// FRACTION CLASS FUNCTIONS

Fraction::Fraction(Fraction const &src) {


num = src.num;
den = src.den;
}

// Normalize: put fraction into a standard form, unique


// for each mathematically different value.
//
void Fraction::normalize(){

// Handle cases involving 0

if (den == 0 || num == 0) {
num = 0;
den = 1;
}

// Put neg. sign in numerator only.

if (den < 0) {
num *= -1;
den *= -1;
}

// Factor out GCF from numerator and denominator.

int n = gcf(num, den);

56
num = num / n;
den = den / n;
}

// Greatest Common Factor


//
int Fraction::gcf(int a, int b) {
if (a % b == 0)
return abs(b);
else
return gcf(b, a % b);
}

// Lowest Common Multiple


//
int Fraction::lcm(int a, int b){
return (a / gcf(a, b)) * b;
}

Fraction Fraction::add(const Fraction &other) {


Fraction fract;
int lcd = lcm(den, other.den);
int quot1 = lcd/den;
int quot2 = lcd/other.den;
fract.set(num * quot1 + other.num * quot2, lcd);
fract.normalize();
return fract;
}

Fraction Fraction::mult(const Fraction &other) {


Fraction fract;
fract.set(num * other.num, den * other.den);
fract.normalize();
return fract;
}

//Sa se defineasca mai multe functii diferite pentru fiecare operator


#include "stdafx.h"
#include <iostream>
using namespace std;

class Fraction {
private:
int num, den; // Numerator and denominator.
public:
Fraction() {set(0, 1);}
Fraction(int n, int d) {set(n, d);}
Fraction(int n) {set(n, 1);}
Fraction(const Fraction &src);

void set(int n, int d) {num = n; den = d; normalize();}


int get_num() const {return num;}
int get_den() const {return den;}
Fraction add(const Fraction &other);
Fraction mult(const Fraction &other);
Fraction operator+(const Fraction &other)
{return add(other);}
Fraction operator*(const Fraction &other)
{return mult(other);}
int operator==(const Fraction &other);
friend ostream &operator<<(ostream &os, Fraction &fr);

57
private:
void normalize(); // Put fraction into standard form.
int gcf(int a, int b); // Greatest Common Factor.
int lcm(int a, int b); // Lowest Common Denominator.
};

int main() {
Fraction f1(1, 2);
Fraction f2(1, 3);

Fraction f3 = f1 + f2 + 1;

cout << "1/2 + 1/3 + 1 = " << f3 << endl;


return 0;
}

// ---------------------------------------------------
// FRACTION CLASS FUNCTIONS

Fraction::Fraction(Fraction const &src) {


num = src.num;
den = src.den;
}

// Normalize: put fraction into a standard form, unique


// for each mathematically different value.
//
void Fraction::normalize(){

// Handle cases involving 0

if (den == 0 || num == 0) {
num = 0;
den = 1;
}

// Put neg. sign in numerator only.

if (den < 0) {
num *= -1;
den *= -1;
}

// Factor out GCF from numerator and denominator.

int n = gcf(num, den);


num = num / n;
den = den / n;
}

// Greatest Common Factor


//
int Fraction::gcf(int a, int b) {
if (a % b == 0)
return abs(b);
else
return gcf(b, a % b);
}

// Lowest Common Multiple

58
//
int Fraction::lcm(int a, int b){
return (a / gcf(a, b)) * b;
}

Fraction Fraction::add(const Fraction &other) {


Fraction fract;
int lcd = lcm(den, other.den);
int quot1 = lcd/den;
int quot2 = lcd/other.den;
fract.set(num * quot1 + other.num * quot2, lcd);
fract.normalize();
return fract;
}

Fraction Fraction::mult(const Fraction &other) {


Fraction fract;
fract.set(num * other.num, den * other.den);
fract.normalize();
return fract;
}

int Fraction::operator==(const Fraction &other) {


return (num == other.num && den == other.den);
}

// ---------------------------------------------------
// FRACTION CLASS FRIEND FUNCTION

ostream &operator<<(ostream &os, Fraction &fr) {


os << fr.num << "/" << fr.den;
return os;
}

// Exercitiul 13.3.1.txt
// Acest exemplu revizuieste programul din exemplul 13.3 astfel incat
afiseaza
// iesirea din clasa Fraction in format (num, den).

#include "stdafx.h"

#include <iostream>
using namespace std;

class Fraction {
private:
int num, den; // Numerator and denominator.
public:
Fraction() {set(0, 1);}
Fraction(int n, int d) {set(n, d);}
Fraction(int n) {set(n, 1);}
Fraction(const Fraction &src);

void set(int n, int d) {num = n; den = d; normalize();}


int get_num() const {return num;}
int get_den() const {return den;}
Fraction add(const Fraction &other);
Fraction mult(const Fraction &other);
Fraction operator+(const Fraction &other)
{return add(other);}

59
Fraction operator*(const Fraction &other)
{return mult(other);}
int operator==(const Fraction &other);
friend ostream &operator<<(ostream &os, Fraction &fr);

private:
void normalize(); // Put fraction into standard form.
int gcf(int a, int b); // Greatest Common Factor.
int lcm(int a, int b); // Lowest Common Denominator.
};

int main() {
Fraction f1(1, 2);
Fraction f2(1, 3);

Fraction f3 = f1 + f2 + 1;

cout << "1/2 + 1/3 + 1 = " << f3 << endl;


return 0;
}

// ---------------------------------------------------
// FRACTION CLASS FUNCTIONS

Fraction::Fraction(Fraction const &src) {


num = src.num;
den = src.den;
}

// Normalize: put fraction into a standard form, unique


// for each mathematically different value.
//
void Fraction::normalize(){

// Handle cases involving 0

if (den == 0 || num == 0) {
num = 0;
den = 1;
}

// Put neg. sign in numerator only.

if (den < 0) {
num *= -1;
den *= -1;
}

// Factor out GCF from numerator and denominator.

int n = gcf(num, den);


num = num / n;
den = den / n;
}

// Greatest Common Factor


//
int Fraction::gcf(int a, int b) {
if (a % b == 0)
return abs(b);
else

60
return gcf(b, a % b);
}

// Lowest Common Multiple


//
int Fraction::lcm(int a, int b){
return (a / gcf(a, b)) * b;
}

Fraction Fraction::add(const Fraction &other) {


Fraction fract;
int lcd = lcm(den, other.den);
int quot1 = lcd/den;
int quot2 = lcd/other.den;
fract.set(num * quot1 + other.num * quot2, lcd);
fract.normalize();
return fract;
}

Fraction Fraction::mult(const Fraction &other) {


Fraction fract;
fract.set(num * other.num, den * other.den);
fract.normalize();
return fract;
}

int Fraction::operator==(const Fraction &other) {


return (num == other.num && den == other.den);
}

// ---------------------------------------------------
// FRACTION CLASS FRIEND FUNCTION -- THIS IS THE REVISED FUNCTION
CODE

ostream &operator<<(ostream &os, Fraction &fr) {


os << "(" << fr.num << ", " << fr.den << ")";
return os;
}
// Exercitiul 13.3.2.txt
// Acest program adauga functiile operator> si operator<
// in programul fract7.cpp si apoi testeaza aceste functii.

#include "stdafx.h"

#include <iostream>
using namespace std;

class Fraction {
private:
int num, den; // Numerator and denominator.
public:
Fraction() {set(0, 1);}
Fraction(int n, int d) {set(n, d);}
Fraction(int n) {set(n, 1);}
Fraction(const Fraction &src);

void set(int n, int d) {num = n; den = d; normalize();}


int get_num() const {return num;}
int get_den() const {return den;}
Fraction add(const Fraction &other);

61
Fraction mult(const Fraction &other);
Fraction operator+(const Fraction &other)
{return add(other);}
Fraction operator*(const Fraction &other)
{return mult(other);}
int operator==(const Fraction &other);
int operator>(const Fraction &other); // DECLARATION OF >
FNCT.
int operator<(const Fraction &other); // DECLARATION OF <
FNCT.
friend ostream &operator<<(ostream &os, Fraction &fr);

private:
void normalize(); // Put fraction into standard form.
int gcf(int a, int b); // Greatest Common Factor.
int lcm(int a, int b); // Lowest Common Denominator.
};

int main() {
Fraction f1(1, 2);
Fraction f2(1, 3);

if (f1 > f2) // TEST > FUNCTION


cout << "1/2 > 1/3" << endl;
else
cout << "1/2 is not > 1/3" << endl;

if (f1 < f2) // TEST < FUNCTION


cout << "1/2 < 1/3" << endl;
else
cout << "1/2 is not < 1/3" << endl;

return 0;
}

// ---------------------------------------------------
// FRACTION CLASS FUNCTIONS

Fraction::Fraction(Fraction const &src) {


num = src.num;
den = src.den;
}

// Normalize: put fraction into a standard form, unique


// for each mathematically different value.
//
void Fraction::normalize(){

// Handle cases involving 0

if (den == 0 || num == 0) {
num = 0;
den = 1;
}

// Put neg. sign in numerator only.

if (den < 0) {
num *= -1;
den *= -1;

62
}

// Factor out GCF from numerator and denominator.

int n = gcf(num, den);


num = num / n;
den = den / n;
}

// Greatest Common Factor


//
int Fraction::gcf(int a, int b) {
if (a % b == 0)
return abs(b);
else
return gcf(b, a % b);
}

// Lowest Common Multiple


//
int Fraction::lcm(int a, int b){
return (a / gcf(a, b)) * b;
}

Fraction Fraction::add(const Fraction &other) {


Fraction fract;
int lcd = lcm(den, other.den);
int quot1 = lcd/den;
int quot2 = lcd/other.den;
fract.set(num * quot1 + other.num * quot2, lcd);
fract.normalize();
return fract;
}

Fraction Fraction::mult(const Fraction &other) {


Fraction fract;
fract.set(num * other.num, den * other.den);
fract.normalize();
return fract;
}

int Fraction::operator==(const Fraction &other) {


return (num == other.num && den == other.den);
}

int Fraction::operator>(const Fraction &other) { // NEW FNCT.


DEFINITION
return ((num * other.den) > (den * other.num));
}

int Fraction::operator<(const Fraction &other) { // NEW FNCT.


DEFINITION
return ((num * other.den) < (den * other.num));
}

// ---------------------------------------------------
// FRACTION CLASS FRIEND FUNCTION

ostream &operator<<(ostream &os, Fraction &fr) {


os << fr.num << "/" << fr.den;
return os;

63
}

FUNCTII PRIETEN
// Exercitiul 13.3.3.txt
// Acest program adauga functia operator<< la clasa Point.
// Functia este declarata ca prieten al clasei.

#include "stdafx.h"

#include <iostream>
using namespace std;

class Point {
private: // Data members (private)
int x, y;
public: // Constructors
Point() {};
Point(int new_x, int new_y) {set(new_x, new_y);}
Point(const Point &src) {set(src.x, src.y);}

// Operations

Point add(const Point &pt);


Point sub(const Point &pt);
Point operator+(const Point &pt) {return add(pt);}
Point operator-(const Point &pt) {return sub(pt);}

friend ostream &operator<<(ostream &os, Point &pt); // FUNCTION


DECLARED

// Other member functions

void set(int new_x, int new_y);


int get_x() const {return x;}
int get_y() const {return y;}
};

int main() {

Point point1(20, 20);


Point point2(0, 5);
Point point3(-10, 25);
Point point4 = point1 + point2 + point3;

cout << "The point is " << point4 << endl; // TEST OPERATOR<<
FUNCT.

return 0;
}

void Point::set(int new_x, int new_y) {


if (new_x < 0)
new_x *= -1;
if (new_y < 0)
new_y *= -1;
x = new_x;
y = new_y;
}

64
Point Point::add(const Point &pt) {
Point new_pt;
new_pt.x = x + pt.x;
new_pt.y = y + pt.y;
return new_pt;
}

Point Point::sub(const Point &pt) {


Point new_pt;
new_pt.x = x - pt.x;
new_pt.y = y - pt.y;
return new_pt;
}

ostream &operator<<(ostream &os, Point &pt) { // FUNCTION DEFINITION


os << "(" << pt.x << ", " << pt.y << ")";
return os;
}

ALOCAREA DINAMICA A MEMORIEI


Pointeri către obiecte

Exact aşa cum pot fi definiţi pointeri către alte tipuri de variabile, pot exista şi
pointeri către obiecte. Când se doreşte acces la membrii unei clase cu ajutorul unui
pointer către un obiect, se foloseşte operatorul săgeată ( -> ) în locul operatorului
punct. Se poate atribui unui pointer adresa unui membru public al unui obiect şi apoi
să aveţi acces la acel membru folosind pointerul.
Se poate elimina orice nepotrivire folosind un modelator (adică o conversie de tip) dar
astfel se trece peste mecanismul de verificare a tipului din C++. În C++, se realizează
o verificare mai strictă a tipurilor decît în C (unde se poate atribui orice tip de valoare
oricărui pointer), atunci cînd sînt implicaţi pointeri.
Pointerul this
Cînd este apelată o funcţie membru, i se pasează automat un argument implicit
(care nu apare în lista de parametri), care este un pointer către obiectul care a generat
apelul (adică obiectul care a invocat funcţia : obiect.functie(...) ). Acest pointer este
numit this.
La membrii unei clase se poate dobîndi acces direct din cadrul unei funcţii membru,
fără nici un specificator de obiect sau de clasă.
Există două restricţii legate de this :

 Funcţiile friend nu sînt membri ai clasei, deci nu le sînt pasaţi pointeri this.
 Funcţiile membre de tip static nu au nici ele un pointer this.

Pointeri către tipuri derivate

În general, un pointer de un anumit tip nu poate indica decît spre un obiect de


acelaşi tip. Totuşi, o excepţie care se referă la clase derivate (şi care este necesară în
anumite situaţii !) este admisă. Astfel, un pointer din clasa de bază poate fi folosit ca
un pointer spre oricare obiect al oricărei clase derivate din clasa de bază. Atenţie,
reciproca nu este adevărată ! Un pointer din clasa derivată nu poate indica spre un
obiect din clasa de bază. Mai mult, chiar dacă se poate folosi un pointer din clasa de
bază pentru a indica un obiect derivat, putem avea acces doar la membrii de tipul

65
derivat, care au fost importaţi din clasa de bază. Deci nu putem avea acces prin
intermediul acelui pointer, la membrii adăugaţi de clasa derivată (şi justificarea este
logică şi imediată: un pointer din clasa de bază nu poate indica ceva ce nu are de unde
să cunoască - adică membrii adăugaţi - în schimb, poate indica acei membri care sînt
de fapt tot din clasa de bază - dar care sînt moşteniţi, “cunoscuţi” de clasa derivată).
Acest inconvenient poate fi rezolvat prin convertirea unui pointer din clasa de bază
într-unul derivat şi astfel se dobîndeşte acces la întreaga clasă derivată.
Pointeri către membrii clasei

C++ permite generarea unui tip special de pointeri care indică generic spre un
membru al unei clase, nu către un anumit exemplar al acelui membru dintr-un obiect.
Acest tip de pointer este numit pointer către un membru al clasei sau pe scurt pointer
la membru. Acesta nu e acelaşi lucru cu un pointer normal. Un astfel de pointer
asigură doar o poziţionare (un offset) într-un obiect din clasa membrului, unde poate
fi găsit acel membru. Deoarece pointerii la membri nu sînt chiar pointeri în înţelesul
pe care îl cunoaştem, nu li se pot aplica operatorii obişnuiţi în operarea cu pointeri
normali: . şi -> . Pentru a avea acces la membrul unei clase prin intremediul unui
pointer de acest tip, vor trebui folosiţi operatorii speciali pentru pointeri la membri: .*
şi ->* .
Referinţe

O referinţă este un pointer implicit, care acţionează ca un alt nume al unui


obiect. O utilizare importantă a referinţei este crearea funcţiilor care folosesc
trasnmiterea parametrului prin referinţă şi nu metoda implicită din C++, apelarea prin
valoare.
În C, pentru a apela prin referinţă, trebuie pasată funcţiei, explicit, adresa
argumentului. Iată mai jos un program care foloseşte această modalitate ne-
automatizată pentru a transmite un parametru (un întreg) prin referinţă.
Transmiterea referinţelor către obiecte

S-a văzut în precedentul capitol că atunci cînd un obiect este transmis unei funcţii ca
argument, se face automat o copie a acelui obiect, ba mai mult, cînd este realizată
acea copie, nici nu e apelat constructorul obişnuit al clasei (fiind realizată doar o copie
exactă, fără iniţializările şi celelalte operaţii conţinute în constructor). În schimb, la
terminarea funcţiei, este apelat destructorul copiei. Dacă nu se doreşte apelarea
destructorului, se poate realiza transmiterea obiectului prin referinţă. La acest gen de
apel, aşa cum ne şi aşteptăm, nu se face o copie a obiectului ci manipularea datelor are
loc chiar în obiectul transmis ca referinţă. Deci destructorul nu mai este apelat la
terminarea funcţiei.
Referinţe independente

Cea mai obişnuită utilizare pentru referinţe este pasarea argumentelor prin
referinţă şi obţinerea valorii returnate de funcţie. Totuşi, pot fi declarate şi referinţe ca
simple variabile. Acest tip de referinţă se numeşte referinţă independentă.
La crearea unei referinţe independente, tot ceea ce se creează este de fapt un al
doilea nume pentru o variabilă. Toate variabilele de tip referinţă independentă trebuie
iniţializate la creare.
Restricţii

66
Există mai multe restricţii care se aplică referinţelor :

 O referinţă nu se poate referi la altă referinţă (adică nu poate fi obţinută adresa unei
referinţe).
 Nu pot fi create matrice de referinţe.
 Nu se poate crea un pointer spre o referinţă.
 O referinţă nu se poate defini pentru un cîmp de biţi.
 O variabilă de tip referinţă trebuie iniţializată la declarare, dar nu trebuie
iniţializată dacă este membru al unei clase, parametru de funcţie sau valoare
returnată.
 Referinţele nule nu sînt permise.

Observaţie

Următorul aspect este de fapt legat de stilul de programare. Unii programatori


adoptă nişte convenţii legate de asocierea operatorilor * sau &. Astfel :

int& p; // asociat cu tipul


int &p; // asociat cu variabila

cele două declaraţii sînt echivalente funcţional dar asocierea cu numele tipului reflectă
dorinţa programatorilor ca limbajul C++ să pună la dispoziţie un pointer distinct
pentru tip (tipul întreg, în cazul nostru). Dar sintaxa din C++nu presupune
distributivitatea operatorilor într-o listă de parametri. De aceea se pot uşor formula
declaraţii greşite. Astfel :

int* a,b;

creează un pointer de tip întreg, nu doi, aşa cum am fi dorit. Într-adevăr, în C++ ,
operatorii * sau & se referă doar la următoarea variabilă şi nu la tipul variabilelor,
deşi văzînd linia-sursă am fi tentaţi să credem că atît a cît şi b ar fi pointeri. Această
confuzie este frecventă chiar şi la programatorii buni, cînd nu sînt atenţi.
Din punctul de vedere al compilatorului, este indiferentă forma de scriere de
mai sus. Pentru evitarea confuziilor, se recomandă asocierea operatorilor de mai sus
totuşi cu variabilele.
Operatorii de alocare dinamică din C++

În limbajul C, după cum se cunoaşte, alocarea dinamică a memoriei este


realizată de funcţiile malloc() şi free(). Pentru compatibilitatea de jos în sus, funcţiile
acestea de alocare dinamică sînt valabile şi în C++, dar există aici nişte funcţii proprii,
de fapt nişte operatori, mai uşor de folosit : new şi delete. Utilizarea acestora prezintă
numeroase avantaje.
Operatorul new returnează un pointer către memoria alocată. Ca şi malloc(),
new alocă memorie din zona heap (zona de memorie liberă). Dacă nu există memorie
suficientă pentru alocare, se returnează un pointer nul. Operatorul delete eliberează
memoria alocată anterior prin utilizarea operatorului new. Formele generale de
utilizare ale celor doi operatori sînt:

p_var=new tip;

67
...
delete p_var;

Aici, p_var este o variabilă de tip pointer care primeşte un pointer spre
memoria care este suficient de mare pentru a păstra un element de tipul tip.
Operatorul delete trebuie să fie folosit doar cu un pointer valid, alocat deja prin new.
Folosirea oricărui alt tip de pointer cu delete duce la un rezultat imprevizibil şi
aproape sigur determină probleme, chiar căderea sistemului.
Deşi new şi delete efectuează funcţii similare cu malloc() şi free(), ele
prezintă mai multe avantaje:

 new alocă automat memorie suficientă pentru păstrarea obiectelor de tipul


specificat (deci nu trebuie determinată mărimea obiectului cu sizeof).
Astfel, se elimină orice posibilitate de eroare în privinţa spaţiului de
alocare.
 new returnează automat un pointer de tipul specificat, nefiind necesară
utilizarea unui modelator de tip, aşa cum trebuia făcut cu malloc().
 Atît new cît şi delete pot fi supraîncărcaţi, permiţînd crearea unui sistem
de alocare propriu.
 Prin utilizarea new memoria poate fi iniţializată cu o valoare cunoscută,
scriind în instrucţiunea cu new o valoare după numele tipului :

p_var=new tip_var (initializator)


Alocare de memorie pentru obiecte

Obiectelor li se poate aloca memorie dinamic, folosind new. Cînd se face


această alocare, se creează un obiect şi se returnează un pointer către el. Obiectul creat
dinamic se comportă ca oricare alt obiect. Cînd este creat, este apelat constructorul,
dacă există. Atunci cînd este apelat delete (deci se eliberează memoria ocupată), se
execută funcţia destructor, dacă există.
Parametrii funcţiei constructor ai obiectului sînt specificaţi după numele tipului, la fel
ca şi pentru alte tipuri de iniţializări.
Se poate face alocare dinamică şi pentru matricele de obiecte, dar deoarece
matricele de obiecte create cu new nu pot fi iniţializate, trebuie să ne asigurăm că una
din funcţiile constructor este neapărat fără parametri. În caz contrar, compilatorul va
semnala eroare (deoarece ar trebui să iniţializeze un obiect care nu permite
iniţializarea). Prin folosirea delete [], funcţia destructor va fi apelată pentru fiecare
obiect al clasei.

//Sa se aloce memorie pentru un vector,sa se faca media elementelor


sale
//si sa se elibereze memoria ocupata

#include "stdafx.h"

#include <iostream>
using namespace std;

int main() {
int sum = 0;
int n;
int *p;

68
cout << "Enter number of items: ";
cin >> n;

p = new int[n]; // Allocate n integers

for (int i = 0; i < n; i++) {


cout << "Enter item #" << i << ": ";
cin >> p[i];
sum += p[i];
}
cout << "Here are the items: ";
for (int i = 0; i < n; i++)
cout << p[i] << ", ";
cout << endl;
cout << "The total is: " << sum << endl;
cout << "The average is: " << (double) sum / n << endl;

delete [] p; // Release n integers.

return 0;
}

// Exercitiul 14.1.1.txt
// Acest program modifica scriptul new1.cpp pentru a utiliza un tip
double
// ca tip de baza pentru o matrice in loc de tipul int.
//se aloca memorie pentru elementele unei matrice cu elemete reale

#include "stdafx.h"

#include <iostream>
using namespace std;

int main() {
double sum = 0.0; // TYPE ALTERED TO DOUBLE HERE.
int n;
double *p; // TYPE OF *p ALTERED TO DOUBLE.

cout << "Enter number of items: ";


cin >> n;

p = new double[n]; // Allocate n double -- ALTERED FROM INT

for (int i = 0; i < n; i++) {


cout << "Enter item #" << i << ": ";
cin >> p[i];
sum += p[i];
}
cout << "Here are the items: ";
for (int i = 0; i < n; i++)
cout << p[i] << ", ";
cout << endl;
cout << "The total is: " << sum << endl;
cout << "The average is: " << sum / n << endl;

delete [] p; // Release n integers.

return 0;
}
//sa se creeze un analizator lexical adica un program care

69
//sa imparta in cuvinte o fraza dandu-se un delimitator
//ex:3/4/5 =>
// 3
// 4
// 5

#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;

class StringParser {
private:
int pos;
char *input_str;
char *delimiters;

public:
StringParser(char *inp, char *delim)
{input_str = inp; delimiters = delim; pos = 0; }

StringParser(char *inp)
{input_str = inp; delimiters = ","; pos = 0; }

char *get();
int get_int();
int more() {return input_str[pos] != '\0'; }
void reset() {pos = 0;}
};

int main() {
char input_str[100];
char *p;

cout << "Enter input line: ";


cin.getline(input_str, 99);

StringParser parser(input_str, "/,");

while (parser.more()) {
p = parser.get(); // Get ptr to newly allocated string
cout << p << endl; // Print it
delete [] p; // Release string memory
}

return 0;
}

// ----------------------------------------------
// STRINGPARSER CLASS FUNCTIONS

char *StringParser::get() {
int j = 0;
char *new_str;
new_str = new char[100];

// Consume initial delimiters, if any

while (strchr(delimiters, input_str[pos]))


pos++;

70
// Copy characters as long as none is a
// delimiter or end of string (null)

while (input_str[pos] != '\0' &&


! strchr(delimiters, input_str[pos]))

new_str[j++] = input_str[pos++];

// Finish string and return it.

new_str[j] = '\0';
return new_str;
}

int StringParser::get_int() {
char *p = get();
return atoi(p);
delete [] p;
}

// Exercitiul 14.2.1.txt
// Acest program modifica scrptul din exemplul 14.2 astfel incat sa
utilizeze
// functia membru get_int() (limitind intrarile la valori intregi)
in locul
// functiei get().

#include "stdafx.h"

#include <iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;

class StringParser {
private:
int pos;
char *input_str;
char *delimiters;

public:
StringParser(char *inp, char *delim)
{input_str = inp; delimiters = delim; pos = 0; }

StringParser(char *inp)
{input_str = inp; delimiters = ","; pos = 0; }

char *get();
int get_int();
int more() {return input_str[pos] != '\0'; }
void reset() {pos = 0;}
};

int main() {
char input_str[100];
int n; // USE INTEGER RATHER THAN CHAR* STRING

cout << "Enter input line: ";


cin.getline(input_str, 99);

71
StringParser parser(input_str, "/,");

while (parser.more()) {
n = parser.get_int(); // GET AN INTEGER FROM NEXT SUBSTRING
cout << n << endl; // Print it
}

return 0;
}

// ----------------------------------------------
// STRINGPARSER CLASS FUNCTIONS

char *StringParser::get() {
int j = 0;
char *new_str;
new_str = new char[100];

// Consume initial delimiters, if any

while (strchr(delimiters, input_str[pos]))


pos++;

// Copy characters as long as none is a


// delimiter or end of string (null)

while (input_str[pos] != '\0' &&


! strchr(delimiters, input_str[pos]))

new_str[j++] = input_str[pos++];

// Finish string and return it.

new_str[j] = '\0';
return new_str;
}

int StringParser::get_int() {
char *p = get();
return atoi(p);
delete [] p;
}
// Copierea unui subsir intr-un sir prin alocare dinamica
#include "stdafx.h"

#include <iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;

class StringParser {
private:
int pos;
char *input_str;
char *delimiters;

public:
StringParser(char *inp, char *delim)
{input_str = inp; delimiters = delim; pos = 0; }

StringParser(char *inp)

72
{input_str = inp; delimiters = ","; pos = 0; }

char *get(char *dest); // ALTERED DECL. - INCLUDES DESTINATION


STRING
int get_int();
int more() {return input_str[pos] != '\0'; }
void reset() {pos = 0;}
};

int main() {
char input_str[100];
char substr[100]; // USES A STATIC STRING -- THIS SHOULD BE
LARGE
// ENOUGH TO CONTAIN ANY POSSIBLE
SUBSTRING.

cout << "Enter input line: ";


cin.getline(input_str, 99);

StringParser parser(input_str, "/,");

while (parser.more()) {
parser.get(substr); // GET NEXT SUBSTRING INTO THE STRING
VAR.
cout << substr << endl; // Print it
}

return 0;
}

// ----------------------------------------------
// STRINGPARSER CLASS FUNCTIONS

char *StringParser::get(char *dest) {


int j = 0;

// Consume initial delimiters, if any

while (strchr(delimiters, input_str[pos]))


pos++;

// Copy characters as long as none is a


// delimiter or end of string (null)

while (input_str[pos] != '\0' &&


! strchr(delimiters, input_str[pos]))

dest[j++] = input_str[pos++];

// Finish string and return it.

dest[j] = '\0';
return dest;
}

int StringParser::get_int() { // THIS FUNCTION MUST ALSO BE


REVISED, AS IT
char temp[256]; // CALLS THE GET FUNCTION.
get(temp);
return atoi(temp);
}

73
DESTRUCTORI SI CUVANTUL CHEIE this
//sa se creeze un destructor care scoate din memorie un sir de
caractere
#include "stdafx.h"

#include <iostream>
#include <string.h>
using namespace std;

class String {
private:
char *ptr;
public:
String();
String(char *s);
~String();

int operator==(const String &other);


operator char*() {return ptr;}
};

int main() {
String a("STRING 1");
String b("STRING 2");
cout << "The value of a is: " << endl;
cout << a << endl;
cout << "The value of b is: " << endl;
cout << b << endl;
}

// ----------------------------------
// STRING CLASS FUNCTIONS

String::String() {
ptr = new char[1];
ptr[0] = '\0';
}

String::String(char *s) {
int n = strlen(s);
ptr = new char[n + 1];
strcpy(ptr, s);
}

String::~String() {
delete [] ptr;
}

int String:: operator==(const String &other) {


return (strcmp(ptr, other.ptr) == 0);
}

// Exercitiul 15.1.1.txt
// Aceasta versiune a programului string1.cpp testeaza
// constructorul prestabilit String().

#include "stdafx.h"

74
#include <iostream>
#include <string.h>
using namespace std;

class String {
private:
char *ptr;
public:
String();
String(char *s);
~String();

int operator==(const String &other);


operator char*() {return ptr;}
};

int main() {
String a("STRING 1");
String b("STRING 2");
String c; // NEW OBJECT DECL.
cout << "The value of a is: " << endl;
cout << a << endl;
cout << "The value of b is: " << endl;
cout << b << endl;

// PRINT VALUE OF C BETWEEN BRACKETS:

cout << "The value of c is between these brackets<";


cout << c << ">" << endl;
}

// ----------------------------------
// STRING CLASS FUNCTIONS

String::String() {
ptr = new char[1];
ptr[0] = '\0';
}

String::String(char *s) {
int n = strlen(s);
ptr = new char[n + 1];
strcpy(ptr, s);
}

String::~String() {
delete [] ptr;
}

int String:: operator==(const String &other) {


return (strcmp(ptr, other.ptr) == 0);
}
// sa se supraincarce (defineasca) intr-o clsa operatori de
concaternare

#include "stdafx.h"

#include <iostream>
#include <string.h>
using namespace std;

75
class String {
private:
char *ptr;
public:
String();
String(char *s);
String(const String &src);
~String();

String& operator=(const String &src)


{cpy(src.ptr); return *this;}

String& operator=(char *s)


{cpy(s); return *this;}

String operator+(char *s);


int operator==(const String &other);
operator char*() {return ptr;}

void cat(char *s);


void cpy(char *s);
};

int main() {
String a, b, c;
a = "I ";
b = "am ";
c = "so ";
String d = a + b + c + "very happy!\n";
cout << d;
return 0;
}

// ----------------------------------
// STRING CLASS FUNCTIONS

String::String() {
ptr = new char[1];
ptr[0] = '\0';
}

String::String(char *s) {
int n = strlen(s);
ptr = new char[n + 1];
strcpy(ptr, s);
}

String::String(const String &src) {


int n = strlen(src.ptr);
ptr = new char[n + 1];
strcpy(ptr, src.ptr);
}

String::~String() {
delete [] ptr;
}

int String:: operator==(const String &other) {


return (strcmp(ptr, other.ptr) == 0);
}

76
String String::operator+(char *s) {
String new_str(ptr);
new_str.cat(s);
return new_str;
}

// cpy -- Copy string function


//
void String::cpy(char *s) {
delete [] ptr;
int n = strlen(s);
ptr = new char[n + 1];
strcpy(ptr, s);
}

// cat -- Concatenate string function


//
void String::cat(char *s) {

// Allocate sufficient room for new string data.

int n = strlen(ptr) + strlen(s);


char *p1 = new char[n + 1];

// Copy data to this new memory block.

strcpy(p1, ptr);
strcat(p1, s);

// Release old memory block and update ptr.

delete [] ptr;
ptr = p1;
}

// Exercitiul 15.2.1.txt
// Acest exemplu revizuieste programul string2.cpp astfel incat sa
suporte functia
// operator+ sub forma unei functii prieten globale.

#include "stdafx.h"

#include <iostream>
#include <string.h>
using namespace std;

class String {
private:
char *ptr;
public:
String();
String(char *s);
String(const String &src);
~String();

String& operator=(const String &src)


{cpy(src.ptr); return *this;}

String& operator=(char *s)


{cpy(s); return *this;}

77
// NEW DECLARATIONS -- FRIEND FUNCTIONS

friend String operator+(String str1, String str2);


friend String operator+(char *s, String str);
friend String operator+(String str, char *s);

int operator==(const String &other);


operator char*() {return ptr;}

void cat(char *s);


void cpy(char *s);
};

int main() {
String a, b, c;
a = "I ";
b = "am ";
c = "so ";

// THIS NEXT STATEMENT TESTS THE FRIEND FUNCTIONS

String d = "Let me say that " + a + b + c + "very happy!\n";


cout << d;
return 0;
}

// ----------------------------------
// STRING CLASS FUNCTIONS

String::String() {
ptr = new char[1];
ptr[0] = '\0';
}

String::String(char *s) {
int n = strlen(s);
ptr = new char[n + 1];
strcpy(ptr, s);
}

String::String(const String &src) {


int n = strlen(src.ptr);
ptr = new char[n + 1];
strcpy(ptr, src.ptr);
}

String::~String() {
delete [] ptr;
}

int String:: operator==(const String &other) {


return (strcmp(ptr, other.ptr) == 0);
}

// cpy -- Copy string function


//
void String::cpy(char *s) {
delete [] ptr;
int n = strlen(s);

78
ptr = new char[n + 1];
strcpy(ptr, s);
}

// cat -- Concatenate string function


//
void String::cat(char *s) {

// Allocate sufficient room for new string data.

int n = strlen(ptr) + strlen(s);


char *p1 = new char[n + 1];

// Copy data to this new memory block.

strcpy(p1, ptr);
strcat(p1, s);

// Release old memory block and update ptr.

delete [] ptr;
ptr = p1;
}

// GLOBAL FRIEND FUNCTIONS IMPLEMENTING THE + OPERATOR


// THESE MUST SUPPORT EVERY COMBINATION ALLOWED OF
// char* AND string TYPE.

String operator+(String str1, String str2) {


String new_str(str1);
new_str.cat(str2);
return new_str;
}

String operator+(String str, char *s) {


String new_str(str);
new_str.cat(s);
return new_str;
}

String operator+(char *s, String str) {


String new_str(s);
new_str.cat(str);
return new_str;
}

// Exercitiul 15.2.2.txt
// Acest program modifica declaratiile din string2.cpp
// astfel incat fiecare functie care are un argument de tipul
// char* sa foloseasca un argument de tipul const char*.

#include "stdafx.h"

#include <iostream>
#include <string.h>
using namespace std;

class String {

79
private:
char *ptr;
public:
String();
String(const char *s); // ALTERED LINE
String(const String &src);
~String();

String& operator=(const String &src)


{cpy(src.ptr); return *this;}

String& operator=(const char *s) // ALTERED LINE


{cpy(s); return *this;}

String operator+(const char *s); // ALTERED LINE


int operator==(const String &other);
operator char*() {return ptr;}

void cat(const char *s); // ALTERED LINE


void cpy(const char *s); // ALTERED LINE
};

int main() {
String a, b, c;
a = "I ";
b = "am ";
c = "so ";
String d = a + b + c + "very happy!\n";
cout << d;
return 0;
}

// ----------------------------------
// STRING CLASS FUNCTIONS

String::String() {
ptr = new char[1];
ptr[0] = '\0';
}

String::String(const char *s) { // ALTERED LINE


int n = strlen(s);
ptr = new char[n + 1];
strcpy(ptr, s);
}

String::String(const String &src) {


int n = strlen(src.ptr);
ptr = new char[n + 1];
strcpy(ptr, src.ptr);
}

String::~String() {
delete [] ptr;
}

int String:: operator==(const String &other) {


return (strcmp(ptr, other.ptr) == 0);
}

String String::operator+(const char *s) { // ALTERED LINE

80
String new_str(ptr);
new_str.cat(s);
return new_str;
}

// cpy -- Copy string function


//
void String::cpy(const char *s) { // ALTERED LINE
delete [] ptr;
int n = strlen(s);
ptr = new char[n + 1];
strcpy(ptr, s);
}

// cat -- Concatenate string function


//
void String::cat(const char *s) { // ALTERED LINE

// Allocate sufficient room for new string data.

int n = strlen(ptr) + strlen(s);


char *p1 = new char[n + 1];

// Copy data to this new memory block.

strcpy(p1, ptr);
strcat(p1, s);

// Release old memory block and update ptr.

delete [] ptr;
ptr = p1;
}
MOSTENIRE-IN PROGRAMAREA PE OBIECT VISUAL
C++.NET
Moştenirea

Moştenirea este una dintre caracteristicile cele mai importante ale unui limbaj
de programare OO. În C++ moştenirea este realizată prin acceptarea ca o clasă să
încorporeze în declararea sa altă clasă. Moştenirea permite construirea unei ierarhii
de clase, trecerea de la cele mai generale la cele mai particulare. Procesul acesta
implică pentru început definirea clasei de bază, care stabileşte calităţile comune ale
tuturor obiectelor ce vor deriva de aici. Clasa de bază reprezintă cea mai generală
descriere. Clasele derivate (obţinute prin moştenire) din clasa de bază se numesc chiar
clase derivate. O clasă derivată include toate caracteristicile clasei de bază şi în plus
calităţi proprii acelei clase.

//sa se prezinte un exemplu de subclasa la fractii

#include "stdafx.h"

#include <iostream>
using namespace std;

class Fraction {
private:
int num, den; // Numerator and denominator.

81
public:
Fraction() {set(0, 1);}
Fraction(int n, int d) {set(n, d);}
Fraction(int n) {set(n, 1);}
Fraction(const Fraction &src);

void set(int n, int d) {num = n; den = d; normalize();}


int get_num() const {return num;}
int get_den() const {return den;}
Fraction add(const Fraction &other);
Fraction mult(const Fraction &other);
Fraction operator+(const Fraction &other)
{return add(other);}
Fraction operator*(const Fraction &other)
{return mult(other);}
int operator==(const Fraction &other);
friend ostream &operator<<(ostream &os, Fraction &fr);

private:
void normalize(); // Put fraction into standard form.
int gcf(int a, int b); // Greatest Common Factor.
int lcm(int a, int b); // Lowest Common Denominator.
};

class FloatFraction : public Fraction {


public:
double get_float() {
return static_cast<double>(get_num())/get_den();}
};

int main() {
FloatFraction fract1;

fract1.set(1, 2);
cout << "Value of 1/2 is " << fract1.get_float() << endl;
fract1.set(3, 5);
cout << "Value of 3/5 is " << fract1.get_float() << endl;
return 0;
}

Fraction::Fraction(Fraction const &src) {


num = src.num;
den = src.den;
}

void Fraction::normalize(){

82
if (den == 0 || num == 0) {
num = 0;
den = 1;
}

// Put neg. sign in numerator only.

if (den < 0) {
num *= -1;
den *= -1;
}

// Factor out GCF from numerator and denominator.

int n = gcf(num, den);


num = num / n;
den = den / n;
}

// Greatest Common Factor


//
int Fraction::gcf(int a, int b) {
if (a % b == 0)
return abs(b);
else
return gcf(b, a % b);
}

// Lowest Common Multiple


//
int Fraction::lcm(int a, int b){
return (a / gcf(a, b)) * b;
}

Fraction Fraction::add(const Fraction &other) {


Fraction fract;
int lcd = lcm(den, other.den);
int quot1 = lcd/den;
int quot2 = lcd/other.den;
fract.set(num * quot1 + other.num * quot2, lcd);
fract.normalize();
return fract;
}

Fraction Fraction::mult(const Fraction &other) {


Fraction fract;
fract.set(num * other.num, den * other.den);
fract.normalize();
return fract;
}

int Fraction::operator==(const Fraction &other) {


return (num == other.num && den == other.den);
}

// ---------------------------------------------------
// FRACTION CLASS FRIEND FUNCTION

83
ostream &operator<<(ostream &os, Fraction &fr) {
os << fr.num << "/" << fr.den;
return os;
}
// Exercitiul 16.1.1.txt
// Acest program modifica scriptul floatfract1.cpp astfel incat sa
// contina o functie set_float().

#include "stdafx.h"

#include <iostream>
using namespace std;

class Fraction {
private:
int num, den; // Numerator and denominator.
public:
Fraction() {set(0, 1);}
Fraction(int n, int d) {set(n, d);}
Fraction(int n) {set(n, 1);}
Fraction(const Fraction &src);

void set(int n, int d) {num = n; den = d; normalize();}


int get_num() const {return num;}
int get_den() const {return den;}
Fraction add(const Fraction &other);
Fraction mult(const Fraction &other);
Fraction operator+(const Fraction &other)
{return add(other);}
Fraction operator*(const Fraction &other)
{return mult(other);}
int operator==(const Fraction &other);
friend ostream &operator<<(ostream &os, Fraction &fr);

private:
void normalize(); // Put fraction into standard form.
int gcf(int a, int b); // Greatest Common Factor.
int lcm(int a, int b); // Lowest Common Denominator.
};

class FloatFraction : public Fraction {


public:
double get_float() {
return static_cast<double>(get_num())/get_den();}

void set_float(double x);

};

int main() {
FloatFraction fract1;

fract1.set_float(0.5);
cout << "Value of 0.5 is " << fract1.get_float() << endl;

84
fract1.set_float(0.6);
cout << "Value of 0.6 is " << fract1.get_float() << endl;
return 0;
}

void FloatFraction::set_float(double x) {
int new_val = static_cast<int>(x * 100.0);
set(new_val, 100);
}

// ---------------------------------------------------
// FRACTION CLASS FUNCTIONS

Fraction::Fraction(Fraction const &src) {


num = src.num;
den = src.den;
}

// Normalize: put fraction into a standard form, unique


// for each mathematically different value.
//
void Fraction::normalize(){

// Handle cases involving 0

if (den == 0 || num == 0) {
num = 0;
den = 1;
}

// Put neg. sign in numerator only.

if (den < 0) {
num *= -1;
den *= -1;
}

// Factor out GCF from numerator and denominator.

int n = gcf(num, den);


num = num / n;
den = den / n;
}

// Greatest Common Factor


//
int Fraction::gcf(int a, int b) {
if (a % b == 0)
return abs(b);
else
return gcf(b, a % b);
}

85
// Lowest Common Multiple
//
int Fraction::lcm(int a, int b){
return (a / gcf(a, b)) * b;
}

Fraction Fraction::add(const Fraction &other) {


Fraction fract;
int lcd = lcm(den, other.den);
int quot1 = lcd/den;
int quot2 = lcd/other.den;
fract.set(num * quot1 + other.num * quot2, lcd);
fract.normalize();
return fract;
}

Fraction Fraction::mult(const Fraction &other) {


Fraction fract;
fract.set(num * other.num, den * other.den);
fract.normalize();
return fract;
}

int Fraction::operator==(const Fraction &other) {


return (num == other.num && den == other.den);
}

ostream &operator<<(ostream &os, Fraction &fr) {


os << fr.num << "/" << fr.den;
return os;
}
// Exercitiul 16.1.1.txt
// Acest program modifica scriptul floatfract1.cpp astfel incat sa
includa
// functia set_float().

#include "stdafx.h"
#include <iostream>
using namespace std;

class Fraction {
private:
int num, den; // Numerator and denominator.
public:
Fraction() {set(0, 1);}
Fraction(int n, int d) {set(n, d);}
Fraction(int n) {set(n, 1);}
Fraction(const Fraction &src);

void set(int n, int d) {num = n; den = d; normalize();}


int get_num() const {return num;}
int get_den() const {return den;}
Fraction add(const Fraction &other);
Fraction mult(const Fraction &other);
Fraction operator+(const Fraction &other)
{return add(other);}
Fraction operator*(const Fraction &other)
{return mult(other);}
int operator==(const Fraction &other);

86
friend ostream &operator<<(ostream &os, Fraction &fr);

private:
void normalize(); // Put fraction into standard form.
int gcf(int a, int b); // Greatest Common Factor.
int lcm(int a, int b); // Lowest Common Denominator.
};

class FloatFraction : public Fraction {


public:

FloatFraction(double x) {set_float(x); } // ADD CONSTRUCTOR

double get_float() {
return static_cast<double>(get_num())/get_den();}

void set_float(double x);

};

int main() {
FloatFraction fract1(0.5), fract2(0.6);

cout << "Value of 0.5 is " << fract1.get_float() << endl;


cout << "Value of 0.6 is " << fract2.get_float() << endl;
return 0;
}

void FloatFraction::set_float(double x) {
int new_val = static_cast<int>(x * 100.0);
set(new_val, 100);
}

Fraction::Fraction(Fraction const &src) {


num = src.num;
den = src.den;
}

// Normalize: put fraction into a standard form, unique


// for each mathematically different value.
//
void Fraction::normalize(){

// Handle cases involving 0

if (den == 0 || num == 0) {
num = 0;
den = 1;

87
}

// Put neg. sign in numerator only.

if (den < 0) {
num *= -1;
den *= -1;
}

// Factor out GCF from numerator and denominator.

int n = gcf(num, den);


num = num / n;
den = den / n;
}

// Greatest Common Factor


//
int Fraction::gcf(int a, int b) {
if (a % b == 0)
return abs(b);
else
return gcf(b, a % b);
}

// Lowest Common Multiple


//
int Fraction::lcm(int a, int b){
return (a / gcf(a, b)) * b;
}

Fraction Fraction::add(const Fraction &other) {


Fraction fract;
int lcd = lcm(den, other.den);
int quot1 = lcd/den;
int quot2 = lcd/other.den;
fract.set(num * quot1 + other.num * quot2, lcd);
fract.normalize();
return fract;
}

Fraction Fraction::mult(const Fraction &other) {


Fraction fract;
fract.set(num * other.num, den * other.den);
fract.normalize();
return fract;
}

int Fraction::operator==(const Fraction &other) {


return (num == other.num && den == other.den);
}

// ---------------------------------------------------
// FRACTION CLASS FRIEND FUNCTION

ostream &operator<<(ostream &os, Fraction &fr) {


os << fr.num << "/" << fr.den;
return os;
}

 metoda este si importul unui fisier sub forma

88
#include<nume_fiesier.cpp> exemplu #include "Fract7.cpp"
dar
1) el trebuie salvat in directorul unde avem exemplele de mostenire

C:\Documents and Settings\ticatica\My Documents\


adica in :
Visual Studio Projects\e16import1
2)trebuie sa-l importam in proiectul nostru cu comanda:
proiect/add existing item

aleg calea spre fisier

89
open
4)Fisierul de imoprtat trebuie sa nu contina sectiunea main()
deci sa aiba continutul de mai jos:
#include <iostream>
using namespace std;

class Fraction {
private:
int num, den; // Numerator and denominator.
public:
Fraction() {set(0, 1);}
Fraction(int n, int d) {set(n, d);}
Fraction(int n) {set(n, 1);}
Fraction(const Fraction &src);

void set(int n, int d) {num = n; den = d; normalize();}


int get_num() const {return num;}
int get_den() const {return den;}
Fraction add(const Fraction &other);
Fraction mult(const Fraction &other);
Fraction operator+(const Fraction &other)
{return add(other);}
Fraction operator*(const Fraction &other)
{return mult(other);}
int operator==(const Fraction &other);
friend ostream &operator<<(ostream &os, Fraction &fr);

private:
void normalize(); // Put fraction into standard form.
int gcf(int a, int b); // Greatest Common Factor.
int lcm(int a, int b); // Lowest Common Denominator.
};

// ---------------------------------------------------

90
// FRACTION CLASS FUNCTIONS

Fraction::Fraction(Fraction const &src) {


num = src.num;
den = src.den;
}

// Normalize: put fraction into a standard form, unique


// for each mathematically different value.
//
void Fraction::normalize(){

// Handle cases involving 0

if (den == 0 || num == 0) {
num = 0;
den = 1;
}

// Put neg. sign in numerator only.

if (den < 0) {
num *= -1;
den *= -1;
}

// Factor out GCF from numerator and denominator.

int n = gcf(num, den);


num = num / n;
den = den / n;
}

// Greatest Common Factor


//
int Fraction::gcf(int a, int b) {
if (a % b == 0)
return abs(b);
else
return gcf(b, a % b);
}

// Lowest Common Multiple


//
int Fraction::lcm(int a, int b){
return (a / gcf(a, b)) * b;
}

Fraction Fraction::add(const Fraction &other) {


Fraction fract;
int lcd = lcm(den, other.den);
int quot1 = lcd/den;
int quot2 = lcd/other.den;
fract.set(num * quot1 + other.num * quot2, lcd);
fract.normalize();
return fract;
}

Fraction Fraction::mult(const Fraction &other) {


Fraction fract;

91
fract.set(num * other.num, den * other.den);
fract.normalize();
return fract;
}

int Fraction::operator==(const Fraction &other) {


return (num == other.num && den == other.den);
}

// ---------------------------------------------------
// FRACTION CLASS FRIEND FUNCTION

ostream &operator<<(ostream &os, Fraction &fr) {


os << fr.num << "/" << fr.den;
return os;
}
5)scriu contiunutul fisierului nou (cel cu subclasa si il execut) dar sa contina #include
"Fract7.cpp"
// Sa se creeze o subclasa prin includerea altui fisier
//cu clasa de baza

#include "stdafx.h"

#include <iostream>
#include "Fract7.cpp"
using namespace std;

class FloatFraction : public Fraction {


public:
double get_float() {
return static_cast<double>(get_num())/get_den();}

void set_float(double x); // NEW DECLARATION

};

int main() {
FloatFraction fract1;

fract1.set_float(0.5);
cout << "Value of 0.5 is " << fract1.get_float() << endl;
fract1.set_float(0.6);
cout << "Value of 0.6 is " << fract1.get_float() << endl;
return 0;
}

void FloatFraction::set_float(double x) {
int new_val = static_cast<int>(x * 100.0);
set(new_val, 100);
}
POLIMORIFISM
Polimorfismul cu functii virtuale

92
Polimorfismul in C++ este admis atit in timpul compilarii cit si in timpul
rularii. polimorfismul din timpul rularii este realizat folosind mostenirea si functiile
virtuale.
Functiile virtuale

O functie virtuala este declarata ca fiind virtual in clasa de baza si redefinita de


o clasa derivata. Redefinirea functiei in clasa derivata are prioritate fata de definirea
functiei din clasa de baza. O functie virtuala declarata in clasa de baza actioneaza ca
un substitut pentru pastrarea datelor care specifica o clasa generala de actiuni si
declara in general forma interfetei. Redefinirea unei functii virtuale intr-o clasa derivata
ofera operatiile efective pe care le executa functia. deci o functie virtuala defineste o
clasa generala de actiuni iar redefinirea ei introduce o metoda specifica.
Utilizarea obisnuita a unei functii virtuale (deci folosind operatorul punct) nu
difera de cea a altor functii membre. Insa utilitatea deosebita a functiilor virtuale,
respectiv, realizarea polimorfismului, decurge din folosirea pointerilor pentru apelul
acestora. Cind un pointer indica spre un obiect derivat care contine o functie virtuala,
la executie se determina automat care dintre versiunile functiei sa fie apelata, in
functie de tipul obiectului spre care indica pointerul. De aceea, cind sint indicate
obiecte diferite, se executa versiunile corespunzatoare ale functiilor virtuale.
La redefinire cuvintul cheie virtual nu mai este necesar, dar nu este eroare daca totusi
il folosim.
Proprietati ale functiilor virtuale

Functiile virtuale si utilizarea acestora sint caracterizate de anumite proprietati :

a. Atributul virtual este mostenit

Mostenirea transmite si natura virtuala a unei functii. Aceasta inseamna ca atunci


cind o
clasa derivata care a mostenit o functie virtuala este ea insasi folosita ca o clasa de
baza pentru o alta clasa derivata, functia virtuala poate fi in continuare suprascrisa.
Deci o functie ramine virtuala indiferent de cite ori este mostenita.
Polimorfismul din timpul rularii (ca in exemplul de mai sus) este permis doar
folosind pointeri, adica exact in modul prezentat in exemplu.
Aparent, redefinirea unei functii virtuale intr-o clasa derivata pare similara cu
supraincarcarea functiei (overload). Exista totusi mai multe diferente. Cea mai
importanta este aceea ca prototipul pentru o functie virtuala redefinita trebuie sa
coincida cu cel specificat in clasa de baza (la supraincarcare, numarul sau tipurile
parametrilor trebuie sa difere !). Daca prototipul difera la redefinire, compilatorul va
considera functia respectiva o simpla functie supraincarcata si avantajele folosirii
functiilor virtuale se pierd.
Exista o serie de restrictii la utilizarea functiilor virtuale:
- acestea nu pot fi membri static ai clasei, de asemenea nu pot fi nici
friend;
- functiile constructor nu pot fi virtuale (in schimb functiile destructor
pot fi).

Datorita restrictiilor si diferentelor dintre functiile supraincarcate si cele virtuale,

93
pentru descrierea redefinirii functiei virtuale intr-o clasa derivata se foloseste operandul
suprascriere.
O clasa care include o functie virtuala se numeste clasa polimorfica.
b. Functiile virtuale sint ierarhizate

S-a vazut ca o functie declarata virtual in clasa de baza poate fi suprascrisa de o


clasa
derivata. Functia nu trebuie neaparat sa fie suprascrisa. Daca functia nu este
suprascrisa in clasa derivata, pentru un obiect din clasa derivata este valabila forma
functiei definite in clasa de baza.
Functii virtuale pure

S-a vazut ca in cazul ueni ierarhii, va fi folosita functia virtuala a clasei


precedente in ordine ierarhica, daca ea nu este redefinita in cadrul clasei curente. Dar
se poate chiar ca in clasa de baza sa nu fie definita (decit declarata) nici o functie
virtuala. Motive pot sa fie mai multe: sint situatii cind la nivelul clasei de baza nu sint
suficiente informatii pentru a permite crearea unei functii virtuale sau altele in care
dorim sa ne asiguram ca toate clasele deerivate suprascriu functiile virtuale.
O functie virtuala pura este o functie virtuala care nu are definitie in clasa de
baza. Declararea unei asemenea functii are urmatoarea forma generala :

virtual tip nume_functie(lista_parametri) = 0;

Orice clasa derivata trebuie sa asigure o definire fiecarei functii virtuale pure.
Daca aceasta cerinta nu este indeplinita, compilatorul sesizeaza eroare.
In practica programarii in C++ se folosesc citeodata clasele abstracte. Acestea sint
clase care contin cel putin o functie virtuala pura. Deoarece o clasa abstracta contine
una sau mai multe functii pentru care nu exista definitii (adica sint functii virtuale
pure), nu pot fi create obiecte de tipul acelei clase. O clasa abstracta este un tip
incomplet care este folosit doar pentru mai usoara definire a claselor derivate.
Chiar daca nu pot fi create obiecte de tipul unei clase abstracte, se pot crea
pointeri si referinte pentru astfel de clase. Aceasta permite claselor abstracte sa admita
polimorfismul in timpul rularii, care consta din selectarea functiei virtuale corecte de
catre pointerii clasei de baza.
Utilizarea functiilor virtuale

Unul dintre aspectele esentiale ale programarii orientate pe obiecte este


principiul “o interfata – metode multiple”. Aceasta inseamna ca poate fi definita o
clasa generala de actiuni pentru care interfata este aceeasi, iar fiecare instanta a clasei
generale care defineste operatiile efective corespunde propriei sale situatii specifice.
Deci o clasa de baza poate fi folosita pentru a defini natura unei interfete cu o clasa
generala, iar fiecare clasa derivata introduce apoi operatiile specifice cerute de tipurile
de date folosite de tipul derivat.

94
Una dintre caile cele mai indicate pentru a asigura transpunerea in practica a
principiului “o interfata – metode multiple” este folosirea functiilor virtuale, a claselor
abstracte si a polimorfismului in timpul rularii. Folosind aceste caracteristici, se pot
realiza ierarhii care sa faca trecerea de la general la specific (de la clasa de baz aspre
clasele derivate), respectind astfel si unul din principiile ingineriei programarii –
abstractizarea. Conform acestei filosofii, trebuie definite toate caracteristicile si
interfetele comune ale unei clase de baza. De asemenea, se folosesc functii virtuale
pentru a defini interfata care va fi folosita de clasele derivate. In esenta, in clasa de
baza trebuie create si definite toate referirile la cazul general, iar clasele derivate
completeaza detaliile specifice.
O utilizare importantă a claselor abstracte şi a funcţiilor virtuale este cea a bibliotecilor de
clase. Un utilizator poate crea propria bibliotecă de clase generice şi extensibile care vor fi
refolosite de alţi utilizatori. Aceştia vor moşteni clasa generală creată iniţial, care defineşte
interfaţa şi elementele comune şi vor defini doar acele funcţii specifice clasei derivate.

Legături iniţiale, legături ulterioare

Legat de cele discutate, mai trebuie precizate două noţiuni folosite frecvent :

Legăturile iniţiale (early bindings) se referă la evenimentele care apar în timpul


compilării şi semnifică faptul că toate informaţiile necesare pentru a apela o funcţie sînt
cunoscute în timpul compilării (altfel spus, legăturile iniţiale arată că legăturile dintre un obiect
şi o apelare de funcţie se realizează în timpul compilării). Exemple din această categorie includ
apelările de funcţii normale (inclusiv funcţiile standard de bibliotecă), apelările de funcţii
supraîncărcate şi operatori supraîncărcaţi. Avantajul legăturilor iniţiale este eficienţa :
deoarece toate informaţiile necesare pentru a apela o funcţie sînt determinate în timpul
compilării, aceste tipuri de funcţii sînt foarte rapide.

Legăturile ulterioare (late bindings) se referă la apelările de funcţii care nu sînt rezolvate
pînă în momentul rulării. Pentru realizarea legăturilor ulterioare sînt utilizate funcţiile virtuale.
În acest caz, apelarea efectivă a funcţiei virtuale este determinată de tipul obiectului spre care
indică pointerul prin care îl accesăm. Deoarece în majoritatea cazurilor acesta nu poate fi
determinat în timpul compilării, obiectul şi funcţia nu sînt legate pînă în momentul rulării.
Avantajul legăturilor ulterioare este flexibilitatea : spre deosebire de legăturile iniţiale, cele
ulterioare permit crearea programelor care să răspundă la evenimentele care apar în timpul
rulării fără să fie necesară crearea unui cod suplimentar pentru selectarea situaţiilor şi apelurilor
dorite. Însă, deoarece rezolvarea direcţionării apelurilor este împinsă spre execuţia programului,
acesta va fi mai lent.
// Prin apelul aceleasi functii ca denumire a unui obiect dintr-o
//subclasa a unei functii din clasa de baza si aceleasi functii dar
redefinita
//in subclasa dar ca si continut diferita
//Sa se exemplifice acest lucru
//EX:1
// 2
// 1
// 2
// 1

#include "stdafx.h"

#include <iostream>

95
using namespace std;

class Horse
{
public:
void Gallop(){ cout << "Galloping...\n"; }
virtual void Fly() { cout << "Horses can't fly.\n" ; }
private:
int itsAge;
};

class Pegasus : public Horse


{
public:
virtual void Fly() { cout << "I can fly! I can fly! I can
fly!\n"; }
};

const int NumberHorses = 5;


int main()
{
Horse* Ranch[NumberHorses];
Horse* pHorse;
int choice,i;
for (i=0; i<NumberHorses; i++)
{
cout << "(1)Horse (2)Pegasus: ";
cin >> choice;
if (choice == 2)
pHorse = new Pegasus;
else
pHorse = new Horse;
Ranch[i] = pHorse;
}
cout << "\n";
for (i=0; i<NumberHorses; i++)
{
Ranch[i]->Fly();
delete Ranch[i];
}
return 0;
}

// Sa se apeleze aceleasi destructori si constructori


//pentru mai multe clase si subclase

#include "stdafx.h"
#include <iostream>

using namespace std;

typedef int HANDS;


enum COLOR { Red, Green, Blue, Yellow, White, Black, Brown } ;
enum BOOL { FALSE, TRUE };
class Horse
{
public:
Horse(COLOR color, HANDS height);
virtual ~Horse() { cout << "Horse destructor...\n"; }
virtual void Whinny()const { cout << "Whinny!... "; }

96
virtual HANDS GetHeight() const { return itsHeight; }
virtual COLOR GetColor() const { return itsColor; }
private:
HANDS itsHeight;
COLOR itsColor;
};

Horse::Horse(COLOR color, HANDS height):


itsColor(color),itsHeight(height)
{
cout << "Horse constructor...\n";
}

class Bird
{
public:
Bird(COLOR color, BOOL migrates);
virtual ~Bird() {cout << "Bird destructor...\n"; }
virtual void Chirp()const { cout << "Chirp... "; }
virtual void Fly()const
{
cout << "I can fly! I can fly! I can fly! ";
}
virtual COLOR GetColor()const { return itsColor; }
virtual BOOL GetMigration() const { return itsMigration; }

private:
COLOR itsColor;
BOOL itsMigration;
};

Bird::Bird(COLOR color, BOOL migrates):


itsColor(color), itsMigration(migrates)
{
cout << "Bird constructor...\n";
}

class Pegasus : public Horse, public Bird


{
public:
void Chirp()const { Whinny(); }
Pegasus(COLOR, HANDS, BOOL,long);
~Pegasus() {cout << "Pegasus destructor...\n";}
virtual long GetNumberBelievers() const
{
return itsNumberBelievers;
}

private:
long itsNumberBelievers;
};

Pegasus::Pegasus(
COLOR aColor,
HANDS height,
BOOL migrates,
long NumBelieve):
Horse(aColor, height),
Bird(aColor, migrates),
itsNumberBelievers(NumBelieve)
{

97
cout << "Pegasus constructor...\n";
}

int main()
{
Pegasus *pPeg = new Pegasus(Red, 5, TRUE, 10);
pPeg->Fly();
pPeg->Whinny();
cout << "\nYour Pegasus is " << pPeg->GetHeight();
cout << " hands tall and ";
if (pPeg->GetMigration())
cout << "it does migrate.";
else
cout << "it does not migrate.";
cout << "\nA total of " << pPeg->GetNumberBelievers();
cout << " people believe it exists.\n";
delete pPeg;
return 0;
}

// Sa se puna in evidenta faptul ca apelul destructorilor este


//exact invers ca ordine decat al constructorilor

#include "stdafx.h"
#include <iostream>

using namespace std;

typedef int HANDS;


enum COLOR { Red, Green, Blue, Yellow, White, Black, Brown } ;
enum BOOL { FALSE, TRUE };

class Animal // common base to both horse and bird


{
public:
Animal(int);
virtual ~Animal() { cout << "Animal destructor...\n"; }
virtual int GetAge() const { return itsAge; }
virtual void SetAge(int age) { itsAge = age; }
private:
int itsAge;
};

Animal::Animal(int age):
itsAge(age)
{
cout << "Animal constructor...\n";
}

class Horse : public Animal


{
public:
Horse(COLOR color, HANDS height, int age);
virtual ~Horse() { cout << "Horse destructor...\n"; }
virtual void Whinny()const { cout << "Whinny!... "; }
virtual HANDS GetHeight() const { return itsHeight; }
virtual COLOR GetColor() const { return itsColor; }
protected:
HANDS itsHeight;
COLOR itsColor;

98
};

Horse::Horse(COLOR color, HANDS height, int age):


Animal(age),
itsColor(color),itsHeight(height)
{
cout << "Horse constructor...\n";
}

class Bird : public Animal


{
public:
Bird(COLOR color, BOOL migrates, int age);
virtual ~Bird() {cout << "Bird destructor...\n"; }
virtual void Chirp()const { cout << "Chirp... "; }
virtual void Fly()const
{ cout << "I can fly! I can fly! I can fly! "; }
virtual COLOR GetColor()const { return itsColor; }
virtual BOOL GetMigration() const { return itsMigration; }
protected:
COLOR itsColor;
BOOL itsMigration;
};

Bird::Bird(COLOR color, BOOL migrates, int age):


Animal(age),
itsColor(color), itsMigration(migrates)
{
cout << "Bird constructor...\n";
}

class Pegasus : public Horse, public Bird


{
public:
void Chirp()const { Whinny(); }
Pegasus(COLOR, HANDS, BOOL, long, int);
~Pegasus() {cout << "Pegasus destructor...\n";}
virtual long GetNumberBelievers() const
{ return itsNumberBelievers; }
virtual COLOR GetColor()const { return Horse::itsColor; }
virtual int GetAge() const { return Horse::GetAge(); }
private:
long itsNumberBelievers;
};

Pegasus::Pegasus(
COLOR aColor,
HANDS height,
BOOL migrates,
long NumBelieve,
int age):
Horse(aColor, height,age),
Bird(aColor, migrates,age),
itsNumberBelievers(NumBelieve)
{
cout << "Pegasus constructor...\n";
}

int main()
{
Pegasus *pPeg = new Pegasus(Red, 5, TRUE, 10, 2);

99
int age = pPeg->GetAge();
cout << "This pegasus is " << age << " years old.\n";
delete pPeg;
return 0;
}

// Fie ca Cercul sa fie o subclasa a doua clase si fiecare


//din clase sa aiba constructori diferiti pe care sa-i apleze aceasta
subclasa
//ex:2 3 0
#include "stdafx.h"

#include <iostream>
using namespace std;
enum BOOL { FALSE, TRUE };
class Shape
{
public:
Shape(){}
~Shape(){}
virtual long GetArea() { return -1; } // error
virtual long GetPerim() { return -1; }
virtual void Draw() {}
private:
};

class Circle : public Shape


{
public:
Circle(int radius):itsRadius(radius){}
~Circle(){}
long GetArea() { return 3 * itsRadius * itsRadius; }
long GetPerim() { return 9 * itsRadius; }
void Draw();
private:
int itsRadius;
int itsCircumference;
};

void Circle::Draw()
{
cout << "Circle drawing routine here!\n";
}

class Rectangle : public Shape


{
public:
Rectangle(int len, int width):
itsLength(len), itsWidth(width){}
~Rectangle(){}
virtual long GetArea() { return itsLength * itsWidth; }
virtual long GetPerim() {return 2*itsLength + 2*itsWidth; }
virtual int GetLength() { return itsLength; }
virtual int GetWidth() { return itsWidth; }
virtual void Draw();
private:
int itsWidth;
int itsLength;
};

100
void Rectangle::Draw()
{
for (int i = 0; i<itsLength; i++)
{
for (int j = 0; j<itsWidth; j++)
cout << "x ";

cout << "\n";


}
}

class Square : public Rectangle


{
public:
Square(int len);
Square(int len, int width);
~Square(){}
long GetPerim() {return 4 * GetLength();}
};

Square::Square(int len):
Rectangle(len,len)
{}

Square::Square(int len, int width):


Rectangle(len,width)

{
if (GetLength() != GetWidth())
cout << "Error, not a square... a Rectangle??\n";
}

int main()
{
int choice;
BOOL fQuit = FALSE;
Shape * sp;

while (1)
{
cout << "(1)Circle (2)Rectangle (3)Square (0)Quit: ";
cin >> choice;

switch (choice)
{
case 1: sp = new Circle(5);
break;
case 2: sp = new Rectangle(4,6);
break;
case 3: sp = new Square(5);
break;
default: fQuit = TRUE;
break;
}
if (fQuit)
break;

sp->Draw();
cout << "\n";
}
return 0;

101
}

// Sa se scrie o aplicatie care pune in evidenta faptul ca


//o clasa poate apela constructorii subclaselor dar nu si invers

#include "stdafx.h"

#include <iostream>
using namespace std;
enum COLOR { Red, Green, Blue, Yellow, White, Black, Brown } ;
enum BOOL { FALSE, TRUE };

class Animal // common base to both horse and bird


{
public:
Animal(int);
virtual ~Animal() { cout << "Animal destructor...\n"; }
virtual int GetAge() const { return itsAge; }
virtual void SetAge(int age) { itsAge = age; }
virtual void Sleep() const = 0;
virtual void Eat() const = 0;
virtual void Reproduce() const = 0;
virtual void Move() const = 0;
virtual void Speak() const = 0;
private:
int itsAge;
};

Animal::Animal(int age):
itsAge(age)
{
cout << "Animal constructor...\n";
}

class Mammal : public Animal


{
public:
Mammal(int age):Animal(age)
{ cout << "Mammal constructor...\n";}
~Mammal() { cout << "Mammal destructor...\n";}
virtual void Reproduce() const
{ cout << "Mammal reproduction depicted...\n"; }
};

class Fish : public Animal


{
public:
Fish(int age):Animal(age)
{ cout << "Fish constructor...\n";}
virtual ~Fish() {cout << "Fish destructor...\n"; }
virtual void Sleep() const { cout << "fish snoring...\n"; }
virtual void Eat() const { cout << "fish feeding...\n"; }
virtual void Reproduce() const
{ cout << "fish laying eggs...\n"; }
virtual void Move() const
{ cout << "fish swimming...\n"; }
virtual void Speak() const { }
};

class Horse : public Mammal


{

102
public:
Horse(int age, COLOR color ):
Mammal(age), itsColor(color)
{ cout << "Horse constructor...\n"; }
virtual ~Horse() { cout << "Horse destructor...\n"; }
virtual void Speak()const { cout << "Whinny!... \n"; }
virtual COLOR GetItsColor() const { return itsColor; }
virtual void Sleep() const
{ cout << "Horse snoring...\n"; }
virtual void Eat() const { cout << "Horse feeding...\n"; }
virtual void Move() const { cout << "Horse running...\n";}

protected:
COLOR itsColor;
};

class Dog : public Mammal


{
public:
Dog(int age, COLOR color ):
Mammal(age), itsColor(color)
{ cout << "Dog constructor...\n"; }
virtual ~Dog() { cout << "Dog destructor...\n"; }
virtual void Speak()const { cout << "Whoof!... \n"; }
virtual void Sleep() const { cout << "Dog snoring...\n"; }
virtual void Eat() const { cout << "Dog eating...\n"; }
virtual void Move() const { cout << "Dog running...\n"; }
virtual void Reproduce() const
{ cout << "Dogs reproducing...\n"; }

protected:
COLOR itsColor;
};

int main()
{
Animal *pAnimal=0;
int choice;
BOOL fQuit = FALSE;

while (1)
{
cout << "(1)Dog (2)Horse (3)Fish (0)Quit: ";
cin >> choice;

switch (choice)
{
case 1: pAnimal = new Dog(5,Brown);
break;
case 2: pAnimal = new Horse(4,Black);
break;
case 3: pAnimal = new Fish (5);
break;
default: fQuit = TRUE;
break;
}
if (fQuit)
break;

pAnimal->Speak();
pAnimal->Eat();

103
pAnimal->Reproduce();
pAnimal->Move();
pAnimal->Sleep();
delete pAnimal;
cout << "\n";
}
return 0;
}
SUPRAINCARCAREA FUNCTIILOR
Supraîncărcarea

Supraîncărcarea funcţiilor şi a operatorilor (overloading) sînt esenţiale pentru


programarea în C++. Aceste două caracteristici oferă posibilitatea realizării polimorfismului şi
adaugă limbajului flexibilitate şi externsibilitate.
Deoarece supraîncărcarea operatorilor este mai dificil de abordat şi necesită înţelegerea
supraîncărcării funcţiilor, aceasta din urmă va fi tratată întîi.
Supraîncărcarea funcţiilor

Supraîncărcarea funcţiilor reprezintă folosirea aceluiaşi nume pentru două sau mai
multe funcţii. Fiecare redefinire a funcţiei trebuie să folosească tipuri diferite de parametri de
apel sau număr diferit de parametri. Compilatorul poate detecta care funcţie trebuie apelată, pe
baza acestor diferenţe.
Trebuie reţinut că nu pot fi supraîncărcate două funcţii care diferă doar prin tipul
returnat.
Ambiguităţi şi anacronisme la supraîncărcarea funcţiilor

Sînt situaţii în care compilatorul nu poate discerne între funcţiile supraîncărcate.


Această situaţie se numeşte (ca şi de altfel în sensul general al situaţiei de tipul acesta)
ambiguă. Aceste situaţii sînt depistate de compilator şi semnalate ca erori fatale şi programul
nu este compilat. Principala cauză de ambiguităţi este conversia automată de tip pe care o
realizează C++. Astfel, compilatorul C++ încearcă să convertească automat argumentele
folosite pentru apelul de funcţii în tipurile argumentelor aşteptate de funcţiile respective.
Supraîncărcarea funcţiilor constructor

Ca oricare altă funcţie, constructorii pot fi şi aceştia supraîncărcaţi. De fapt, această


supraîncărcare se practică foarte des (au fost cîteva exemple chiar în cursurile precedente).
Adresa unei funcţii supraîncărcate

În C putem să atribuim adresa unei funcţii, unui pointer şi apoi să aelăm funcţia
folosind pointerul. La fel se poate proceda (s-a văzut în cursurile precedente) şi în C++. O
complicaţie survine la supraîncărcarea funcţiilor, deoarece în această situaţie doar declararea
corespunzătoare a pointerului poate face diferenţierea.
Supraîncărcarea operatorilor

În C++ pot fi supraîncărcaţi aproape toţi operatorii. Supraîncărcarea acestora este strîns
legată de supraîncărcarea funcţiilor. În C++ supraîncărcarea operatorilor poate să determine
efectuarea unor operaţii speciale relativ la clasele create. Astfel, o memorie stivă poate fi
încărcată cu un element, folosind operatorul + supraîncărcat corespunzător, respectiv - pentru

104
extragere. Supraîncărcarea nu afectează vreuna din semnificaţiile originale ale utilizării
operatorului supraîncărcat.
Operatorii se supraîncarcă folosind funcţiile operator. O astfel de funcţie defineşte
operaţiile specifice pe care le va efectua operatorul supraîncărcat relativ la clasa în care este
destinat să lucreze. Funcţiile operator pot sau nu să fie membre ale clasei în care vor opera. De
obicei, cînd funcţiile operator nu sînt membre, sînt măcar funcţii friend. Cele două situaţii
(cînd sînt membre, respectiv cînd sînt friend) trebuie tratate diferit.

Funcţiile operator membre

Forma generică a definirii unor astfel de funcţii este :

tip_returnat nume_clasa::operator#(lista_argumente)
{
... // aici vor fi operatiile care reprezinta redefinirea
// operatorului
}
La operandul -, a trebuit să fim atenţi la ordine : operandul din dreapta semnului trebuie scăzut
din operandul din stînga (ordinea naturală) şi ţinînd cont de operandul care generază apelul
funcţiei operator-() (adică acel operand care va transmite un pointer this), a rezultat
exprimarea aparent curioasă din definirea funcţiei operand respective.
Pe de altă parte, trebuie remarcat că în C++, în lipsa unei supraîncărcări, operatorul =
devine un operator de copiere membru cu membru. În exemplul prezentat, funcţia operator=()
a returnat *this, ceea ce a permis realizarea atribuirilor multiple (de altfel, aceasta este raţiunea
pentru care a fost supraîncărcat acest operator).
Ultimul lucru pe care îl remarcăm este legat de supraîncărcarea operatorului unar.
Evident, acesta nu are parametri, deoarece acţionează asupra unui singur operand, care este deja
transmis prin this.

Simbolul # trebuie înlocuit cu operatorul a cărui supraîncărcare se defineşte.

// SA se supraincarece o functie pentru intregi si reale

#include "stdafx.h"

#include <iostream>
using namespace std;
int supra(int ); // prima functie are un parametru intreg
double supra(double ); // iar a doua are parametru double

main()
{
cout << supra(19) << " "; // apelul primei functii
cout << supra(5.4) << "\n"; //apelul celeilalte functii

return 0;
}

// acum sint definite cele doua functii


int supra(int i)
{
return i;
}

105
double supra(double d)
{
return d;
}
// Sa se supraincarce o functie cu numar diferit de paramatrii

#include "stdafx.h"
#include <iostream>
using namespace std;

int supra1(int ); // un parametru


int supra1(int ,int ); // doi parametri (aceeasi denumire a
// functiei)

main()
{
cout << supra1(11) << " "; // apelul primei functii
cout << supra1(5,4) << "\n"; //apelul celeilalte functii

return 0;
}

// acum sint definite cele doua functii


int supra1(int i)
{
return i;
}

int supra1(int i, int j)


{
return i*j;
}
// Sa se supraincarece functiile constructor

#include "stdafx.h"

#include <iostream>
#include <stdio.h>
using namespace std;

class data {
int zi, luna, an;
public:
data(char *);
data(int, int, int );
void arata_data();
};

// constructor de initializare cu sir (forma zz/ll/aa)


data::data(char *s)
{
sscanf(s, "%s%*c%s%*c%s", &zi, &luna, &an);
}
// constructor de initializare cu intregi (zi, luna, an)
data::data(int z, int l, int a)
{
zi=z;
luna=l;
an=a;
}
void data::arata_data()

106
{
cout << zi << "/" << luna<< "/"<<an<<"\n";
}

main()
{
data d1(4, 3, 98), d2("10/04/98");

d1.arata_data();
d2.arata_data();

return 0;
}
SUPRAINCARCAREA OPERATORILOR
// Sa se prezinte supraincarcarea operatorului PLUS

#include "stdafx.h"

#include <iostream>
using namespace std;
class loc{
int longit, latit;
public:
loc(){} // necesar pentru constructii de obiecte
// temporare
loc(int lg, int lt) {
longit=lg;
latit=lt;
}
void arata() {
cout << longit << " ";
cout << latit <<"\n";
}
loc operator+(loc ot);
};

loc loc::operator+(loc ot) // supraincarcarea operatorului +


{
loc tmp; // folosim un obiect temporar

tmp.longit=ot.longit+longit; // aici sint operatiile


tmp.latit=ot.latit+latit;

return tmp; // obiectul este returnat


}

main()
{
loc ob1(10,20), ob2(15,25); // se creeaza doua obiecte
// initializate

ob1.arata(); // se va afisa 10 20
ob2.arata(); // se va afisa 15 25

ob1=ob1+ob2; // aici se foloseste supraincarcarea


ob1.arata(); // se va afisa 25 45

return 0;
}

107
// Sa se supraincarce patru operatori

#include "stdafx.h"
#include <iostream>
using namespace std;

class loc{
int longit, latit;
public:
loc(){} // necesar pentru constructii de obiecte
// temporare
loc(int lg, int lt) {
longit=lg;
latit=lt;
}
void arata() {
cout << longit << " ";
cout << latit <<"\n";
}
loc operator+(loc ot);
loc operator-(loc ot);
loc operator=(loc ot);
loc operator++();
};

loc loc::operator+(loc ot) // supraincarcarea operatorului +


{
loc tmp; // folosim un obiect temporar

tmp.longit=ot.longit+longit; // aici sint operatiile


tmp.latit=ot.latit+latit;

return tmp; // obiectul este returnat


}
loc loc::operator-(loc ot) // supraincarcarea operatorului -
{
loc tmp; // folosim un obiect temporar
// atentie la ordinea operanzilor
tmp.longit= longit-ot.longit; // aici sint operatiile
tmp.latit= latit-ot.latit;

return tmp; // obiectul este returnat


}
loc loc::operator=(loc ot) // supraincarcarea operatorului =
{
loc tmp; // folosim un obiect temporar

longit=ot.longit; // aici sint operatiile


latit=ot.latit;

return *this; // aici este returnat chiar obiectul


// care a generat apelarea
}
// Atentie ! urmeaza un operator unar (nu are parametri - oare //
de ce ?)
loc loc::operator++() // supraincarcarea operatorului ++
{
// nu mai folosim un obiect temporar
longit++; // aici sint operatiile
latit++;

108
return *this; // de asemenea este returnat chiar
// obiectul care a generat apelarea, de fapt a operat
// direct asupra obiectului

main()
{
loc ob1(10,20), ob2(15,25), ob3(3,7); // se creeaza
// trei obiecte initializate

ob1.arata(); // se va afisa 10 20
ob2.arata(); // se va afisa 15 25

++ob1; // oare ce se intimpla ?


ob1.arata(); // se afiseaza 11 21

ob2=++ob1;
ob1.arata(); // afiseaza 12 22
ob2.arata(); // afiseaza tot 12 22

ob1=ob2=ob3; // se poate si atribuire multipla


ob1.arata(); // evident se va afisa 3 7
ob2.arata(); // se va afisa tot 3 7

return 0;
}
Matrice, pointeri şi referinţe
//sa se creeze o matrice de obiecte
#include "stdafx.h"
#include <iostream>
using namespace std;

class cl {
int i;
public:
cl(int j){ i = j; }
int da_i() { return i; }
};

main()
{
c1 mo[ 3] = { 1, 2, 3 }; // initializare
int i;
for ( i = 0; i < 3 ; i ++)
cout << mo[ i ] . da_i() << endl;
return 0;
}

//sa se puna in evidenta pointari catre obiecte ( nu preia primul


//element din matrice)
#include<stdafx.h>
#include <iostream>
using namespace std;
class cl {
int i;
public:
cl(int j) { i = j; }
int da_i() { return i; }
};

109
main()
{
cl ob(23), *p;
p = &ob; // da adresa lui ob
cout << p->da_i(); // foloseste -> pentru a apela da_i()
return 0;
}
// Sa se puna pointer prin deplasarea in matrice

#include<stdafx.h>
#include <iostream>
using namespace std;
class cl {
int i;
public:
cl() { i = 0; }
cl(int j) { i = j; }
int da_i() { return i; }
};

main()
{
cl ob[ 3 ] = { 1, 2, 3 };
cl *p;
int i;

p = ob; // preia inceputul matricei


for ( i = 0; i < 3; i++) {
cout << p->da_i() << endl;
p ++; // indica spre urmatorul obiect
}
return 0;
}
// Afisarea unui ponter catre un membru public al clasei
#include<stdafx.h>
#include <iostream>
using namespace std;
class acces_p{
public:
int i;
acces_p(int j) {i=j; }
};

main()
{
acces_p poin(1);
int *p ,i;

p=&poin.i; // se preia adresa lui poin.i

cout << *p; // si se afiseaza cu acces prin pointer


return i;
}
// Sa se puna in evidenta folosirea pointerului THIS
//(adică obiectul care a invocat funcţia : obiect.functie(...) ).
//adica in loc de obiect se oune THIS
//Funcţiile friend nu sînt membri ai clasei, deci nu le sînt pasaţi
pointeri this.
//Funcţiile membre de tip static nu au nici ele un pointer this.
//

110
#include<stdafx.h>
#include <iostream>
using namespace std;
class putere{
double b;
int e;
double rez;
public:
putere(double, int );
double rezultat() {return this->rez; }
};

putere::putere(double baza, int exp)


{
this ->b=baza;
this->e=exp;
this->rez=1;
if (exp==0) return;
for ( ; exp>0; exp--) this->rez=this->rez * this->b;

main()
{
putere x(65.3, 4), y(1.35, 5), z(200.1, 0); // 3 obiecte

cout << x.rezultat() << endl;


cout << y.rezultat() <<endl;
cout << z.rezultat() << endl;

return 0;
}
//Sa se puna in evidenta folosirea pointerului THIS
//(adica obiectul care a invocat functia : obiect.functie(...) )
//acici el se subintelege ca e din clasa curenta

#include<stdafx.h>
#include <iostream>
using namespace std;
class putere{
double b;
int e;
double rez;
public:
putere(double, int );
double rezultat() {return rez;}
};

putere::putere(double baza, int exp)


{
b=baza;
e=exp;
rez=1;
if (exp==0) return;
for ( ; exp > 0; exp--) rez=rez * b;
}

main()
{
putere x(65.3, 4), y(1.35, 5), z(200.1, 0); // 3 obiecte

111
cout << x.rezultat() << endl;
cout << y.rezultat() << endl;
cout << z.rezultat() << endl;

return 0;
}
//Sa se puna in evidenta pointer catre functii si date membru
//ai unei clase
#include<stdafx.h>
#include <iostream>
using namespace std;
class c1{
public:
c1(int i) {val=i; }
int val;
int val_dubla() {return val+val; }
};
main()
{
int c1::*date; // pointer la o data membru
int (c1::*func)(); // pointer la o functie membru
c1 ob1(1), ob2(2); // crearea a doua obiecte

date=&c1::val; // obtinem offsetul pentru val


func=&c1::val_dubla;// iar aici obtinem offsetul pentru
// functia val_dubla()

// acum putem profita de pointerii la membri obtinuti mai sus


cout << "Iata date obtinute cu pointeri la membri :";
cout << ob1.*date << " " << ob2.*date << endl;
cout << "Acum folosim pointeri la functii membre : ";
cout << (ob1.*func)() << " " << (ob2.*func)() << endl;

return 0;
}
//cu pointari sa se puna in evidenta
//transmiterea datelor prin referinta
#include<stdafx.h>
#include <iostream>
using namespace std;
void neg(int *);

main()
{
int in;
in=100;
cout << in << " este negat ";
neg(&in); // se transmite adresa explicit
cout << in << endl;

return 0;
}

void neg(int *i)


{
*i= - *i;
}
//transmiterea datelor explicit prin referinta
#include<stdafx.h>
#include <iostream>

112
using namespace std;
void neg(int &i); // i este referinta

main()
{
int in;
in=100;
cout << in << " este negat ";
neg(in); // nu e nevoie de &
cout << in << endl;

return 0;
}

void neg(int &i)


{
i= - i; // i este referinta deci nu e nevoie de *
}

//explicit transmiterea datelor prin referinta


#include<stdafx.h>
#include <iostream>
using namespace std;
void schimb(int &, int & );

main()
{
int a,b;
a=1;
b=2;

cout << " a si b: " << a << " " << b << " ";
schimb(a, b); // aici schimbam ; vedem ca nu trebuie
// scris cu &
cout << " a si b: " << a << " " << b << " "
;

return 0;
}

void schimb (int &i, int &j)


{
int temp;

temp=i; // nu trebuie sa lucram cu *


i=j;
j=temp;
}
// Transmiterea referintelor catre obiecte
#include "stdafx.h"
#include <iostream>
using namespace std;

class nu_distruge{
int k;
public:
int i;
nu_distruge(int );
~nu_distruge();
void neg(nu_distruge &ob) {ob.i = -ob.i; } // nu se va
// crea obiect temporar

113
};

nu_distruge::nu_distruge(int valinit) // constructorul


{
cout << "Construieste " << valinit << "\n";
k=valinit;
}

nu_distruge::~nu_distruge() // destructorul
{
cout << "Distruge " << k << "\n";
}

main()
{
nu_distruge ob(1); // un obiect initializat

ob.i=10;
ob.neg(ob); // la apel se transmite obiectul prin
// referinta

cout << ob.i << "\n";

return 0;
}

//referinte independente(pasarea argumentelor prin referinţă şi


//obţinerea valorii returnate de funcţie. )
#include "stdafx.h"
#include <iostream>
using namespace std;
main()
{
int a;
int &ref=a; // aceasta e o referinta independenta

a=1;
cout << a << " " << ref << "\n";

ref=10;
cout << a << " " << ref << "\n";

int b=39;
ref=b; // aici, valoarea lui b trece de fapt in a
cout << a << " " << ref << "\n";

ref--; // decrementeaza pe a in realitate


cout << a << " " << ref << "\n";

return 0;

}
Operatorii de alocare dinamică din C++
//Sa se aloce dinamic un intreg si sa se elibereze spatiul
#include "stdafx.h"
#include <iostream>
using namespace std;
#include <stdlib.h>

main()

114
{
int *p;
p=new int; // aloca spatiu pentru un intreg
if (!p) {
cout << "Eroare de alocare\n";
exit(1);
}
*p=190;

cout << "La " << p << " " ;


cout << " este valoarea " << *p << "\n";

delete p;
return 0;
}
//sa se supraincarce operatorii de alocare dinamica
#include "stdafx.h"
#include <iostream>
using namespace std;
#include <stdlib.h>

main()
{
int *p;
p=new int(314); // aloca spatiu pentru un intreg
// dar si initializeaza
if (!p) {
cout << "Eroare de alocare\n";
exit(1);
}
*p=190;

cout << "La " << p << " " ;


cout << " este valoarea " << *p << "\n";

delete p;
return 0;
}
//alocarea dintr-o data a memoriei pentru 10 obiecte
//si eliberarea memoriei
#include "stdafx.h"
#include <iostream>
using namespace std;
#include <stdlib.h>

main()
{
int *p, i; // (ati retinut ca doar primul e pointer ?)

p=new int [10]; // se aloca memorie pentru 10 intregi


if(!p){
cout << "Eroare de alocare\n";
exit(1);
}
for (i=0; i<10; i++) p[i]=i;
for (i=0; i<10; i++) cout << p[i] << " ";

delete [] p; // aici eliberam memoria ocupata de


// cei 10 intregi
}
//sa se puna in evidenta pointarii catre o constanta

115
#include "stdafx.h"
#include <iostream>
using namespace std;
const int* u;
int const* v;
int d = 1;
int* const w = &d;
const int* const x = &d; // (1)
int const* const x2 = &d; // (2)
int main() {} ///:~

116

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