Detyrë: Të tregohet dalja në ekran për kodin në vazhdim.
int v[4] = { 6, 2, 7, 4 };
cout << *(v + 1) + 1;
Detyrë: Të tregohet dalja në ekran për kodin në vazhdim.
int v1[3] = { 1, 2, 3 };
int v2[3] = { 4, 5, 6 };
int *p[2] = { v1, v2 };
cout << 2 * *(*(p + 1) + 1);
Supozojmë një strukturë të të dhënave Pika
e cila paraqet dyshën e numrave (x,y)
:
struct Pika {
double x;
double y;
};
Shpesh kemi funksione të cilat ndërveprojnë me këtë strukturë:
bool baraz(Pika p1, Pika p2) {
return p1.x == p2.x && p1.y == p2.y;
}
double distanca(Pika p1, Pika p2) {
return sqrt(
pow(p1.x - p2.x, 2) + pow(p1.y - p2.y, 2)
);
}
double distanca_nga_qendra(Pika p) {
return sqrt(pow(p.x, 2) + pow(p.y, 2));
}
string toString(Pika p) {
stringstream ss;
ss << "(" << p.x << ", " << p.y << ")";
return ss.str();
}
Pika konstrukto(double x, double y) {
Pika p = { x, y };
return p;
}
Pika p1 = konstrukto(6.0, 3.5);
Pika p2 = konstrukto(4.2, 7.1);
cout << "Distanca mes pikes p1=" << toString(p1)
<< " dhe pikes p2=" << toString(p2)
<< " eshte d=" << distanca(p1, p2)
<< endl;
if (baraz(p1, p2)) {
cout << "Pikat jane te barabarta.";
} else {
cout << "Pikat jane te ndryshme.";
}
Stili i tillë i programimit njihet si programim procedural.
Ekziston një stil tjetër i programimit i cili grupon të dhënat dhe funksionet mbi to në një njësi të vetme që quhet klasë.
Stili i programimit me klasa quhet programimi i orientuar në objekte (POO).
Klasa përshkruan strukturën e të dhënave si dhe ofron funksione të cilat veprojnë mbi ato të dhëna.
Të dhënat e klasës njihen si fusha, ndërsa funksionet e klasës njihen si metoda.
Të dhënat e klasës deklarohen sikur te strukturat:
class Pika {
double x;
double y;
};
Realisht, në C++ nuk ka dallim teknik ndërmjet strukturës dhe klasës.
Kontrollimi i qasjes (private, public)
Fushat private mund të lexohen vetëm nga funksionet brenda klasës.
Fushat publike mund të lexohen nga cilido bllok.
class Pika {
public: double x;
private: double y;
};
int main() {
Pika p;
p.x = 5.0; // OK.
p.y = 3.5; // Gabim, ndalohet leximi nga blloku i jashtëm.
return 0;
}
Në disa raste dëshirojmë t’i mbajmë fushat private me qëllim të ndalimit të qasjes nga blloqet e jashtme.
Kjo është një veçori kritike për arritjen e enkapsulimit.
Nëse nuk ceket, klasat e kanë qasjen e nënkuptuar private, ndërsa strukturat e kanë publike.
Nuk ka dallim tjetër ndëmjet strukturave dhe klasave.
Funksionet e klasës deklarohen bashkë me të dhënat:
class Pika {
private:
double x;
double y;
public:
double distanca_nga_qendra() {
return sqrt(pow(x, 2) + pow(y, 2));
}
};
Thirrja e metodës bëhet përmes operatorit të qasjes sikur te fushat:
Pika p = ...;
cout << p.distanca_nga_qendra();
Në këtë rast funksioni merr vlerat e pikës p
.
class Pika {
private: double x, y;
public: bool baraz(Pika tjeter) {
return x == tjeter.x && tjeter.y == tjeter.y;
}
};
int main() {
Pika p1 = ..., p2 = ...;
if (p1.baraz(p2)) cout << "Te njejta";
else cout << "Te ndryshme";
return 0;
}
Vini re se si parametri i parë i funksionit sikur p1
në baraz(p1,p2)
tani bëhet implicit duke marrë formën p1.baraz(p2)
.
Argumenti implicit që paraqet referencën kontekstuale të objektit aktual në POO quhet this
.
Vlera kontekstuale this
është pointer për objektin aktual.
class Personi {
private:
string emri;
int mosha;
public:
void shtyp_infot() {
cout << "Emri: " << this->emri << endl;
cout << "Mosha: " << this->mosha << endl;
}
};
Nëse kemi 2 variabla p1
dhe p2
, me funksione të zakonshme kemi shënuar:
shtyp_infot(p1);
shtyp_infot(p2);
Me metoda (stili i POO) e shkruajmë:
p1.shtyp_infot();
p2.shtyp_infot();
Edhe pse po duket se thirrja p1.shtyp_infot()
nuk po merr parametra,
ajo realisht mban referencën e variablës p1
gjatë thirrjes së funksionit.
Thirrjet p1.shtyp_infot()
dhe p2.shtyp_infot()
japin rezultate të ndryshme
pasi që ekzekutohen në kontekste të ndryshme.
Variablat tipi i të cilave është klasë i quajmë objekte ose instanca.
Konstruktori është një funksion i veçantë i cili thirret gjatë krijimit të instancës.
Zakonisht përdoren për të inicializuar gjendjen e klasës duke i dhënë vlera fushave.
Konstruktori shkruhet si metodë e cila ka emrin e klasës dhe nuk ka tip kthimi.
class Pika {
private:
double x;
double y;
public:
Pika(double x, double y) {
this->x = x;
this->y = y;
}
};
Konstruktorët mund të mbingarkohen.
Konstruktori thirret gjatë krijimit të instancës.
Thirrjet e mëposhtme janë ekuivalente:
int main() {
Pika p1 = Pika(2.5, 3);
Pika p2(2.5, 3);
return 0;
}
Konstruktori më së shpeshti përdoret për të vendosur vlera në fusha.
class Studenti {
private:
int mosha;
double notaMesatare;
public:
Studenti(int mosha, double notaMesatare) {
this->mosha = mosha;
this->notaMesatare = notaMesatare;
}
}
Vini re se dykuptimësinë e identifikatorëve e tejkalojmë përmes qasjes eksplicite me this
.
Copy constructor
Në C++ secila klasë ka një konstruktor special për kopjim të objektit.
Zakonisht kjo mund të shkaktojë sjellje të papritura, prandaj shpesh do ta ndalojmë.
class Studenti {
public:
// Konstruktori i kopjimit.
Studenti(const Studenti&) { ... }
// Operatori i shoqërimit.
Studenti& operator=(const Studenti&) { ... }
};
Destruktori është bllok kodi që thirret:
Zakonisht përdoret për lirim të resurseve.
Shkruhet në formën ~Klasa() { ... }
.
Nuk merr parametra e as nuk kthen asgjë.
class Klasa {
private:
int* data;
public:
Klasa() { // Konstruktori
this->data = new int { 0 };
}
~Klasa() { // Destruktori
delete this->data;
}
};
Enkapsulimi i fushave private
Zakonisht e kontrollojmë qasjen në fusha me dy metoda publike getX()
dhe setX(x)
.
class Studenti {
private:
int mosha;
public:
int getMosha() {
return this->mosha;
}
void setMosha(int mosha) {
this->mosha = mosha;
}
};
Detyrë: Të shkruhet klasa Studenti
e cila ka:
emri
, mbiemri
, mosha
, notat[5]
nota(i)
e cila merr notën në pozitën i
.notaMesatare()
.emriPlote()
e cila kthen emrin dhe mbiemrin e bashkuar.shtyp()
e cila shtyp në ekran të dhënat e studentit.Detyrë: Të shkruhet klasa Pika
e cila ka:
x
dhe y
(nr. real).Pika(x,y)
dhe metodat mbështjellëse të fushave.distanca(Pika tjeter)
.shtyp()
që shtyp në ekran kordinatat në formën (x,y)
, psh. (4,3)
.Detyrë: Të shkruhet klasa Rrethi
e cila ka:
rrezja
(nr. real) dhe qendra
(e tipit Pika
nga detyra e kaluar).Rrethi(qendra,rrezja)
.siperfaqja()
dhe perimetri()
.distanca(Rrethi tjeter)
e cila llogarit distancën mes qendrave të rrathëve.shtyp()
që shtyp në ekran qendrën dhe rrezen e rrethit.Detyrë: Të krijohet një varg me 5 instanca të tipit Rrethi
nga detyra e kaluar.
shtyp()
.Detyrë: Të shkruhet klasa NumerKompleks
me veçoritë private
re
dhe im
si dhe anëtarët në vijim:
NumerKompleks(re,im)
shto(k)
, zbrit(k)
, shumezo(k)
, ku k
është NumerKompleks
.shto(re,im)
, zbrit(re,im)
, shumezo(re,im)
.shtyp()
, toString()
.Në main
të deklarohen disa instanca të tipit
NumerKompleks
dhe të kryhen llogaritje të ndryshme.