Sunteți pe pagina 1din 50

PROGRAMARE ORIENTAT OBIECT (C++)

Cursul 1
 Scurt introducere n POO
 clase i obiecte
 atribute, metode, stri
 ascunderea informaiei, ncapsulare
 declararea claselor i obiectelor n C++
 constructori i destructori
 exemplu clasa Cont
 Tipuri abstracte de date clase si obiecte
 exemplu clasa Stiva
 Utilizarea bibliotecilor de clase
 stringuri definite de utilizator
 din clasa string a STL
Ce este C++
Este un C mai bun;
Programatorii buni in C au un dezavantaj: au tendina sa
scrie cod C++ in stilul C pierznd beneficiile aduse de C++
Suport abstractizarea datelor
Suport programare orientat obiect
Suport programare generic
 C++ nu a fost proiectat s impuna un anume stil de
programare, el suporta stilurile (paradigmele) tradiionale i
pe cele avansate:
 Programare procedural: Decide ce proceduri sunt
necesare, si alege cei mai buni algoritmi pentru ele
 Programare modular: Decide ce module sunt necesare,
mparte programul asa fel incat datele sa fie ascunse n
module
 Tipuri abstracte de date (Tipuri definite de utilizator):
Decide ce tipuri ii sunt de folos si construiete cte un set
complet de operaii pentru acestea

 Programare orientat obiect (POO): Decide ce clase


sunt necesare, proiecteaz cate un set complet de operaii
pentru acestea si expliciteaz prile comune ale lor prin
relaia de motenire (derivare, generalizare), i folosete
polimorfismul
 Programare generic: Decide algoritmii ce sunt necesari
i parametrizeaz-i pentru a funciona pe o varietate de tipuri
i de structuri de date

CLASE SI OBIECTE o prim viziune


 Un obiect este caracterizat de:
 nume un identificator
 atribute date de un anume tip
 valorile atributelor la un moment dat definesc o stare a
obiectului
 metode (servicii, operaii) funcii ce acceseaz atributele
obiectului modificnd eventual starea acestuia; ele definesc
comportarea obiectului
O clas descrie unul sau mai multe obiecte ce pot fi
precizate printr-un set uniform de atribute(date) i
metode(funcionalitate).
 Orice obiect are memoria sa proprie unde se pstreaz
valorile tuturor atributelor sale
 Orice obiect are un tip; un obiect este o instan a unei
clase
 Clasa definete caracteristicile si comportarea obiectelor

Clasa cont
 Specificarea clasei
 Un cont bancar:
 are un titular, sold, o rat a dobnzii, numar de cont
 se pot efectua operaii de depunere, extragere, actualizare
sold
 Extragerea atributelor:
 titular, sold, rat a dobnzii, numr de cont
 Extragerea metodelor:
 depunere, extragere, actualizare sold
 Completare specificaie
 actualizare sold  data ultimei operaii
Clase - proiectare
 Definiia unei clase presupune:
 combinarea datelor cu operaiile ce se aplic acestora
 ascunderea informaiei

Combinarea datelor cu operaiile


 datele si operaiile ce se aplic asupra lor sunt
incluse n aceeai unitate sintactic; n acest mod
datele i procesele devin legate

ASCUNDERE i NCAPSULARE
 Ascunderea informaiei:
 Modul de structurare a datelor nu este cunoscut: datele
sunt declarate intr-o seciune privat a clasei.
 Accesul la date, pentru consultare, modificare, etc. se face
numai prin intermediul funciilor clasei: acestea sunt
declarate intr-o seciune public a clasei interfaa clasei.
 Pot exista date publice precum si funcii private:
decizia este a programatorului.
 ncapsulare = Combinare + Ascundere
 Datele si funciile (operaiile) care pot aciona asupra
datelor sunt incluse n aceeai unitate sintactic
 n C++ acest lucru se realizeaza prin tipul utilizator struct
sau class
AVANTAJE
 Combinarea datelor:
 definete clar ce structuri de date sunt manevrate i
