Sunteți pe pagina 1din 54

Cursul 3

De la C la C++, elemente de programare structurat(continuare)



CLASE n C++

Suprancarcarea operatorilor Template uri Alocare dinamic

Declaraie clas Date membru Functii membru

Pointerul this Constructor si operatorul new Destructor si operatorul delete

Manageri: constructori, destructor Functii de acces Implementori (operatori) Functii ajutatoare Functii membru const

POO(C++)

Gh GRIGORAS

Suprancarcare operatori 1
O nou modalitate de a apela o funcie Se pot suprancarca operatorii existeni, cu excepia operatorilor:
:: Operatorul de rezoluie . Operatorul de selectare a membrilor .* Operatorul de selectare prin pointeri la funcii

Nu pot fi introdui operatori noi Nu pot fi schimbate: precedena i asociativitatea

POO(C++)

Gh GRIGORAS

Suprancarcare operatori 2
Sintaxa este cea de la funcii; numele funciei este: operator@ (@ este operatorul ce se suprancarc) Numrul argumentelor depinde de:
Aritatea operatorului (unar sau binar) Locul defininirii: Ca funcie global: 1 pentru unar, 2 pentru binar; Ca funcie membru a unei structuri: 0 pentru unar, 1 pentru binar
POO(C++) Gh GRIGORAS 3

Suprancarcare operatori 3
Apelul:
ca funcii globale:

a @ b @a a@ operator@(a, b) operator@(a)
ca funcii membru:

a @ b @a a.operator@(b) Excepii ++ i -

a@ a.operator@()

prefixai: se respect regula postfixai: un argument fictiv

operator++();// ++ prefixat operator++(int);// ++ postfixat


POO(C++) Gh GRIGORAS 4

