You are on page 1of 65

T07.

Specialieji klasi
metodai ir kintamieji
P175B123 T06
2
Pakartojimas
1. Kokie metodai yra btini klass, turinios susietj sra,
ssajai?
2. K dar papildomai prie ssajos metod dl klass ssajos
turime paskelbti klasje?
3. Papasakokite, k inote apie ssajos rodykl.
4. Kuo pirmiausiai dvikryptis sraas skiriasi nuo vienkrypio?
5. Koki dviej sra savybes akumuliuoja dvikryptis sraas?
6. Kas yra ir kur talpinami fiktyvs elementai?
7. Kuo naudingi fiktyvs elementai?
3
Temos klausimai
Rodykl this
Kopijos konstruktorius ir dinamin atmintis
Kopijos konstruktorius dinaminiam masyvui
Kopijos konstruktorius susietajam sraui
Priskyrimo operatorius
Sudting operacij uklojimas
P175B123 T06
4
Specialieji metodai
5
Specialieji metodai
Kiekviena klas turi 4 specialiuosius metodus:
konstruktori
destruktori
kopijos konstruktori
priskyrimo operatori
P175B123 T06
6
Specialij metod slygos
jei ie 4 metodai klasje nepaskelbti, tai juos
AUTOMATIKAI sukuria ir realizuoja
kompiliatorius.

juos BTINA klasje paskelbti ir realizuoti, jeigu
klass kintamieji yra rodykls tipo!
P175B123 T06
7
Kopijos konstruktoriaus apibrimas
Kopijos konstruktorius tai konstruktorius su vienu
parametru, kuris yra to paties tipo, kaip ir klas, kuriai
priklauso konstruktorius.
Kopijos konstruktoriaus tikslas kuriamo objekto
kintamiesiems suteikti tokias pat reikmes, kokias turi
anksiau sukurtas kitas objektas.
P175B123 T06
8
Priskyrimo operatorius
Priskyrimo operatorius taikomas ir objektams, t.y.,
vien objekt galima priskirti kitam, kaip elgiams ir
su prasto tipo kintamaisiais (int, double, char,...).
Priskyrimo operatorius veikia panaiai, kaip kopijos
konstruktorius - deinje pusje esanio objekto
lauk reikmes priskiria kairje pusje esanio
objekto atitinkamiems laukams.
Priskyrimo operatoriaus realizavimo btinumo
slygos sutampa su kopijos konstruktoriaus
realizavimo btinumo slygomis (kai naudojami
rodykls tipo duomenys!).
P175B123 T06
9
Kopijos konstruktorius ir priskyrimo operatorius
Kopijos konstruktorius naudojamas naujo objekto
duomen lauk pradinms reikmms suteikti.
Priskyrimo operatorius naudojamas esamo objekto
duomen lauk reikmms pakeisti.
Priskyrimo sakinys nekvieia kopijos konstruktoriaus,
todl btina priskyrimo operatoriaus uklojim realizuoti
atskirai.
Preke Pr1; Preke Pr2 = Pr1; // kopijos konstruktorius
Preke Pr1, Pr2; Pr2 = Pr1; // priskyrimo operacija
Priskyrimo operatorius realizuojamas pagal operatori
uklojimo taisykles.
P175B123 T06
10
Rodykl this
11
Atmintis objektui
Programos vykdymo metu sukuriamiems objektams
iskiriama atmintis
Atmintis skiriama tik objekto kintamiesiems
Jeigu sukuriami keli vienos klass objektai, kiekvienas
j atmintyje savo kintamiesiems saugoti turi atskir
viet, o metodais naudojasi bendrai
Programos kodo segmente visada yra tik vienas klass
metod rinkinys, o ne tiek, kiek yra sukurta tos klass
objekt
P175B123 T06
12
Rodykl this
Programos vykdymo metu metodas privalo inoti, su
kurio objekto duomenimis jis turi atlikti veiksmus.
Kreipiantis metod, jam perduodamas paslptas
parametras rodykl objekto pradi, kuri ymima
raktiniu odiu this.
Rodykl this visada saugo objekto pradios adres.
P175B123 T06
13
Rodykls this ibandymas
class ThisDemo {
string eilute;
public:
void ObjektoAdresas(string vardas)
{
cout << "Objekto vardas " << vardas
<< " adresas " << this << endl;
}
};
P175B123 T06
14
Pagrindin programa
int main()
{
ThisDemo a1, a2, a3;
a1.ObjektoAdresas("a1");
a2.ObjektoAdresas("a2");
a3.ObjektoAdresas("a3");
return 0;
}
Rezultatas ekrane:
Objekto vardas a1 adresas 0012FF7C
Objekto vardas a2 adresas 0012FF6C
Objekto vardas a3 adresas 0012FF5C
P175B123 T06
15
Rodykls this paslaptys
this niekada neraome klass metodo parametr
srae, taiau ji visada perduodama
Kadangi rodyklei this suteikiama objekto pradios
adreso reikm, ji gali bti naudojama objekto
kintamj irinkimui
P175B123 T06
16
Klas dl this
class Klas {
int a;
double b;
public:
void Dti(int ca, double cb);
...
};
P175B123 T06
17
this metode
void Klas::Dti(int ca, double cb)
{
a = ca;
b = cb;
}
// Alternatyvus, bet perteklinis
void Klas::Dti(int ca, double cb)
{
this->a = ca;
this->b = cb;
}
P175B123 T06
18
this reikalinga
3 situacijos, kai rodykl this reikalinga:
Kai objektas, jo klasei priklausanio metodo viduje,
kvieia iorin funkcij ar kitos klass metod ir nori
perduoti rodykl save.
Kai uklojami operatoriai. Pvz.: uklojamajame
priskyrimo operatoriuje objektas turi pasitikrinti, ar jis
nebando savs priskirti sau.
Kai sutampa klass kintamj ir metodo parametr
vardai, norint atskirti klass kintamuosius nuo
parametr vard, prie klass kintamj nurodoma
rodykl this, nors iai situacijai yra alternatyva
nurodomas klass vardas.
P175B123 T06
19
this. Pirma situacija
// Kreipinys iorin funkcij
void Klas::Kelti()
{
...
Vykdyti(this);
// Kreipiasi iorin funkcij ir
// perduoda rodykl save
...
}
P175B123 T06
20
this. Antra situacija
// Uklojamas priskyrimo operatorius
// Gali bti grinama void
Klas & Klas::operator =(const Klas & kitas)
{
// Jeigu priskyrimas sau paiam, tai nedarom nieko,
// tik griname nuorod save
if (this == &kitas)
return *this;
...
}
P175B123 T06
21
this. Treia situacija
// Sutampa kintamj ir parametr vardai:
// naudojam this
void Klas::Dti(int a, double b)
{
this->a = a;
this->b = b;
}
P175B123 T06
22
this. Alternatyva
// Klass kintamj atskyrimui,
// naudojame klass vard
void Klas::Dti(int a, double b)
{
Klas::a = a;
Klas::b = b;
}
P175B123 T06
P175B123 T06
23
Kopijos konstruktorius
24
Kopijos konstruktoriaus forma
KlassVardas (const KlassVardas & objektoV)
{
// Kopijos konstruktoriaus kamienas
}