care sunt operaiile legale asupra lor.
 programul capt modularitate.

 scade riscul alterrii datelor din exterior.


 faciliteaz ascunderea informaiei.
 Ascunderea informaiei:
 programe mai sigure i mai fiabile
 elibereaz clasele utilizator de grija manevrrii datelor
 previne apariia erorilor
AVANTAJE
 ncapsulare:
Combinare + Ascunderea informaiei =
Protejarea datelor
 previne apariia erorilor prin limitarea
accesului la date
 asigur portabilitatea programelor
 faciliteaz utilizarea excepiilor
 interfaa unei clase = operaiile cu care o clas utilizator
poate manevra datele
Structurarea nivelului de acces la informaie
Limitarea accesului la informaie

 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:
 Componenta este vizibil n funciile clasei i n clasele
derivate
 Domeniul private:
 Componenta este vizibil doar n funciile clasei i n
funciile i clasele prieten
 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
 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
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)
};
Exemplu
//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 ];
};
Exemplu
//data.h
#include <iostream>
using namespace std;
class Data {
public:
Daitnat(iunnt_aon_z=i a=n _zciu_rceunrte(n)t)a;(), int
o_luna = luna_curenta(),
~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);

Exemplu
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();
};
OBIECTE - Declaraie
 Declaraie obiecte:
<Nume_clasa> <Nume_Obiect>,C ;
<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

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
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()
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
}
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;}
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,maine (26,3,2007);
azi.set_an(2007);
azi.set_luna(3);
azi.set_zi(5);

pd = &azi;
pd->get_zi();
(*pd).get_zi();
 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++()
 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!
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!

//O
}
 const face parte din tipul metodei, la implementarea n
afara clasei trebuie precizat acest lucru:
inline int Data::get_an() const{
return an;
}
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
 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 azi(2);
Data maine(3, 4);
Data acum;
Data Craciun(25 Decembrie);

Data d(5, 3, 2007);


Data d = Data(5, 3, 2007);
 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
 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
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);
}
 Distruge un obiect n maniera n care a fost construit
 Are sintaxa: ~<Nume_clasa>(){O }
 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;
Data d;
Tablou* q = new Tablou;
//O
delete p;
delete q;//delete p;
//delete d.anul; nu asa
}

 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
 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
Clasa cont
class Cont
{
public:
Cont();
~Cont();
void depune(double);
void extrage(double);
void setDob(double);
private:
char *titular;
double sold;
double rataDob;
char *dataUltOp;
void actualizeazaSold();
void atribuieNrCont();

}
//Clasa cont - implementare
Cont::Cont()
{
titular = NULL;
dataUltOp = NULL;
sold = 0;
rataDob = 0;
atribuieNrCont();
}
Cont::~Cont()
{
delete titular;
delete dataUltOp;
}
void Cont::depune(double suma)
{
sold += suma;
}
void Cont::extrage(double suma)
{
actualizeazaSold();
if(suma > sold)
throw "Sold insuf.";
sold -= suma;
}
Clasa cont - utilizare
void main()
{
Cont cont;
cont.depune(2000);
}
cont.sold += 2000;
error C2248: 'sold' : cannot access private
member declared in class 'Cont'

Clase si Obiecte - Tipuri abstracte de dat


 Clasa, Obiect o alta viziune (definiie):
 O clasa este o implementare a unui tip de dat abstract.
Ea definete:
 atribute care implementeaz structura de dat respectiv
 metode care implementeaz operaiile tipului de dat
abstract.
 Un obiect este o instan a unei clase. El este unic
determinat de numele su i definete o stare reprezentat
de valorile atributelor sale la un moment dat
Stiva
 tipul de data abstract Stiva
 entitati de tip dat: liste LIFO
 operaii:
 push()
 pop()
 top()

Utilizarea de clase
 exist multe bibloteci de clase
 STL

 MFC
 etc
 pentru utilizare, trebuie cunoscut doar interfaa