Exemplul 1
struct X{ void operator+(int); void operator+(double); X(int); int n; ... }; void operator+(X, X); void operator+(double, X); void f(X a){ a+99; // a.operator+(99) a+5.55; // a.operator+(5.55) 33 + a; // ::operator+(X(33), a) 1.1 + a; // ::operator+(1.1, a) a + a // :: operator+(a, a) }

POO(C++)

Gh GRIGORAS

Exemplul 2
struct Y{ public: Y* operator&(); Y operator&(Y); Y operator++(int); Y operator&(Y, Y); Y operator/(); // };

// // // // //

adresa, operator unar operatorul logic &, binar ++ postfix, unar Eroare, prea multe argumente Eroare, prea putine argumente

POO(C++)

Gh GRIGORAS

Exemplul 3
struct Clock{ Clock tic_tac(); Clock operator++(); Clock operator++(int); int ora, min, ap; // ap=0 pentru AM, 1 pentru PM }; Clock Clock::tic_tac(){ ++min; if(min == 60){ ora++; min = 0; } if(ora == 13) ora = 1; if(ora == 12 && min == 0) ap = !ap; return *this; }
POO(C++) Gh GRIGORAS 7

Exemplul 3
Clock Clock::operator++(){ return tic_tac(); } Clock Clock::operator++(int n){ Clock c = *this; tic_tac(); return c; }

POO(C++)

Gh GRIGORAS

Exemplul 3
ostream& operator<<(ostream& out, Clock c){ out << setfill ('0') << setw(2) << c.ora << ':' << setw(2) << c.min << setfill(' '); if(c.ap) out << " PM"; else out << " AM"; return out; } int main(){ Clock x , y; x.ora = 11;x.min = 59; x.ap = 0; cout << x.ora << x.min << x.ap << endl; y = x++; cout << " x = " << x << endl; cout << " y = " << y << endl; x.tic_tac(); x.tic_tac(); cout << " x = " << x << endl; return 0; }
POO(C++) Gh GRIGORAS 9

Exemplul 3
using namespace std; struct complex{ float re; float im; }; int operator==(complex, complex); int operator!=(complex, complex); complex operator+(complex, complex); complex operator+(int, complex); complex& operator+=(complex&, complex); complex operator-(complex, complex); complex& operator-=(complex&, complex); complex operator*(complex, complex); complex& operator*=(complex&, complex); complex operator/(complex, complex); complex& operator/=(complex&, complex); ostream& operator<<(ostream&, complex&); istream& operator>>(istream&, complex&);
POO(C++) Gh GRIGORAS 10

Exemplul 3
complex operator+(complex z1, complex z2){ z1.re += z2.re; z1.im += z2.im; return z1; } complex operator+(int k, complex z){ z.re += k; z.im += k; return z; } complex& operator+=(complex& z1, complex z2){ z1.re += z2.re; z1.im += z2.im; return z1; }
POO(C++) Gh GRIGORAS 11

Exemplul 3
int operator!=(complex z1, complex z2){ return (z1.re != z2.re) || (z1.im != z2.im); }

ostream& operator<<(ostream& s, complex& z){ s << "(" << z.re << ", " << z.im << ")"; return s; } istream& operator>>(istream& s, complex& z){ s >> z.re >> z.im; return s; }
POO(C++) Gh GRIGORAS 12

Exemplul 4
struct Punct{ int x, y; }; Punct operator*(int n, Punct p){ // Numar * Punct Punct q; q.x = n*p.x; q.y = n*p.y; return q; } bool operator==(Punct p, Punct q){ // p1==p2? return (p.x == q.x && p.y == q.y); } ostream& operator<<(ostream& s, Punct& p){ s << "(" << p.x << ", " << p.y << ")"; return s; }

POO(C++)

Gh GRIGORAS

13

Exemplul 4
istream& operator>>(istream& s, Punct& p){ s >> p.x >> p.y; return s; } Punct p,q; int n = 3; cin >> q; p = n*q; cout << p << q; if(p == q) cout << p egal q; else cout << p diferit q;
POO(C++) Gh GRIGORAS 14

Operatori de conversie
struct X{ public: X(double = 0.0l);//ctor de convesie: double X ~X(); operator int();//operator de conversie: X int private: double dbl; }; //... X::operator int(){ return int(dbl); } X x(3.14); int i = int(x); int j = (int)x; int k = x;
POO(C++) Gh GRIGORAS 15

Operatori de conversie
#include <iostream.h> #include <assert.h> struct Intreg{ public: Intreg(int a = 0) : i(a) {} operator int() const{return i;} private: int i; }; void main(){ Intreg i; i = 12; // i = Intreg(12) int ibis = i; // apel operator int() if (ibis == i) // apel operator int() cout << "Un Intreg: " << i << endl; //apel operator int() Intreg j = 3, k = j, m(k); assert(m + .1416 == 3.1416); // apel operator int() cout << "Sfarsit de program!"<< endl; } /* Un Intreg: 12 Sfarsit de program! */
POO(C++) Gh GRIGORAS 16

Template-uri
//Supraincarcare functii void swap(int& x, int& y){ int aux = x; x = y; y = aux; } void swap(char& x, char& y){ char aux = x; x = y; y = aux; } void swap(float& x, float& y){ float aux = x; x = y; y = aux; }

POO(C++)

Gh GRIGORAS

17

Template-uri
int x = 23, y = 14; char c1 = 'o', c2 = '9'; double u = .5, v = 5.5; swap(x, y); swap(u, v); swap(c1, c2);

Polimorfism parametric:
utilizarea aceluiai nume pentru mai multe nelesuri(polimorfism). nelesul este dedus din tipul parametrilor (parametric).
Gh GRIGORAS 18

POO(C++)

Template-uri
Funcie generic de interschimbare:
template <class T> void swap(T& x, T& y) { tip aux = x; x = y; y = aux; }

int m = 8, n = 15; swap(m, n); // swap<int>(m, n); cout << endl << m << ", " << n << endl; double a = 10.0, b = 20.0; swap(a,b); // swap<double>(m, n); cout << endl << a << ", " << b << endl; complex z1, z2; z1.re = 23.5; z1.im = 33.5; z2.re = 1; z2.im = 2; swap(z1, z2); // swap<complex>(m, n);
POO(C++) Gh GRIGORAS 19

Template-uri
Funcie generic de sortare:
template <class T> void naiveSort(T a[], int n) { for (int i=0; i<n-1; i++) for(int j=i+1; j<n; j++) if (a[i] > a[j]) swap<T>(a[i], a[j]); };

Parametrii generici pot fi i tipuri de baz


template <class T, int n> void naivSort2(T a[]) { for (int i=0; i<n-1; i++) for(int j=i+1; j<n; j++) if (a[i] > a[j]) swap<T>(a[i], a[j]); };

POO(C++)

Gh GRIGORAS

20

Template-uri
La apel, pentru n trebuie transmis o constant:
int i; double x[5] = {2,1,3,5,4}; naivSort<double>(x, 5); for (i=0; i<5; i++) cout << x[i] << ", "; cout << endl; double y[5] = {2,1,3,5,4}; naivSort2<double, 5>(y); for (i=0; i<5; i++) cout << x[i] << ", "; cout << endl; int n = 5; double z[5] = {2,1,3,5,4}; naivSort2<double, n>(z);
POO(C++)

// eroare
21

Gh GRIGORAS

Alocare dinamic
Operatorul new:
Alocare de obiecte simple:
new tip; new tip(parametri);
int* pi = new int; complex* pc = new complex(2., 3.); string *pstr = new string(Sir alocat dinamic);

Alocare de tablouri de obiecte:


Se apeleaz constructorul implicit

new tip[];

double* pt = new double[5]; string *ptstr = new string[30]; int const* q = new int[10];// *q este const const int* q = new int[10];// la fel int* const q = new int[10];// q este const
POO(C++) Gh GRIGORAS 22

Alocare dinamic
Operatorul delete:
Dealocare obiecte simple:

delete pointer; delete pi;


Dealocare tablouri de obiecte:

delete []pointer; delete []pt; delete []ptstr; Pentru tipurile utilizator(clase) la execuia operatorului delete se apeleaz destructorul clasei
Gh GRIGORAS 23

POO(C++)

Alocare dinamic: Exemplu


struct matrice { void init_matrice(int d1, int d2); void free_mem(); int dim1() const { return(s1); } int dim2() const { return(s2); } int** p; int s1, s2; }; istream& operator>>(istream& inp, matrice m); ostream& operator<<(ostream& out, matrice m);

POO(C++)

Gh GRIGORAS

24

Alocare dinamic: Exemplu


void matrice::init_matrice(int d1, int d2) { s1 = d1; s2 = d2; if(d1 <= 0 || d2 <= 0) throw "dimensiune gresita \n"; p = new int*[s1]; if(p == 0) throw "alocare imposibila \n"; for (int i = 0; i < s1; ++i){ p[i] = new int[s2]; if(p[i] == 0) throw "alocare imposibila \n"; } } void matrice::free_mem() { for (int i = 0; i < dim1(); ++i) delete p[i]; delete []p; }
POO(C++) Gh GRIGORAS 25

Alocare dinamic: Exemplu


istream& operator>>(istream& inp, matrice m) { for(int i = 0; i < m.dim1(); ++i) { for(int j = 0; j < m.dim2(); ++j) inp >> m.p[i][j]; } return inp; } ostream& operator<<(ostream& out, matrice m) { for(int i = 0; i < m.dim1(); ++i) { for(int j = 0; j<m.dim2(); ++j) out << m.p[i][j] << ' '; out << endl; } return out; };
POO(C++) Gh GRIGORAS 26

CLASE
O clas n C++ se caracterizeaz prin:
Un nume - identificator O colecie de date membru prin aceste date este reprezentat un obiect. Datele sunt create pentru fiecare obiect (instan a clasei) O colecie de funcii membru tratamente (metode) ce se aplic obiectelor. Un tratament se execut de ctre un obiect ca rspuns la primirea unui mesaj Eventual, o colecie de prieteni: funcii i/sau clase prieten
POO(C++) Gh GRIGORAS 27

CLASE
Specificarea unei clase se face prin numele rezervat class sau struct Specificarea este cuprins, n general, ntr-un fiier header ce va fi partajat de fiierele ce implementeaz clasa i de cele ce utilizeaz clasa Numele clasei este numele unui tip utilizator: se pot declara variabile care au acest tip Componentele unei clase sunt repartizate n trei domenii de protecie: public, protected, private
POO(C++) Gh GRIGORAS 28

CLASE - Declaraie
Declaraie clas cu class:
class <Nume_clasa> {Corp_clasa}; class <Nume_clasa> { //Declaratii membri privati (nerecomandat) public: // Declaratii functii (eventual date) protected: // Declaratii date (eventual metode) private: // Declaratii date (eventual metode) };
POO(C++) Gh GRIGORAS 29

CLASE - Declaraie
Declaraie clas cu struct:
struct <Nume_clasa> {Corp_clasa}; struct <Nume_clasa> { // Declaratii membri public (nerecomandat) public: // Declaratii functii (eventual date) protected: // Declaratii date (eventual metode) private: // Declaratii date (eventual metode) };
POO(C++) Gh GRIGORAS 30

CLASE - Declaraie
Fiecare domeniu de protecie poate fi, fizic, mprit n mai multe regiuni. Ordinea regiunilor poate fi arbitrar Domeniul public:
Componenta este vizibil oriunde Variabilele ce definesc starea unui obiect nu trebuie s fie publice (principiul ncapsulrii) n general, metodele sunt n domeniul public

Domeniul protected: Domeniul private:

Componenta este vizibil n funciile clasei i n clasele derivate Componenta este vizibil doar n funciile clasei i n funciile i clasele prieten
Gh GRIGORAS 31

POO(C++)

Exemplul 1
//FILE stiva1.h class Stack { public: enum { MaxStack = 50 }; void init() { top = -1; } void push( int ) ; int pop() ; bool isEmpty() { return top < 0; } bool isFull() { return top >= MaxStack - 1; } void print() ; private: int top; int arr[ MaxStack ]; };

POO(C++)

Gh GRIGORAS

32

Exemplul 2
//data.h #include <iostream> using namespace std; class Data { public: Data(int o_zi = zi_curenta(), int o_luna = luna_curenta(), int un_an = an_curent()); ~Data() {} void aduna_zi(int n); void aduna_luna(int n); void aduna_an(int n); Data operator ++(int); // postfix Data& operator ++(); // prefix void set_zi(int zi_noua); void set_luna(int ln_noua); void set_an(int an_nou);

POO(C++)

Gh GRIGORAS

33

Exemplul 2
int get_zi() const; int get_luna() const; int get_an() const; friend ostream& operator<<(ostream&, const Data&); static Data azi(); private: int zi, luna, an; static int zi_curenta(); static int luna_curenta(); static int an_curent(); bool esteAnBisect(); int NrZileLuna(); int NrZileAn(); };
POO(C++) Gh GRIGORAS 34

OBIECTE - Declaraie
Declaraie obiecte:
<Nume_clasa> <Nume_Obiect>, ; <Nume_clasa> <Nume_Obiect>(<Parametri_actuali>);

La declararea unui obiect:


Se aloc memorie pentru datele membru Se execut o metod constructor

La ieirea dintr-un bloc


Se apeleaz destructorul (este unic) pentru fiecare din obiectele locale ce nceteaz s mai existe
POO(C++) Gh GRIGORAS 35

OBIECTE - Declaraie
Data d1; // Apel constructor d1.Data() Data d2(5,3,2007); // Apel constr. Data(int,int,int) Data d3[5];// Apel constructor Data() de 5 ori

Obiecte dinamice:
Data *pd = new Data; // apel constructor pd->Data() Data *t = new Data[5];// apel de 5 ori t->Data() delete pd; // se apeleaza pd->~Data() delete [] t; // se apeleaza t ->~Data() de 5 ori

POO(C++)

Gh GRIGORAS

36

Exemplu
#include <iostream> using namespace std; class C { public: C(){cout << "C() ";} ~C(){cout << "~C() ";} private: int i; }; int main(){ C c1; C* p1= new C; { C c[2]; C* p2 = new C; delete p2; } C c[2]; delete p1; return 0; } //C() C() C() C() C() ~C() ~C() ~C() C() C() ~C() ~C() ~C() ~C()
POO(C++) Gh GRIGORAS 37

CLASE - Implementare
Funcii membru(Metode) - Implementare:
n cadrul clasei implementarea se face, n general, inline n afara clasei (precedat de inline pentru implementare inline):
<tip> <Nume_clasa>::<Nume_functie>(<Lista_parametri>) { // Corp functie }

POO(C++)

Gh GRIGORAS

38

CLASE - Implementare
void Data::aduna_luna(int n){ int l = luna + n; if (l > 12) { luna = l % 12; if (luna == 0) luna = 12; an += (l - luna)/12; } else luna = l; } inline void Data::set_an(int an_nou){an = an_nou;}
POO(C++) Gh GRIGORAS 39

CLASE - Mesaje
Apel(Invocare) funcie membru (Mesaj ctre obiect):
<Nume_obiect>. <Nume_functie>(Lista_par_act) <Nume_point_obiect> -> <Nume_functie>(Lista_par_act) (*<Nume_point_obiect>). <Nume_functie>(Lista_par_act)

Data* pd, azi; azi.set_an(2007); azi.set_luna(3); azi.set_zi(5); pd = &azi; pd->get_zi(); (*pd).get_zi();


POO(C++) Gh GRIGORAS 40

CLASE Funcii membru


Funcii manager: constructori, destructor
Data(int, int, int), Data(int, int), Data(int), Data(), Data(const char*) ~Data()

Funcii de acces:
Data::get_zi(), Data::set_an()

Implementori:
void Data::aduna_zi()

Operatori :
Data& Data::operator++()
POO(C++) Gh GRIGORAS 41

CLASE Funcii membru


Funcii ajuttoare:
bool Data::esteAnBisect(){ return (an%400==0)||((an%4==0)&&(an%100!=0)); }

Funcii membru const (nu modific starea obiectului):


int Data::get_zi() const {return zi;} int Data::get_an() const {return an++;}//Eroare!

POO(C++)

Gh GRIGORAS

42

CLASE Metode const


O funcie membru const poate fi apelat att pentru obiecte const ct i pentru obiecte non - const; O funcie membru non - const nu poate fi apelat pentru obiecte const! Exemplu
void f(Data& d, const Data& cd){ int i = d.get_an(); d.aduna_an(2); int j = cd.get_an(); cd.aduna_an(1); // Eroare: cd este obiect const! // } inline int Data::get_an() const{ return an; }
POO(C++) Gh GRIGORAS 43

const face parte din tipul metodei, la implementarea n afara clasei trebuie precizat acest lucru:

CLASE - Pointerul implicit this


Pentru fiecare funcie membru exist o singur instan care este accesibil fiecrui obiect Pointerul this pointer implicit accesibil doar n funciile membru ale unei clase (structuri); pointeaz la obiectul pentru care este apelat funcia int get_luna() const {return this->luna;} int get_luna(Data* d )const {return d->luna;} Data azi(5,3,2007); cout << azi.get_luna() << endl; cout << azi.get_luna(&azi) << endl; (*this) pentru (returnarea) obiectul(ui) curent ntr-o funcie membru
POO(C++) Gh GRIGORAS 44

CLASE - Pointerul implicit this


Exemple:
void Data::setLuna( int m ) { luna = m; //this->luna = m; Echivalent //(*this).luna = m; Echivalent } Data& Data::aduna_an(int n) { if(zi==29 && luna==2 && !esteAnBisect(an+n){ zi = 1; luna = 3; } an += n; return (*this); } d.aduna_zi(1).aduna_luna(1).aduna_an(1);
POO(C++) Gh GRIGORAS 45

CLASE - Pointerul implicit this


#include <iostream> using namespace std; class ExThis{ public: ExThis() :Y(0.0){ cout << "Obiect " << X++ ; cout << " : this = " << this << "\n"; } ~ExThis(){ cout << "Se distruge:" << --X << " this = " << this << "\n"; } private: static int X; double Y; }; int ExThis::X = 0; void main(){ cout << " main: Se declara tabloul Tab[5] de tip ExThis:\n" ; ExThis Tab[5]; cout << " Sfarsit main: Se distrug obiectele din tablou:\n"; }
POO(C++) Gh GRIGORAS 46

CLASE - Pointerul implicit this


/* main: Se declara tabloul Tab[5] de tip ExThis: Obiect 0 : this = 0x0012FF4C Obiect 1 : this = 0x0012FF54 Obiect 2 : this = 0x0012FF5C Obiect 3 : this = 0x0012FF64 Obiect 4 : this = 0x0012FF6C Sfarsit main: Se distrug obiectele din tablou: Se distruge:4 this = 0x0012FF6C Se distruge:3 this = 0x0012FF64 Se distruge:2 this = 0x0012FF5C Se distruge:1 this = 0x0012FF54 Se distruge:0 this = 0x0012FF4C */

POO(C++)

Gh GRIGORAS

47

CONSTRUCTORI
Constructorii unei clase
void Data::init(int z, int l, int a) {zi = z; luna = l; an = a;} Data d; d.init(5,3,2007);

Constructor: o funcie membru cu misiunea de a iniializa obiectele declarate. Dac o clas are constructori, obiectele clasei sunt iniializate la declarare.
Data Data Data Data Data Data
POO(C++)

azi(2); maine(3, 4); acum; Craciun(25 Decembrie); d(5, 3, 2007); d = Data(5, 3, 2007);
Gh GRIGORAS 48

CONSTRUCTORI
Constructor implicit: poate fi apelat fr parametri
Data(int z = 0, int l = 0, int a = 0); Data(int z = ziua(), int l = luna(), int a = anul());

Dac o clas nu are constructori, se apeleaz unul implicit (furnizat de sistemul C++); Dac o clas are constructori, ar trebui s aib i unul implicit ; O clas ce are membri const sau referine trebuie s aib constructori
class X{const int a; const int& b;}; X x; // Eroare, constructorul implicit nu poate // initializa a si b
POO(C++) Gh GRIGORAS 49

CONSTRUCTORI
Constructor i operatorul new:
Data* d = new Data(12, 3, 2006);// d obiect dinamic class Tablou{ public: Tablou(int n=10){p = new char[sz = n];} ~Tablou(){delete[] p;} private: const char* p; int sz; };

Dac o clas are membri pointeri(este necesar alocare dinamic) trebuie definit explicit un constructor i destructorul clasei. Obiectele membru ntr-o clas trebuiesc construite la crearea obiectului compus: alegerea constructorului se face n lista de iniializare a constructorului clasei compuse
POO(C++) Gh GRIGORAS 50

CONSTRUCTORI
class Y{ public: Y(){y = 0;}; Y(int n){y = n;}; private: int y; }; class X{ public: //X(int n):y1(Y::Y()), y2(Y::Y(n)),x(n){} X(int n):y1(), y2(n),x(n){} private: int x; Y y1,y2; }; void main(){ X x(2); }
POO(C++) Gh GRIGORAS 51

DESTRUCTOR
Distruge un obiect n maniera n care a fost construit Are sintaxa: ~<Nume_clasa>(){ } Apelat implicit pentru o variabil(obiect) din clasa automatic la prsirea domeniului de vizibilitate Apelat implicit cnd un obiect din memoria heap, creat cu operatorul new, este ters cu operatorul delete
int main(){ Tablou* p = new Tablou; Tablou* q = new Tablou; // delete p; delete q;//delete p; }
POO(C++) Gh GRIGORAS 52

Creare / distrugere obiecte


Obiect din clasa automatic: creare la (execuia ajunge la) declarare i distrugere la ieirea din domeniul su de vizibilitate; Obiect n memoria heap: este creat cu new i distrus cu delete; Obiect membru nestatic (ca dat membru a altei clase): este creat/distrus cnd un obiect al crui membru este, este creat/distrus Obiect element al unui tablou: este creat/distrus cnd tabloul a crui element este, este creat/distrus
POO(C++) Gh GRIGORAS 53

Creare / distrugere obiecte


Obiect local static: este creat cnd se ntlnete prima dat declaraia sa la execuia programului i este distrus la terminarea programului; Obiect global, obiect n namespace, obiect membru static: este creat odat la nceputul programului i distrus la terminarea programului Obiect temporar: este creat ca parte a evalurii unei expresii i distrus la sfritul expresiei n care apare
POO(C++) Gh GRIGORAS 54