Papildomai - bazinis odis const ir nuorodos operatorius &.
Parametrui nebus skiriama nauja vieta atmintyje (&) ir nebus
galima pakeisti parametro reikmi (const).
Nuoroda & btina, kitaip gautume begalin rekursij.
const paskelbimas nra btinas, bet labai naudingas.
Kopijos konstruktorius gali turti ir daugiau parametr, taiau
pirmuoju visuomet turi bti nuoroda esamos klass objekt.
24
P175B123 T06
25
Kopijos konstruktoriaus atvejai
Kopijos konstruktorius naudojamas 4 atvejais:
Objekto kopijos paskelbimas;
Ireiktas priskyrimas, paskelbiant objekt;
Objekto kopijos sukrimas, perduodant j
parametru metodui;
Sukuriant laikin bevard objekt (r. Operatori
uklojime).
25
P175B123 T06
26
Pvz., Numatytasis kopijos konstruktorius1/2
class Miestas {
private:
string pavad; // Miesto pavadinimas
long gyvsk; // Gyventoj skaiius
public:
Miestas(string p = "", long g = 0):
pavad(p), gyvsk(g) { }
void Dti(string p, string s, long g);
void Rodyti();
};
26
P175B123 T06
27
// Veikia konstruktorius
Miestas mano("Kaunas", 353800);
// Veikia kopijos konstruktorius
Miestas tavo(mano);
// Veikia kopijos konstruktorius
Miestas ms = mano;
mano Kaunas 353800
tavo Kaunas 353800
ms Kaunas 353800
Pvz., Numatytasis kopijos konstruktorius2/2
27
P175B123 T06
28
Reikia kopijos konstruktoriaus?
Kompiliatorius ikvieia klasje esant numatytj objekto
kopijos konstruktori ir kopijuoja esamus duomenis.