(elementele publice)
 nu intereseaz implementarea
 programul care utlizeaz clasa este independent de
implementarea clasei
 Exemplu: string
 my-string.h
 STL
// my_string.h
class string
{
public:
// Constructori/destructori
string();
string(char* new_string);
string(const string& new_string);
...
~string();
Utilizarea de clase
// Operatori
friend string operator+ (const string& lhs, const string&
rhs);
string& operator+= (const string& a_string);
string& operator= (const string& a_string);
friend bool operator< (const string& lhs, const string&
rhs);
friend bool operator> (const string& lhs,
const string& rhs);
friend bool operator== (const string& lhs, const string&
rhs);

friend ostream& operator<< (ostream& os, const


string&a_string);
private:
char* char_arr;
int string_length;
};
//Utilizarea de clase
string s1(123); // creare sir dintr-un numar
string s2; // creare sir vid
s2 = string("abc") + s1; ////
//operatorul de atribuire
s1 = s2 ; // operatorul de atribuire
cout << s1 << endl << s1 + s2 << endl;
// scrierea in fluxul standard de iesire
s1 = "armata"; // apelare constructor
// si apoi operator de atribuire
cout << s1 << endl;
s2 = "armata";
cout << ((s1 == s2)?1:0) << endl;
// operatorul de testare a egalitatii
string s3(s2); // creare prin copiere
//(apel constructor de copiere
O
Utilizarea de clase
 STL (Standard Template Library)
#include <string>
using namespace std

Cont versiunea 2
// cont.h char* ==> string
#include <string>
using namespace std;

class Cont
{
public:
Cont();
Cont(string nume, double soldInit);
~Cont();
void depune(double);
void extrage(double);
void setDob(double);
private:
string titular;
string nrCont;
double sold;
double rataDob;
string dataUltOp;
void actualizeazaSold();
void atribuieNrCont();
}
// cont.cpp
#include "cont.h"
Cont::Cont()
{
dataUltOp = "";
sold = 0;
atribuieNrCont();
}
Cont::Cont(string nume, double soldInit) : titular(nume),
sold(soldInit)
{
// dataUltOp = azi();
}
void Cont::depune(double suma)
{
sold += suma;

// demo.cpp
#include "cont.h"
void main()
{
Cont cont("Ionescu", 10000);
cont.extrage(2000);
}

Funcii: suprancarcare
 C++ dispune de un mecanism de verificare a tipului mult
mbunatit fa de C.
 Ca i n viaa real, nelesul unui cuvnt poate fi dedus
din context
 Utilizarea aceluiai cuvnt cu nelesuri diferite
suprancrcare (overloading)
 n loc de a folosi, de pild print_char(),print_int(),
print_float(), folosim print(char), print(int), print(float)
 Numele funciilor pot fi suprancrcate: mai multe funcii, n
care numrul i/sau tipul parametrilor difer, pot avea
acelai nume:
int f(int x, int y){return x*y;}
double f(int x, int y){return x*y;}
int f(double x, int y){return x+y;}
void main(){
cout << f(5.3, 3)<< ' ';
cout << f(2.f,3)<< ' ';
cout << f(2,3) << ' ';

}
// 8 5 6
 Funciile suprancrcate pot aparine i unei clase:
void f();
class X { void f();}
 Funciile cu acelai nume nu pot diferi doar prin tipul
returnat:
double f(int);
int f(int); // eroare pentru ca f(40) este ambiguu
 Constructorii unei clase sunt funcii suprancrcate
 Parametrii funciilor pot avea valori implicite:
void add3(int& s, int a, int b, int c = 0){
s = a + b + c;
}
add3(s1, 3, 5, 9);
add3(s2, 5, 6);
 Atenie la ambiguiti (suprancrcare + parametri
implicii):
int f(int x = 0, int y = 0);
double f(int z);
// apelul f(7) este ambiguu!

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

 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
 prefixai: se respect regula
 postfixai: un argument fictiv
operator++();// ++ prefixat
operator++(int);// ++ postfixat
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;
}
Clock Clock::operator++(){
return tic_tac();
}

Clock Clock::operator++(int n){


Clock c = *this;
tic_tac();
return c;
}
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.set_ora(11);
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;
}
struct complex{
float re;
float im;
public:
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);
friend ostream& operator<<(ostream&, complex&);
friend istream& operator>>(istream&, complex&);
}
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;
}
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;

}
#include <stdio.h>
class Point
{
protected:
unsigned x, y;
public:
Point();
Point(Point &p);
Point(unsigned X, unsigned Y);
~Point();
unsigned long Arie();
unsigned GetX();
unsigned GetY();
void SetX(unsigned X);
void SetY(unsigned Y);
Point& operator += (Point __p);
Point& operator -= (Point __p);
Point operator + (Point __p);
Point operator - (Point __p);
Point& operator = (Point __p);
int operator == (Point __p);
int operator != (Point __p);
int operator < (Point __p);
int operator > (Point __p);
int operator <= (Point __p);
int operator >= (Point __p);
};
Point::Point()
// constructor implicit
{
x = 0;
y = 0;
}

Point::Point(unsigned X, unsigned Y)
{
x = X;
y = Y;
}
Point::Point(Point &p)
{
x = p.x;
y = p.y;
}
Point::~Point()
{
}
unsigned Point::GetX()
{
return x;
}
unsigned Point::GetY()
{
return y;
}
void Point::SetX(unsigned X)
{
x = X;
}
void Point::SetY(unsigned Y)
{
y = Y;
}
unsigned long Point::Arie()
{
return this->x * this->y;
}
Point& Point::operator += (Point __p)

{
x += __p.x;
y += __p.y;
return *this;
}
Point& Point::operator -= (Point __p)
{
x -= __p.x;
y -= __p.y;
return *this;
}
Point Point::operator + (Point __p)
{
return Point(x + __p.x, y + __p.y);
}
Point Point::operator - (Point __p)
{
return Point(x - __p.x, y - __p.y);
}
int Point::operator == (Point __p)
{
return x == __p.x && y == __p.y;
}
int Point::operator != (Point __p)
{
return !(*this == __p);
}
int Point::operator < (Point __p)
{

return x < __p.x && y < __p.y;


}
int Point::operator > (Point __p)
{
return x > __p.x && y > __p.y;
}
int Point::operator <= (Point __p)
{
return x <= __p.x && y <= __p.y;
}
int Point::operator >= (Point __p)
{
return x >= __p.x && y >= __p.y;
}
Point& Point::operator = (Point __p)
{
x = __p.x;
y = __p.y;
return *this;
}
void main()
{
Point *p = new Point;
// p->x = 5; // operatie imposibila: x este membru privat
// p->y = 8; // operatie imposibila: y este membru privat
p->SetX(5); // corect: acces la variabila x prin intermediul
functiei
p->SetY(8);
printf("Aria = %d\n", p->Arie());
delete p;

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:
new tip[O];
 Se apeleaz constructorul implicit
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
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
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);
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;
}
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;
};
 Pointeri la
date membru
metode
 Suprancrcare operatori
 Constructor de conversie vs.Operator de conversie
 Clase parametrizate
Pointeri la date membru
Operatorii .* i ->*
 Declaraie:
tip Nume_clasa::*point_membru;
tip Nume_clasa::*point_membru =
&Nume_clasa::Nume_membru;
 Utilizare
Nume_clasa obiect, *point_obiect;
obiect.*point_membru = C
point_obiect ->*point_membru = C
Pointeri la metode
 Declaraie

tip (Nume_clasa::*point_func)(parametri);
tip (Nume_clasa::*point_func)(parametri) =
&Nume_clasa::Nume_metoda;
 Utilizare:
(obiect.*point_func)(parametri);
(point_obiect ->*point_func)(parametri);
 Un pointer la o funcie membru, cand se instantiaza,