Numatytasis kopijos konstruktorius atlieka iuos veiksmus
efektyviau, nes gali naudoti optimizavimo technik, kuri
kitais atvejais nemanoma.

Kai klasje apibrti duomen laukai, kuriems vieta
atmintyje iskiriama dinamikai, numatytasis
konstruktorius nebetinka.
28
P175B123 T06
29
Klas Prek
class Prek {
private:
int kiek; // Masyvo element skaiius
double *A; // Rodykl masyv
public:
Prek(int kiek = 3) : kiek (kiek)
{ // Konstruktoriuje praoma atminties
A = new double [kiek];
}
~Prek() { delete [] A; }
void Upildyti(int kuo = 10);
};
29
P175B123 T06
30
Veiksmai

void Prek::Upildyti(int kuo)
{
A[0] = kuo;
for (int i = 1; i < kiek; i++)
A[i] = A[i-1] + 10;
}
30
P175B123 T06
31
Situacija atmintyje
10 20 30
Pr1.kiek
3
Pr1.A
Pr2.kiek
3
Pr2.A
Prek Pr1;
Pr1.Upildyti();
Prek Pr2(Pr1);
31
P175B123 T06
32
Teisinga situacija
10 20 30
Pr1.kiek
3
Pr1.A
10 20 30
Pr2.kiek
3
Pr2.A
32
P175B123 T06
33
Klas su kopijos konstruktoriumi
class Prek {
private:
int kiek;
double *A;
public:
Prek(int kiek = 3): kiek (kiek)
{
A = new double [kiek];
}
Prek(const Preke & desine);
~Prek() { delete [] A; }
void Upildyti(int kuo = 10);
};
33
P175B123 T06
34
Kopijos konstruktorius
Prek::Prek(const Prek & dein)
{
kiek = dein.kiek;
A = new double[kiek];
for(int i = 0; i < kiek; i++)
A[i] = dein.A[i];
}
34
P175B123 T06
35
Kopijos konstruktoriaus slygos
Klasms, turinioms duomen laukus,
kuriems iskiriama atmintis dinamikai,
programuotojas pats privalo realizuoti
kopijos konstruktori arba udrausti
kompiliatoriui naudoti numatytj kopijos
konstruktori.

Norint udrausti ir paiam nerealizuoti, reikia
kopijos konstruktoriaus antrat patalpinti
klass private srit.
35
P175B123 T06
36
Klas su dinaminiu srau
class Sarasas {
struct Sar { // naudojamas tik klasje
int duom;
Sar * kitas;
};
Sar *p, // srao pradia
*d; // ssajos metodams
public:
Sarasas() : p(NULL), d(NULL) { }
~Sarasas() { Naikinti(); }
Sarasas(const Sarasas & kitas);
void Naikinti();
void DtiIPradi(int x);
Sarasas & operator =(const Sarasas & kitas);
void operator +=(const Sarasas & kitas);
Sarasas operator +(const Sarasas & kitas) const;
string Spausdinti(string tekstas);
};
P175B123 T06
37
Kopijos konstruktorius
Sarasas::Sarasas(const Sarasas & kitas) {
Sar *dn, *gn;
p = NULL;
for (Sar *d = kitas.p; d != NULL; d = d->kitas) {
dn = new Sar;
dn->duom = d->duom;
dn->kitas = NULL;
if (!p)
p = dn;
else
gn->kitas = dn;
gn = dn;
}
}
P175B123 T06
P175B123 T06
38
Sudtingesnij operatori
uklojimas
P175B123 T06
39
Operatori uklojimo poreikis
Naudoti bazini operatori sintaks veiksmuose su
ms sukurt klasi objektais. A = B + C, kur A, B, C -
sukurtos klass X objektai.
Reikia stengtis suteikti uklotam operatoriui tok turin,
kuris bent kiek primint bazin operatori.
40
Prisiminkime: Operatori uklojimo sintaks
<tipas> operator <op. simb.>([<parametrai>])


<tipas> - operatoriaus grainamo rezultato tipas,
<op. simb.> - operatoriaus simbolis,
<parametrai> - operatoriaus parametrai.
bazinis odis
P175B123 T06
P175B123 T06
41
Grinamos reikms tipas 1
bool naudojamas uklojamuose palyginimo
operatoriuose
void - retai, nes apriboja ukloto operatoriaus
dalyvavimo iraikose galimybes
Klass objektas - rezultatas yra naujas objektas,
pvz.: C A + B;
Nuoroda (&) klass objekt - rezultatas yra tas
pats objektas, pvz.: A + B;
P175B123 T06
42
Grinamos reikms tipas 2
Klass objektas grinamas, kai operatorius nekeiia
esamo objekto, o nuoroda klass objekt grinama,
kai keiia esam objekt.
Antruoju atveju metodo kamiene vienintelis manomas
grinimo sakinys yra:
return *this;