trebuie s se potriveasc cu functia respectiva n trei
elemente:
 numrul i tipurile argumentelor
 tipul valorii returnate
 tipul clasei a crei membru este
//Pointeri la functii membru
class C{
public:
void f(int n=5) const {cout << "apel C::f(" << n <<")" <<
endl;}
void g(int n) const {cout << "apel C::g(" << n <<")" <<
endl;}
void h(int n) const {cout << "apel C::h(" << n <<")" <<
endl;}
void i(int n) const {cout << "apel C::i(" << n <<")" <<
endl;}
};
void main(){
C c;
C* pc = &c;
void (C::*p_metoda)(int=0) const = &C::h;
(c.*p_metoda)(7);
(pc->*p_metoda)();
p_metoda = &C::f;
(pc->*p_metoda)(8);
(c.*p_metoda)();
c.f();

}
// apel C::h(7) apel C::h(0) apel C::f(8) apel C::f(0) apel
C::f(5)
Exemplu
Atenie la declararea pointerilor
class Ex{
public:
int fct(int a, int b){ return a+b;}
};
//typedef int (Ex::*TF)(int,int);
typedef int (*TF)(int,int);
void main(){
Ex ex;
TF f = Ex::fct; // eroare: f nu e pointer
// al clasei Ex
cout << (ex.*f)(2,3) << "\n";
}
 Operatorii binari se definesc fie ca funcii membru nestatic
cu un argument sau funcii
nemembru cu 2 argumente
Suprancarcare operatori: operator@
 Operatorii unari se definesc fie ca funcii membru nestatic
fr argumente (cu un argument int pentru postfix) sau
funcii nemembru cu 1 argument (2 argumente postfix);
 operator=, operator[], operator() i
operator-> trebuie definii ca funcii membru nestatic; asta
asigur c primul operand este lvalue
Suprancarcare operatori
 operator<< i operator>> nu pot fi definite ca metode; n
std sunt definii aceti operatori i redefinirea ca metode ar
nsemna modificarea claselor din std ceea ce este imposibil;

 operator<< i operator>> nu pot fi definite ca friend dac


se folosete std;
 Pentru un operator binar x@y unde x este de tip X iar y de
tip Y sistemul procedeaz astfel:
 Dac X este o clas se determin dac X sau clasa sa de
baz definete operator@ ca membru; dac da se folosete
acest operator
 Dac nu, se caut declaraia lui operator@ n contextul
ce conine x@y apoi n namespace-ul lui X, n namespaceul lui Y i se ncearc aplicarea celui ce se potrivete mai
bine. Condiia este ca cel puin un operand s fie de
tip(clasa) utilizator.
Suprancarcare operator []
#include <iostream>
using namespace std;
class Cstring{
public:
Cstring(char* s = "", int l = 0) ;
Cstring(const Cstring&);
char& operator[](int);
Cstring& operator=(const Cstring&);
int get_lung() { return lung;}
private:
char* rep;
int lung;
};
char& Cstring::operator[](int i){return *(rep+i);}
Cstring::Cstring(char* s, int
l):rep(s),lung((l==0)?strlen(s): l)
{
cout << "Sirul : '"<< rep;
cout << "' are lungimea : " << lung << endl;
}