P175B123 T06
43
Grinamos reikms tipas ir realizacija
Nuo uklojamo operatoriaus antrats priklauso jo realizavimas.
1. Jei reikia grinti klass objekt, tai metodo viduje skelbiamas
laikinasis klass tipo objektas, kuris sukaupia operatoriaus
rezultat, ir grinama io objekto reikm.
2. Jei reikia grinti nuorod objekt, tai pagal operatoriaus
reikalavimus modifikuojamas esamos klass objektas ir grinama
rodykls this adresu esanti reikm (return *this;).
Pirmuoju atveju esamos klass objektas ilaiko savo reikm
nepakitusi.
44
Uklojamo operatoriaus parametro apibrimas
Parametras apibriamas kaip const ir perduodamas
pagal nuorod (&).
const - negalima keisti perduodamo parametro
reikms.
& - parametrui nebus skiriama nauja vieta atmintinje.
Klass objektas gali uimti daug vietos atmintinje.
P175B123 T06
45
Operatori variantai
Operatoriai gali bti dvivieiai, pvz.: +, -, &&, arba
vienvieiai, pvz.: ++, --, !.
Dvivieiai operatoriai turi operandus i abiej pusi,
pavyzdiui, a + b, c - d ir pan.
Vienvieiai operatoriai operand turi tik i vienos puss,
pavyzdiui, !a, ++b, b++ ir pan.


Dvivieiams operatoriams reikia apibrti vien
parametr, o vienvieiams parametr nra.
Priedlinis ++
Priesaginis ++
P175B123 T06
46
Dviviei operatori pavyzdiai
// Daugiau operatorius (>)
bool A::operator >(const A & kitas)

// Sudties operatorius (+)
A A::operator +(const A & kitas)

// Priskyrimo operatorius (=)
A & A::operator =(const A & kitas)

A klas, kurioje ukloti operatoriai
P175B123 T06
47
Vienviei operatori pavyzdiai
// Neigimo operatorius (!)
bool A::operator !()
// Priedlinis operatorius (++)
A A::operator ++()
// Priesaginis operatorius (++)
A A::operator ++(int)

A klas, kurioje ukloti operatoriai
P175B123 T06
48
Objektai uklotoje operacijoje
Kai dvivieiame operatoriuje dalyvauja 2 to paties tipo
objektai, jie abu turi uklot operatori.
Atliekant uklot operatori, visada kvieiamas kairje
operatoriaus pusje esanio objekto metodas, kuris
ukloja mint operatori.
Operatoriaus deinje pusje esantis objektas visada
perduodamas per parametr.
Ukloto operatoriaus viduje naudojami klass kintamieji
tiesiogiai kreipiasi pirmojo objekto duomenis.
Nordami kreiptis antrojo objekto duomenis, turime
nurodyti jo vard, kuris yra operatori uklojanio
metodo parametras.
P175B123 T06
P175B123 T06
49
Klasi su dinamine atmintimi
operatori uklojimas
P175B123 T06
50
Klas su dinaminiu masyvu
class Masyvas {
private:
int *Ad; // dinaminis masyvas
int kiek; // element kiekis masyve
public:
Masyvas();
~Masyvas() { delete [] Ad; }
Masyvas(const Masyvas & desine);
Masyvas & operator =(const Masyvas & desine);
void Sukurti(int kiek=5, int nuoko=1, int ka=5);
void Isvesti(string pavadinimas) const;
Masyvas & operator +=(const Masyvas & desine);
Masyvas operator +(const Masyvas & desine) const;
};
P175B123 T06
51
Priskyrimo realizacij ypatumai
Priskyrimo operatoriaus uklojimas gali bti realizuotas 2
variantais:
void Masyvas::operator =(const Masyvas & desine),
Masyvas & Masyvas::operator =(const Masyvas & desine).

a = b;, kur a ir b klass Masyvas tipo objektai.