int main(){
Cstring p1("Popescu Ion"), p2("Ionescu Paul");
cout << " \nSirul p1 folosind operator[] : ;
cout << endl;
for ( int i = 0; i < p1.get_lung(); i++)
cout << p1[i];
p1 = p2;
cout << " \nNoul sir p1 folosind operator[]: ;
cout << endl;
for ( i = 0; i < p1.get_lung(); i++)
cout << p1[i];
return 0;
}
Operator () Obiecte funcii
class Matrice{
public:
enum { max_Size = 20};
Matrice(int s1, int s2) :size1(s1), size2(s2){}
int& operator()(int, int);
int get_s1(){return size1;}
int get_s2(){return size2;}
private:
int a[max_Size];
int size1,size2;
};
int& Matrice::operator()(int i, int j){
if(i < 0 || i >= size1)
throw "Primul indice gresit\n";
if(j < 0 || j >= size2)
throw "Al doilea indice gresit\n";
return a[i*size2 + j];
}
int main(){
Matrice a(3, 4);

int i, j;
for (i = 0; i < a.get_s1(); i++)
for(j =0; j < a.get_s2(); j++)
a(i, j) = 2*i + j;
for (i = 0; i < a.get_s1(); i++) {
for(j =0; j < a.get_s2(); j++)
cout << a(i, j) << " ";
cout << endl;
}
try{
cout << a(1, 2) << endl;
cout << a(2, 8) << endl;
}
catch(char* s){cout << s ;}
return 0;
}
/*
0123
2345
4567
4
Al doilea indice gresit
*/
CLASE: Suprancrcare operatori
 Minimizarea numrului funciilor ce au acces direct la
reprezentare:
 Operatorii ce modific valoarea primului argument, ca
membri (ex. +=)
 Operatorii ce produc noi valori, ca funcii externe (ex. +, -,
)
class complex{
public:
complex& operator+=(const complex a);
//O

private:
double re, im;
};
inline complex& complex:: operator+=(const complex
a){
re += a.re; im += a.im; return *this;
}
complex operator+(complex a, complex b){
complex s = a;
return s+= b;
}
CLASE: Constructor de conversie
 Constructorul de conversie definete o conversie(ce se
aplic implicit) de la un tip (de baza) la un tip utilizator
X::X(tip_de_baza m)

CLASE: Constructor de conversie


 Constructorul de conversie poate suplini definiiile unor
operatori; pentru clasa complex nu-i necesar a
defini:
complex operator+(double, complex);
complex operator+(complex, double);
 Un constructor de conversie nu poate defini:

 O conversie implicit de la un tip utilizator la un tip de


baz
 O conversie de la o clas nou la o clas definit anterior,
fr a modifica declaraiile vechii clase
 Soluia: Operatorul de conversie
 este o funcie membru:
X::operator T()const;
care definete o conversie de la tipul X la tipul T
 Exemplu:
class Clock{
public:
Clock(int = 12, int = 0, int = 0);
Clock tic_tac();
friend ostream& operator<<(ostream&, Clock&);
Clock operator++();
Clock operator++(int);
operator int(); // Conversie Clock --> int
// Ora 8:22 AM devine 822
// Ora 8.22 PM devine 2022
private:
int ora;
int min;
int ap; // 0 pentru AM, 1 pentru PM
};
 Ambiguitate constructor de conversie/operator de
conversie:
class Apple {
public:
operator Orange() const; // Apple -> Orange
};
class Orange {
public:
Orange(Apple); // Apple -> Orange

};
void f(Orange) {}
int main() {
Apple a;
f(a);
}
//error C2664:'f' : cannot convert parameter 1 from
//'class Apple' to 'class Orange'
CLASE: Conversie
 Ambiguitate operatori conversie/suprancrcare funcii:
class Orange {};
class Pear {};
class Apple {
public:
operator Orange() const; // conversie Apple -> Orange
operator Pear() const; // conversie Apple -> Pear
};
// Supraincarcare eat():
void eat(Orange);
void eat(Pear);
int main() {
Apple c;
eat(c); // Error: Apple -> Orange or Apple -> Pear ???
}
Clase parametrizate
 Programare generic : programare ce utilizeaz
tipurile ca parametri
 n C++ - mecanismul template: clase template,
funcii template
 Programatorul scrie o singur definiie template
iar C++, pe baza parametrilor, genereaz
specializri care sunt compilate cu restul
programului surs

 O funcie template poate fi suprancrcat cu:


 Funcii template cu acelai nume dar parametri
template diferii
 Funcii non template cu acelai nume dar cu ali
parametri
 Clasele template se mai numesc tipuri
parametrizate
 Declaraie template:
template < lista_argumente_template > declaratie
lista_argumente_template :: argument_template|
lista_argumente_template, argument_template
argument_template :: tip_argument|declaratie_argument
tip_argument :: class identificator|typename identificator
declaratie_argument::<tip> identificator
declaratie:: declaraia unei clase sau funcii
template< class T, int i > class MyStack{};
template< class T1, class T2 > class X{};
template< typename T1, typename T2 > class X{};
template<class T> class allocator {};
template<class T1, typename T2 = allocator<T1> >
class stack { };
stack<int> MyStack; // al doilea argument este implicit
class Y {...};
template<class T, T* pT> class X1 {...};
template<class T1, class T2 = T1> class X2 {...};
Y aY;
X1<Y, &aY> x1;
X2<int> x2;
 Funciile membru ale unei clase template sunt
funcii template parametrizate cu parametrii
clasei template respective
 Definirea membrilor unei clase template:

 Definiie inline, la specificarea clasei nu este


specificat explicit template
 Definiie n afara specificrii clasei trebuie declarat
explicit template:
template <lista_argumente_template >
nume_clasa_template<argum>::nume_functie_membru(para
metri)
{
//Corp functie
}
 Compilatorul nu aloc memorie la declararea unui
template
 Instaniere template: procesul de generare a