a = b = c = d;, kur a, b, c ir d klass Masyvas
objektai. Antrasis variantas laikomas klasikiniu.
P175B123 T06
52
Priskyrimo operatorius masyvui
Masyvas & Masyvas::operator =(const Masyvas & desine)
{
if (this == &desine)
return *this;
if (kiek != desine.kiek) {
int *NaujasMasyvas;
NaujasMasyvas = new int[desine.kiek];
delete [] Ad;
Ad = NaujasMasyvas;
kiek = desine.kiek;
}
for (int i = 0; i < kiek; i++)
Ad[i] = desine.Ad[i];
return *this;
}
Kuo skiriasi, jei
antratje grinamas
tipas void?
P175B123 T06
53
Sudtis ir priskyrimas
Masyvas & Masyvas::operator +=(const Masyvas & desine)
{
int *NaujasMasyvas = new int[kiek + desine.kiek];
for (int i = 0; i < kiek; i++)
NaujasMasyvas[i] = Ad[i];
delete [] Ad;
Ad = NaujasMasyvas;
for (int i = 0, j = kiek; i < desine.kiek; i++)
Ad[j++] = desine.Ad[i];
kiek += desine.kiek;
return *this;
}
Kaip galima realizuoti +
operacijos uklojim?
P175B123 T06
54
Priskyrimo uklojimas sraui
Sarasas & Sarasas::operator =(const Sarasas & kitas) {
if (this == &kitas)
return;
Sar *dn, *gn;
Naikinti();
for (Sar *d = kitas.p; d != NULL; d = d->kitas) {
dn = new Sar;
dn->duom = d->duom;
dn->kitas = NULL;
if (!p)
p = dn;
else
gn->kitas = dn;
gn = dn;
}
return *this;
}
Kuo skiriasi kamienas nuo
kopijos konstruktoriaus
kamieno?
55
A += B, klaidingai

A
1
A.p
3 5
2
B.p
4
NULL
P175B123 T06
56
A += B, teisingai

A
1 3 5
2
4
NULL
4
NULL
2
A.p
B.p
P175B123 T06
57
A += A, klaidingai

A
1 3 5
A.p
P175B123 T06
58
Galima ir taip, A += B
A.p
4 2
Turime nukopijuoti
Abiej objekt sraai lieka nepriklausomi
Gerai !
1 3 5
2
B.p
4
P175B123 T06
60
Sudties ir priskyrimo (+=) uklojimas 1/2
void Sarasas::operator +=(const Sarasas & kitas)
{
Sar *dn, *gn, *pn = NULL;
// deins puss srao kopija
for (Sar *d = kitas.p; d != NULL; d = d->kitas) {
dn = new Sar;
dn->duom = d->duom;
dn->kitas = NULL;
if (!pn)
pn = dn;
else
gn->kitas = dn;
gn = dn;
}
// tsinys kitoje skaidrje
P175B123 T06
61
Sudties ir priskyrimo (+=) uklojimas 2/2
// iekom paskutinio elemento ir prie jo prijungiam
if (p) {
dn = p;
while (dn->kitas)
dn = dn->kitas;
dn->kitas = pn;
}
else
p = pn;
}
P175B123 T06
62
Sudties (+) uklojimas
Sarasas Sarasas::operator +(const Sarasas & kitas) const
{
Sarasas Laik;
Laik += *this;
Laik += kitas;
return Laik;
}
P175B123 T06
63
Testas
int main() {
Sarasas p1, // pirmas konteineris su srau
p2, // antras konteineris su srau
p3; // treias konteineris su srau
SkaitytiAtv(CDuom, p1); // i failo CDuom suformuoja p1
cout << p1.Spausdinti("p1 (suformuotas) ") << endl;
p2 = p1;
cout << p2.Spausdinti("p2 (p2 = p1) ") << endl;
p1 += p2;
cout << p1.Spausdinti("p1 (p1 += p2) ") << endl;
cout << p2.Spausdinti("p2 ") << endl;
p3 = p1 + p2;
cout << p3.Spausdinti("p3 (p3 = p1 + p2) ") << endl;
}
P175B123 T06
64
Testavimo rezultatai
p1 (suformuotas) 1 2 3
p2 (p2 = p1) 1 2 3
p1 (p1 += p2) 1 2 3 1 2 3
p2 1 2 3
p3 (p3 = p1 + p2) 1 2 3 1 2 3 1 2 3
rodymui, kad
nepakito p2
P175B123 T06
65
Santrauka
1. Rodykl this
2. Kopijos konstruktorius
3. Priskyrimo operatoriaus realizavimas
3. Sudtingesni operatori uklojimas (+, +=)
P175B123 T06
66
Programavimo konkurs
udaviniai
P175B123 T06

You might also like