unei declaraii de clas (funcie) de la o
clas(funcie) template cu argumente
corespunztoare
template class MyStack<class T,int n>{O};
template class MyStack<int, 6>;
template MyStack<int, 6>::MyStack();
template<class T> void f(T) {...}
template void f<int> (int);
template void f(char);
Clase parametrizate Exemplul 1
template <class Elt>
class Cell
{
public:
Cell();
Cell(const Cell&); // constructor de copiere
~Cell();
Elt getVal() const;
void setVal(Elt);
Cell& operator =(const Cell&);

private:
Elt* val;
};
template <class Elt>
Cell<Elt>::Cell()
{
val = new Elt;
template <class Elt>
Cell<Elt>::Cell(const Cell<Elt>& c)
{
val = new Elt;
*val = *(c.val);
}
template <class Elt>
Cell<Elt>::~Cell()
{
delete val;
}
template <class Elt>
Cell<Elt>& Cell<Elt>::operator =(const Cell<Elt>& c)
{
*val = *(c.val);
return *this;
}
#include "cell.h"
template <class Elt>
class Array
{
public:
Array(int = 1);
Array(const Aray&);
~Array();
Elt get(int);

void set(int, Elt);


Array& operator =(const Array&);
Cell<Elt>& operator [](int)
const Cell<Elt>& operator [](int) const;
private:
Cell<Elt> *arr;
int nOfComp;
};
template <class Elt>
Array<Elt>::Array(int nMax)
{
arr = new Cell<Elt>[nMax];
if(arr == NULL) throw Memorie insuficienta ";
nOfComp = nMax;
};
template <class Elt>
Array<Elt>::~Array()
{
delete[] arr;
};
template <class Elt>
Elt Array<Elt>::get(int i)
{
if((i<0)||(i>=nOfComp)) throw "Index gresit.";
return arr[i].getVal();
};

Template: Suprancrcare operatori


template <class Elt>
Cell<Elt>& Array<Elt>::operator [](int i)
{
if((i<0)||(i>=nOfComp)) throw "Index out of range.";
return arr[i];

}
// pentru a sorta tablouri de celule de int-uri
// trebuie definit operatorul de comparare:
bool operator >(const Cell<int>& x, const Cell<int>& y)
{
return x.getVal() > y.getVal();
}
// sortare prin insertie
template <class T>
void insert_sort(Array<T>& a, int n)
{
int i,j;
Cell<T> temp;
for(i=1;i<n;i++) {
temp = a[i];
j=i-1;
while((j >= 0) && (a[j] > temp)) {
a.set(j+1, a[j].getVal());
j--;
}
if (i != (j-1))
a.set(j+1, temp.getVal());
}
}
typedef Cell<int> Int;
typedef Cell<char> Char;
Clase parametrizate - Exemplu 2
template <class T>
class Vector
{
public:
Vector(int=0);
T& operator [](int);

const T& operator [](int) const;


// O
private:
T* tab;
int n;
};
template <class T>
class Matrice
{
public:
Matrice(int=0, int=0);
Vector<T>& operator [](int);
const Vector<T>& operator [](int) const;
private:
Vector<T>* tabv;
int m, n;
};
Clase parametrizate - Exemplu 2
template <class T>
T& Vector<T>::operator [](int i)
{
cout << "Vector<T>::operator [](int i)" << endl;
return tab[i];
}
template <class T>
const Vector<T>& Matrice<T>::operator [](int i) const
{
cout << "Matrice<T>::operator [](int i) const" << endl;
if (i < 0 || i >= m) throw "index out of range";
return tabv[i];
}
Vector<int> v(5);
v[3] = 3; // apel varianta nonconst
const Vector<int> vv(5);

vv[4] = 4;// apel varianta const


Matrice<double> m(3,5);
m[1][2] = 5.0;
const Matrice<double> mm(3,5);
mm[2][3] = 7.0;
Clase parametrizate
 O versiune a unui template pentru un
argument template particular este numit o
specializare
 O definiie alternativ pentru o clas(funcie)
template ( de ex. pentru a funciona cnd
argumentul template este pointer) este
numit specializare definit de utilizator
Clase parametrizate - Specializri
template <class T>
class Vector
{
public:
Vector(int=0);
T& operator [](int);
const T& operator [](int) const;
private:
T* tab;
int n;
};
 Specializri:
Vector<int> vi;
Vector<Punct*> vpp;
Vector<string> vs;
Vector<char*> vpc;
Clase parametrizate - Specializri
 Specializare a clasei Vector<T> pentru pointeri la void:

template<> class Vector<void*>{


// specializare fara parametri template
void** p; // O
};
 Specializare a clasei Vector<T> pentru pointeri la T:
template<class T> class Vector<T*>{
// specializare cu parametri template
//O
Clase parametrizate - Specializri
template <class T>
void swap(T& x, T& y){
T t = x; x = y; y = t;
}
 Specializare pentru Vector<T> :
template <class T>
void swap(Vector<T>& a, Vector<T>& b){
a.swap(b);
}
 n clasa Vector<T>, metoda:
template <class T>
void Vector<T>:: swap(Vector<T>& a){
swap(v, a.v);
swap(sz, a.sz);
}
Clase parametrizate
 Dou instanieri ale unei clase template sunt
echivalente dac parametrii template ce
reprezint tipuri sunt aceeai iar ceilali au aceleai valori
MyString<char> s1;
MyString<unsigned char> s2;
typedef unsigned char Uchar;
MyString <Uchar> s3;

Clase parametrizate - friend


 Funcii(clase) friend n clase template:
 Dac funcia friend acceseaz un parametru
template, aceasta trebuie s fie template. n
acest caz o instaniere este friend doar pentru
instanierile clasei template cu aceiai parametri
(friend legat).
 Prieteni template nelegai - are ali parametri
template
 Dac funcia friend nu acceseaz parametri
template , este friend pentru toate instanierile
clasei
Clase parametrizate - friend
template <class T> class X
{
//..
friend void f1();
// f1 friend pentru toate specializarile
friend void f2(X<T>& );
// f2(X<float>&) friend pentru X<float>
friend class Y;
friend class Z<T>;
friend void A::f3();
friend void C<T> :: f4(X<double>&);
//O
};
Clase parametrizate
 Membri statici n template uri
 Fiecare specializare a unei clase template
are copia proprie a mebrilor static, att
date ct i funcii
 Datele statice trebuiesc iniializate,
global sau pe specializri

template<class T, int n>


class ClasaN{
static const int cod;
//
};
template<class T, int n>
const int ClasaN<T, n>::cod = n;
template<>
const int ClasaN<int, 10>::cod =50

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