You are on page 1of 28

Programozs C++-ban

A C++ nyelv a C programozsi nyelv egy tovbbfejlesztett vltozata, gy nhny rszlettl


eltekintve, fellrl kompatibilis a C-vel. A C nyelv lehetsgein tlmenen, a C++ igen
flexibilis s hatkony eszkzket nyjt a programoznak j adatstruktrk definilsra. A C+
+ lehetv teszi, hogy a programoz munkjt olyan jl kezelhet rszekre oszthassa fel,
amelyek szorosan ktdnek az alkalmazi program alapkoncepcijhoz. Mskpp
fogalmazva: a C++ megteremti annak a lehetsgt, hogy egy problmt adattpusokra, s az
adott adattpusokhoz szorosan hozzrendelt mveletekre kpezhessnk le. gy a valsghoz
kzel ll objektumokat definilhatunk a C++ programban. Ezek az objektumok aztn
knyelmesen s biztonsgosan hasznlhatk olyan kontextusban is, amikor tpusuk a program
fordtsakor mg nem llapthat meg. Ezt a fajta programozsi technikt objektum-orientlt
programozsnak (rviden OOP-nek) nevezzk. Ha jl hasznljk, az OOP rvidebb,
ttekinthetbb, s knnyebben karbantarthat programokat eredmnyez, mint a
"hagyomnyos" programozsi stlus.
A C++ alapelemei az osztlyok (classes). Egy osztly nem ms, mint egy felhasznl ltal
definilt j tpus, amely a szksges adatstruktrt, s az adott struktrj adatokkal
vgezhet mveleteket definilja. Az osztlyok hasznlata lehetv teszi az informcirejtst
(teht azt, hogy bizonyos dolgokrl csak a hasznlatukhoz szksges ismereteket tesszk
msok ltal is hozzfrhetv), garantlja az adatok inicializlst, implicit tpuskonverzit
biztost a felhasznl ltal definilt adattpusok esetben, az egyes opertorokhoz jabb
jelentst rendelhetnk ltaluk, stb. C++-ban sokkal hatkonyabb eszkzk llnak
rendelkezsre a modularits kidombortsra s a tpusellenrzsre, mint a C-ben. Tovbbi
olyan bvtseket is tartalmaz a C++, amelyek nincsenek kapcsolatban az objektum-orientlt
programozssal. Ilyenek pldul az n. inline fggvnyek, a cm szerint tadhat
fggvnyparamterek, az inicializlt fggvnyparamterek, stb.
A C++ megtartja a C-nek azt a tulajdonsgt, hogy igen hatkonyan kezeli a hardver kzeli
adattpusokat (bitek, byte-ok, szavak, cmek), gy ez az j nyelv tovbbra is jl felhasznlhat
rendszerprogramozi feladatok megoldsra.
A C++ nyelv tervezi elsdlegesnek tekintettk a C egyszersgnek megrzst, s a C-vel
val kompatibilitst, valamint a rgi C szintaxisnak tisztbb ttelt. A C++-ban nincsenek
magas szint adattpusok s hozzjuk rendelt mveletek. Pldul nem ltezik a C++-ban
mtrix tpus s mtrix invertl opertor. Ha a felhasznlnak szksge van ilyen tpusra, a
nyelv lehetv teszi annak definilst. Valjban a C++ programozi tevkenysg alapvet,
lnyegi rszt a megfelel adattpusok definilsa teszi ki. Egy jl megtervezett felhasznli
adattpus nem abban klnbzik egy beptett tpustl, hogy hogyan lehet hasznlni, hanem
csak abban, hogy mikpp van definilva. Az objektumok tpusnak ismeretben a
fordtprogram megfelelen tudja kezelni a bellk alkotott kifejezseket, mg a
hagyomnyos C-ben a programoznak kn-keservvel kell lernia minden egyes mvelet
vgrehajtsi mdjt. A tpusok pontos ismerete azt is elsegti, hogy mr programfordtskor
kiderljenek olyan hibk, amelyek egy hagyomnyos C program esetben csak a tesztels
sorn tallhatk meg.

Ebben a rszben - ahogy az 1. fejezetben ttekintettk a BORLAND C++ implementci


ANSI C kompatibilis elemeit - ismertetjk a nyelv AT&T C++ 2.0 kompatibilis rszeit. A C+
+-ra vonatkoz alapreferenciaknt ajnljuk Bjarne Stroustrup knyvt (The C++
programming language). Fel kell azonban hvnunk az olvas figyelmt arra, hogy ez a knyv
"csak" az 1.0-s verzij C++ egzakt referencija. Mivel az AT&T a 2.0-s C++ vltozatban a
korbbi verzit tovbb bvtette, mi olyan nyelvi elemekrl is emltst tesznk, amelyekrl
Stroutstrup fenti knyve (rtelemszeren) nem szl. A C++-ra vonatkoz legfrissebb
referenciaknt Stroustrup egy jabb munkjt ajnljuk (The Annotated C++ Reference
Manual). A C++ nyelv BORLAND C++ implementcijnak teljes referencijt az eredeti
programdokumentci Programmer's Guide cm ktete tartalmazza.
Tartalomjegyzk:

j elemek a C++-ban
Alternatvk a #define direktva helyett
Cm szerint nyilvntartott tpus, vagy referencia tpus vltozk
Inicializlt fggvnyparamterek
C ++ kommentek
Az OOP alapjai
Egysgbezrs
rkls
Tbbrtsg (polimorfizmus)
Fggvnymezk definilsa
Fggvnymezk aktivizlsa
A this nev, implicit mutat
Konstruktorok s destruktorok
Konstruktorok definilsa
Destruktorok definilsa
Mezhozzfrs
Mezhozzfrsi szintek
Mezhozzfrs s rkls
Virtulis fggvnyek
Ksi sszerendels
Virtulis fggvnyek deklarlsa
Dinamikus objektumok
Dinamikus objektumok ltrehozsa
Dinamikus objektumok megszntetse
Tovbbi flexibilits a C++-ban
Rokonok s bartok
Operator overloading
C++ I/O knyvtrak

Alternatvk a #define direktva helyett


A 1.3-as rszben megismerkedtnk a #define preprocesszor utastssal. Ez a direktva hrom
clt szolgl:

feltteles fordtst vezrl szimblumokat definilunk vele az elfeldolgoz #if ...


#elif ... #else ... #endif, illetve #ifdef, #ifndef szerkezetei szmra,
programjaink szm-, vagy szvegkonstansaihoz, illetve konstans-kifejezseihez
szimblikus neveket rendelhetnk, ezltal nvelve a programkd rugalmassgt s
olvashatsgt, s vgl
fggvny-jelleg makrkat definilhatunk segtsgvel.

Az utbbi kt alkalmazst clszer elvlasztani a fordtsvezrl funkciktl. Ahhoz, hogy ezt


megtehessk, a C++ kt lehetsget knl.
Az egyik a const kulcssz hasznlata. (Megjegyzend, hogy a const kulcssz az ANSI Cnek is rsze, lsd 1.4.6-os szakaszt.)
Minden olyan konstanst, amit nem fordtsvezrlsre akarunk hasznlni, clszer a const
deklarcij valtozknak kezdeti rtkl adni. Ezek utn a const deklarcij vltzkat
ugyangy hasznlhatjuk, mint a jl megszokott #define konstansokat, azzal a nem mellkes
klnbsggel, hogy menteslnk a #define konstansok feldolgozsokor trtn egyszer
szveghelyettests esetleges kellemetlen mellkhatsaitl. Ezltal biztonsgosabb vlhatnak
forrsprogramjaink.
A const mdost szval deklarlt vltozk mellett a felsorolt tpus (enum) vltozk
alkalmazsa is hatkony alternatva a #define direktva helyett. C++ az enum tpust kicsit
mskpp rtelmezi, mint a hagyomnyos C. A klnbsg az, hogy mg a hagyomnyos C az
enum s int tpusokat kompatibilisnek tekinti, addig a C++ a klnbz enum tpusokra
vonatkozlag is szigor tpusellenrzst vgez. gy pldul egy enum tpus vltoznak nem
adhatunk int tpus rtket.
A #define-nal trtn makrdefincikkal szemben hatkony alternatvt jelentenek az n.
inline (sorok kztti) fggvnyek. Rviden: egy inline fggvny elg kis terjedelm ahhoz,
hogy helyben (in situ), a fggvnyhvs helyre behelyettestve le lehessen fordtani. Ebben a
tekintetben egy inline fggvny olyan, mintha makr lenne, azaz a fggvnyhvsokkal jr
adminisztrcira nincs szksg. Rvid, egy-kt soros fggvnyek esetben ez sokkal
hatkonyabb, sokkal olvashatbb megoldst jelent, mint a makr-definci. Az n. explicit
inline fggvnyek deklarlsra szolgl a C++ inline kulcsszava. (Az implicit inline
deklarcirl az n. fggvnymezk kapcsn egy ksbbi fejezetben lesz sz.)
Teht az inline fggvnyek a hagyomnyos C elfeldolgoz #define direktvjval
definilhat makrkhoz hasonltanak. Annyival fejlettebbek a makrknl, hogy egy ilyen
fggvny meghvsa nem pusztn szveghelyettests, hanem a definci szerint generlt kd
msoldik be a hvsok helyre, gy a makrkkal kapcsolatban emltett mellkhatsok
jelentkezsnek is kisebb a veszlye. Vgl az explicit inline fggvny-defincira lljon itt
egy plda:

inline int abs(int x)


{
return (x < 0) ? -x : x;
}

Cm szerint nyilvntartott tpus, vagy referencia tpus vltozk


A 1.9.3-as rszben, a hagyomnyos C nyelv ismertetsnl emltettk, hogy a fggvnyek
rtk szerint veszik t az aktulis paramtereiket. (A tmbket ebbl a szempontbl tekintsk
olyan pointereknek, amelyek adott szm rtkes adat szmra lefoglalt trterletre mutatnak
- lsd a 1.9.6-os szakaszt. Igy a tmbk is belefrnek az "rtk szerint" fogalmba, hiszen a
mutatkat tnyleg rtk szerint adjuk t.) Ha egy vltozt cm szerint akartunk paramterknt
tadni, akkor a formlis paramterlistban az adott tpusra mutat pointert kellett
deklarlnunk, a fggvnytrzsben az indirekci opertort kellett alkalmaznunk, s a
fggvny meghvsakor az aktulis paramterlistban magunknak kellett explicit mdon
gondoskodnunk arrl, hogy a megfelel paramterhelyre a megfelel vltoz cme kerljn.
Ennek a dolognak az a nagy htrnya, hogy a fggvnytrzsben nem klnlnek el
szintaktikailag az igazi tmbk s a cm szerint tadott skalrjelleg vltozk.
A C++-ban ilyen, s hasonl jelleg problmk thidalsra bevezettk az n. cm szerint
nyilvntartott, vagy referencia tpus (reference type) fogalmt s ehhez definiltk a &
tpusmdost opertort. Igy pldul a
int& r;

deklarci azt jelenti, hogy r olyan vltoz, amely egy egsz tpus vltozra vonatkoz
referencit tartalmazhat. gy is felfoghatjuk a dolgot, hogy egy ilyen fajta vltoz egy olyan
konstans pointer-kifejezs, amelyre vonatkozlag automatikusan vgrehajtdik egy
indirekci-mvelet, amikor az adott referencia tpus vltozra hivatkozunk. Ez hrom dolgot
von maga utn. Az egyik, hogy a fenti plda szerinti r vltoz minden olyan helyen llhat,
ahol egy int tpus vltoz is llhat, azaz egsz tpus kifejezsekben akr balrtk, akr
jobbrtk lehet. A msodik, hogy a referencia tpus vltozkkal semmilyen mvelet nem
vgezhet, hiszen minden hivatkozs alkalmval minden egyebet megelz az implicit
indirekci mvelet (dereference operation, lsd a 1.5.2 alatt az egyoperandus * opertorrl
lertakat). Ezzel ll szoros sszefggsben a harmadik fontos dolog, hogy nincs rtelme egy
cm szerint nyilvntartott tpus vltozt inicializls nlkl definilni. Teht csak az
albbihoz hasonl defincinak van rtelme:
int ii = 0;
int& rr = ii;
Ekkor az rr++; utasts szintaktikailag ugyan helyes, de nem az rr vltoz inkrementldik,
hanem az az int tpus trterletfoglal trolsi egysg, amelyiknek a cmt rr tartalmazza.
Ez a fenti pldban ppensggel az ii vltoz. Ez az rtelmezs trivilis akkor, amikor az

inicializl kifejezs egy balrtk, de nem ktelez, hogy az inicializtor balrtk legyen, st,
az sem ktelez, hogy a referncia tpus alaptpusba tartozzon. Ilyen esetekben
a)
elszr tpuskonverzi hajtdik vgre, ha az szksges,
b)
aztn a tpuskonverzi eredmnye egy ideiglenes vltozba kerl,
c)
s vgl ennek az ideiglenes vltoznak a cme kerl felhasznlsra az adott referencia
tpus vltoz inicializlshoz.

Tekintsk az albbi deklarcit:

double& dr = 1;

Ez a fentiek alapjn a kvetkezkppen rtelmezhet:

A hasznlat

double* drp;
double temp;
temp = (double)1;
drp = &temp;
sorn a (*drp) kifejezs

egyenrtk a dr-rel.

A referencia tpus igazn kellemes felhasznlsi terlete a bevezetben is emltett


fggvnyparamter-deklarci. Ez azt jelenti, hogy a formlis paramterlistban mr
lehetsgnk van arra, hogy egy paramtert ne a re mutat pointer segtsgvel adjunk t cm
szerint, hanem jelezzk, hogy egy olyan vltozrl van sz, amit cm szerint kell tadnuk
(mert pldul kimen paramterknt is szksgnk lesz r), ugyanakkor a fggvnytrzsben a
tbbi, rtk szerint tadott vltozhoz hasonl mdon - ugyanolyan szintaktikval szeretnnk kezelni. A 1.9.3-as rszben kzlt egyszer plda a referncia tpus felhasznlsval
gy nz ki:
void f1(long& a)
{
a += 2L;
}

Ekkor az
alfa = 0L; f1(alfa);

kdrszlet szintaktikailag helyes, s hatsra alfa rtke 2L lesz. A klnbz


paramtertadsi lehetsgeket szemllteti a kvetkez kis program:

#include <stdio.h>
// **********************************************************
int any_function(int par_by_value, //Ertek szerinti int
int* use_for_arrays,//Ertek szerinti pointer
int& par_by_address)//Cim szerinti int
// **********************************************************
{ int
work;
work = par_by_value;
par_by_value *= 3;
*use_for_arrays = par_by_address * work;
par_by_address = work * work;
return par_by_value;
}
// **********************************************************
main()
// **********************************************************
{
int x = 2, y[ ] = { 1, 2 }, z = 10, w = 0;
w = any_function(z,y,x);
printf("%d %d %d %d\n",x,y[0],z,w);
}
Az any_function fggvny harmadik paramtert deklarltuk referencia tpusnak,
tpusnv (int) utn ll & tpusmdost opertor utal. Tekintsk t a fenti program

erre a

mkdst.
A main-ben any_function meghvsa eltt az x, y[0], z s w vltozk rtke rendre 2, 1, 10
s 0, a w-nek fggvnyhvssal trtn rtkads eredmnyekppen (mellkhatsknt) pedig
x, y[0], z, valamint w a 100, 20, 10 s 30 rtkeket veszik fel; a szabvnyos kimeneten ezek a
szmok fognak sorra megjelenni. Lthat, hogy az rtk szerint tadott paramter (z) nem

vltozott meg, y[0] j rtket kapott, hiszen a re mutat pointeren keresztl indirekt mdon
cmezve belertunk, s a cm szerint tadott skalr, x is j rtkkel br a fggvnyhvs utn.
Lthat az is, hogy par_by_value s par_by_address hasznlata szintaktikailag azonos.
Az any_function deklarcijakor a par_by_address parmternl hasznlt megolds
hasonlt ahhoz, amit a Pascal nyelv alkalmaz. Pascal-ban is alaprtelmezs szerint rtk
szerint addnak t a paramterek; ott a VAR kulcsszval jelezhetjk a cm szerinti
paramtertadst, ugyanakkor a FUNCTION, vagy PROCEDURE trzsben az rtk, vagy cm
szerint tadott paramterek hasznlatban nincs szintaktikai klnbsg.
A referencia tpust fggvnyek visszatrsi tpusaknt is nagyon jl fel lehet hasznlni.
Gondoljunk csak a 1.12-es pontban a balrtkek kapcsn deklarlt char *get_buff_pos(int
i) fggvnyre. Ennek a fggvnynek balrtkknt val alkalmazsa gy nzett ki:
*get_buff_pos(1) = 'b';

Ha fggvnynket char & tpus visszatrsi rtkkel deklarljuk, akkor a referencia tpus
tulajdonsgai kvetkeztben a get_buff_pos(1) kifejezs minden tovbbi nlkl rvnyes
balrtk kifejezs lesz, teht a fenti rtkad utastst gy rhatjuk:
get_buff_pos(1) = 'b';

Vegyk szre, hogy a referencia tpus visszatrsi rtk miatt a char& get_buff_pos(int
i) fggvny egy rtkad utasts mindkt oldaln llhat. A referencia tpusrl itt
elmondottak elssorban a fogalom megrtetst szolgljk. A referencia tpus legeslegfontosabb szerepet azonban a felhasznl ltal definilt tpusokra vonatkoz opertorfggvnyeknek definilsnl jtssza - ezek visszatrsi rtke ugyanis az adott tpusra
vonatkoz referencia-tpus.
Vegyk szre, hogy a referencia tpust kpz & opertor termszetes kiegsztse a
hagyomnyos C tpusmdost opertorainak: mg a * indirekci opertornak, a [ ] indexel
opertornak s a ( ) fggvnyaktivizl opertornak volt prja a tpusmdost opertorok
kztt, addig az 'address of' opertornak (egyoperandus &) nem volt.

Inicializlt fggvnyparamterek
Vltozk esetben mr a hagyomnyos C-ben megszoktuk, hogy a definci sorn kezdeti
rtkeket is megadhatunk. A C++ filozfia a kezdeti rtkadst kiemelt fontossggal kezeli
(lsd pldul a konstruktorokat 2.7-nl), gy szinte termszetes, hogy ezt a lehetsget a
fggvnyparamterekre is kiterjeszti.
A C nyelv (s a C++ is) megengedi, hogy egy fggvnyt kevesebb aktulis paramterrel
aktivizljunk, mint ahny paramtert a formlis paramterlistban deklarltunk. Ez sokszor
kellemes, jl kihasznlhat tulajdonsg, sokszor azonban kellemetlen, nehezen szrevehet
mellkhatsokat eredmnyez hibaforrs is lehet. Gondoljunk csak a jl ismert printf
fggvnyre, melynek mkdse a C ezen tulajdonsgn alapul: Ha a formtum-specifikl
sztringben tbb kiirand adatot hatrozunk meg, mint ahnyat aztn tnylegesen felsorolunk a
printf aktulis paramterlistjban, akkor mindig valami "szemt" kerl standard outputra.
Ehhez hasonlan hatrozatlan paramterrtkekkel dolgozhat akrmilyen ms fggvny is, ha
vletlenl hinyos aktulis paramterlistval hvtuk meg. Az ilyen - esetleg fatlis hibt okoz
- szitucik elkerlst szolglja az a lehetsg, hogy egy fggvny deklarcijakor a
formlis paramterlistn az egyes paramterekhez alaprtelmezs-szer (default) kezdeti
rtkeket rendelhetnk. Tekintsnk erre egy pldt:

double triangle(double a=0, double b=0, double gamma=90);

Ha a fenti deklarci szerinti fggvnyt arra hasznljuk, hogy egy hromszg harmadik
oldalnak hosszt kiszmtsuk a koszinusz-ttel segtsgvel (gy, hogy a kt ismert oldal
ltal kzbezrt szget fokokban kell megadnunk), akkor a gamma paramter kihagysval a
Pithagorasz-ttelre egyszersdhet a problma. Teht a triangle(3,4,135)
fggvnyhvskor az aktulis paramterek rtke rendre 3, 4 s 135, a triangle(3,4)
hvskor 3, 4 s 90, triangle(3) hatsra 3, 0, 90 lesz, s vgl a triangle()
fggvnyhvs esetben teljesen az alaprtelmezs szerinti 0, 0, 90 szmhrmas lesz
rvnyben.

C ++ kommentek
Figyeljk meg a 2.1.2-es rsz pldaprogramjban, hogy a C++-ban kt slash (/) karakterrel
egysoros kommentrokat rhatunk. Ez igaz minden C++ rendszerre. A BORLAND C++
esetben ezt a kommentezsi stlust alkalmazhatjuk akkor is, ha csak egyszer C fordtknt
akarjuk hasznlni a rendszert, mindazonltal megjegyzend, hogy az egysoros kommentrok
ilyen jellse ltalban nem portbilis (mert a rgebbi C fordtk nem fogadjk el //-t.
Termszetesen a /* .. */ pros s a // alkalmazsa vegyesen is lehetsges.

Az OOP alapjai
Az objektum-orientlt programozs (rviden OOP) a termszetes gondolkodst, cselekvst
kzelt programozsi md, amely a programozsi nyelvek tervezsnek termszetes
fejldse kvetkeztben alakult ki. Az gy ltrejtt nyelv sokkal struktrltabb, sokkal
modulrisabb s absztraktabb, mint egy hagyomnyos nyelv. Egy OOP nyelvet hrom fontos
dolog jellemez. Ezek a kvetkezk:

Az egysgbezrs (encapsulation) azt takarja, hogy az adatstruktrkat s az adott


struktrj adatokat kezel fggvnyeket (Smalltalk, illetve a TURBO Pascal
terminolgival lve metdusokat) kombinljuk; azokat egy egysgknt kezeljk, s
elzrjuk ket a klvilg ell. Az gy kapott egysgeket objektumoknak nevezzk. Az
objektumoknak megfelel trolsi egysgek tpust a C++-ban osztlynak (class)
nevezzk.
Az rkls (inheritance) azt jelenti, hogy adott, meglv osztlyokbl levezetett jabb
osztlyok rklik a definlsukhoz hasznlt alaposztlyok mr ltez adatstruktrit s
fggvnyeit. Ugyanakkor jabb tulajdonsgokat is definlhatnak, vagy rgieket
jrartelmezhetnek. gy egy osztlyhierarchihoz jutunk.
A tbbrtsg (polymorphism) alatt azt rtjk, hogy egy adott tevkenysg (metdus)
azonostja kzs lehet egy adott osztlyhierarchin bell, ugyanakkor a hierarchia
minden egyes osztlyban a tevkenysget vgrehajt fggvny megvalstsa az
adott osztlyra nzve specifikus lehet. Az n. virtulis fggvnyek lehetv teszik,
hogy egy adott metdus konkrt vgrehajtsi mdja csak a program futsa sorn
derljn ki. Ugyancsak a tbbrtsg fogalomkrbe tartozik az n. overloading,
aminek egy sajtsgos esete a C nyelv standard opertorainak tdefinilsa (operator
overloading).

Ezek a tulajdonsgok egytt azt eredmnyezik, hogy programkdjaink sokkal struktrltabb,


knnyebben bvthetv, knnyebben karbantarthatv vlnak, mintha hagyomnyos, nem
OOP-technikval rnnk ket. Hogy a C++ elnyeit lvezhessk, kicsit mdostanunk kell a
programozsrl alkotott kpnket. Ehhez segt hozz a fenti hrom tulajdonsg rszletesebb
trgyalsa.

Egysgbezrs
A C++ egyik fontos tulajdonsga, hogy lehetsgnk van az adataink s az ket manipull
programkd sszeforrasztsra, egy egysgbe zrsra, egy osztlyba foglalsra. (Ez az n.
encapsulation.) Pldul tegyk fel, hogy definltunk egy karakterkszletet (font-ot) ler
adatstruktrt (pldul egy fejrszt s az egyes karakterek tulajdonsgait ler tmbt), amely
kell informcit tartalmaz ahhoz, hogy a karaktereket kirajzolhassuk a kpernyre, s
vannak fggvnyeink, amelyekkel a karaktereinket megjelenthetjk, tsznezhetjk s
mozgathatjuk a kpen.
A hagyomnyos C-ben az a szoksos megolds, hogy az adatstruktrinkat s a hozzjuk
tartoz fggvnyeket egy nll, kln fordthat forrsmodulban helyezzk el. Ez a
megolds mr elg elegns, de az adatok s az ket manipull fggvnyek kztt mg nincs
explicit sszerendeltsg, tovbb ms programozk egy msik modulbl direkt mdon is
hozzfrhetnek az adatainkhoz, anlkl, hogy az adatok kezelsre szolgl fggvnyeinket
hasznlnk. Ilyen esetekben az alap-adatstruktra megvltozsa fatlis hibt okozhat egy
nagyobb project-ben.
A C++-ban specilis trolsi egysgfajtk, az osztlyok szolglnak arra, hogy adatokat s a
hozzjuk rendelt fggvnyeket egy egysgknt, egy objektumknt kezelhessnk. Az osztlyok
alaptpusa a C++-ban a class, amely hasonlt a hagyomnyos C-bl ismert struct-ra s
union-ra. A C++-ban a struct s union is egy bizonyos fajta osztlyok. A union-ra a
hagyomnyos rtelemben tovbbra is szksg van, a struct-ot a kulcsszt pedig a C++-ban
alapveten a hagyomnyos C-vel val kompatibilits biztostsa vgett tartottk meg.
Teht a fenti kulcsszavak szolglnak arra, hogy osztlyokat definilhassunk. A C++-ban egy
osztly tpus trolsi egysg ( class, vagy struct) fggvnyeket (n. fggvnymezket angolul member functions) kombinl adatokkal (adatmezkkel - angolul data members), s az
gy ltrejtt kombincit elrejtjk, elzrjuk a klvilg ell. Ezt rtjk az egysgbezrs alatt.
Egy class-deklarci hasonl a jl ismert struktradeklarcihoz:
class font {

A fenti deklarci utn a


definilhat:

...
};
font tpussal

tetszleges vltoz, objektumpldny (instance)

font times[10];
font *f_ptr;

Egy msik vltozs a hagyomnyos C-hez kpest az, hogy egy struct vagy class
tpuscmke (fenti pldnkban a font) kulcssz elhagysval nmagban is tpusrtk, teht
kzvetlenl is hasznlhat vltozk definilsra, deklarlsra.

A hagyomnyos C struktrk (struct) s a C++ osztlyok ( class) kztt a f klnbsg a


mezkhz val hozzfrsben van. A C-ben egy struktra mezi (a megfelel rvnyessgi
tartomnyon bell) szabadon elrhetek, mg a C++-ban egy struct vagy class minden
egyes mezjhez val hozzfrs nllan kzbentarthat azltal, hogy publikusnak,
privtnak, vagy vdettnek deklarljuk a public, private s protected kulcsszavakkal. (A
hozzfrsi szinteket ksbb rszletesebben is trgyaljuk.) A C s a C++ union-jai tbbkevsb hasonlak, egy C++ union-ban minden mez public, azaz mindenhonnan
hozzfrhet, s ez a hozzfrsi szint nem is vltoztathat meg. Egy struct-tal definilt
osztlyban alaprtelmezs szerint minden mez public (ennek a hagyomnyos C-vel val
kompatibilits az oka, egybknt a struct osztlyknt val hasznlata kerlend), de ez
megvltoztathat, mg egy class-szal definilt osztlyban a mezk alaprtelmezs szerint
private hozzfrsek, br ez is mdosthat. Az OOP-re jellemz az, hogy az adatmezket
privtnak, a fggvnymezket pedig publikusnak deklarljuk. A tovbbiakban csak a class
tpus osztlyokkal foglalkozunk, s javasoljuk, hogy a C++-ban programozk is csak a
class kulcsszval definiljanak osztlyokat.
Elbbi pdnknl maradva, a font tpust class-knt (osztlyknt) deklarlva elrhetjk,
hogy a privt (private) hozzfrs karakter-ler informcit csak a hozzjuk rendelt
publikus (public) fggvnyekkel lehessen kezelni. gy, ha a karakterfont lersban valamit
vltoztatunk, azt az adott projectben rsztvev tbbi programoz szre sem fogja venni
(feltve persze, hogy az adatmezkkel egytt az azokat kezel fggvnymezket is
mdostjuk). A font-defincink tbb mr nem egy konkrt reprezentcihoz ktdik, hanem
azokhoz a mveletekhez, amelyeket az egyes karakterekkel vgezhetnk.

rkls
Mi jut esznkbe az rkls szrl? Taln az, hogy a gyermek milyen tulajdonsgokat rklt
szleitl, vagy gondolhatunk egy csaldfra is. Ugyanilyen csaldfa pthet fel osztlyokkal
is. A C++-ban deklarlhatk szrmaztatott osztlyok (derived classes), amelyek rklik az
stpusok, az alaposztlyok (base classes) adat- s fggvnymezit. Ez lehetv teszi egy
hierarchikus osztlystruktra ltrehozst.
Nzznk meg erre egy egyszer pldt. Ha grafikus programot ksztnk, szksgnk lehet
arra, hogy kezeljk a grafikus kpernyn egy pont (pixel) helynek x s y koordintit.
Hozzunk ezrt ltre egy location (hely) nev struktrt:
struct location {
int x;
int y;
};
az x, y

Tegyk fel, hogy szksgnk van


koordintban lv pont tulajdonsgra is, pldul
nyilvn akarjuk tartani, hogy egy krdses pont milyen szin. Ezt megoldhatjuk a color
(szn) felsorolt tpus vltoz bevezetsvel. gy definiljuk a point (pont) tpust:
enum

Ezek utn

colortype { black, red,


blue,
green, yellow, white };
struct point {
int
x;
int
y;
enum colortype color;
};
deklarlhatunk point tpus vltozkat:

struct point origin, center,


current_pos, new_pos;

A C++-ban a fenti deklarcit rvidebben is rhatjuk - lvn egy osztlydefinicnl megadott


tpuscmke nmagban is tpus rtk:
point origin, center,
current_pos, new_pos;
Mint lttuk, a point tpusban is felhasznltunk olyan adatmezket, amilyenek a locationban szerepeltek. J lenne teht, ha point definilshoz felhasznlnnk a location tpust.
Nos, hagyomnyos C-ben a point-ot a location struktra felhasznlsval gy

definilhatnnk:

struct point {
struct location position;
colortype
color;
};

Ez nem ms, mint struktrk egymsbagyazsa (nested structures). Ugyanakkor a C++


esetben a deklarciban jelezhetjk, hogy a pont is egy hely. Ezt gy tehetjk meg, hogy
mind a point tpust, mind a location tpust class-knt definiljuk, s point-ot a locationbl szrmaztatjuk:
class location

protected:
int x;
int y;

}
class point : location
{
colortype color;
};

Ez a deklarci sokkal jobban kifejezi azt, hogy miben klnbzik a point tpus a
location tpustl. (A protected kulcssz jelentst ksbb trgyaljuk majd.) A klnbsg
teljesen nyilvnvalan abban van, hogy a point egy hely (location), amelyhez valamilyen
sznt is rendeltnk.
A kpernyn a pont helyzete a point defincijban explicit mdon nem szerepel, mert azt a
location tpustl rklte. Mivel a point tpus a location leszrmazottja, annak
minden mezjt rkli, de ugyanakkor a sznt ler mezvel bvtettk. Egy szrmaztatott
tpus defincis blokkjban csak az j, vagy megvltozott tulajdonsgoknak megfelel mezk
szerepelnek. Termszetesen a point tpusbl jabb osztlyokat szrmaztathatunk gy, hogy
tovbb bvtjk tetszleges tpus mezkkel. Az gy ltrehozott tpusok termszetesen (az j
tulajdonsgaik mellett) hordozni fogjk a point tpus minden meglv tulajdonsgt, s
hasznlhatk lesznek minden olyan esetben, amikor point is hasznlhat.
Azt az eljrst, amely ltal az egyik tpus rkli a msik tpus tulajdonsgait, rklsnek
hvjk. Az rkl a leszrmazott tpus ( descendant type). Az stpus (ancestor type) az,
amelytl a leszrmazott tpus rkl.
Fenti pldnkban a location az stpus, a point pedig a leszrmazott tpus. Ksbb ltni
fogjuk, hogy ez az eljrs korltlanul folytathat. Definilhatjuk a point leszrmazott tpust,
majd ennek a point leszrmazott tpusnak a leszrmazottjt. A programtervezs legnagyobb
rsze az OOP-ben a megfelel osztly-hierarchinak, azaz az osztlyok csaldfjnak a
ltrehozst jelenti.

A point tpus a location tpusnak egy kzvetlen leszrmazottja (immediate descendants).


Fordtva, a location tpus a point tpusnak kzvetlen stpusa ( immediate ancestor). Egy
objektumtpusnak brmennyi kzvetlen leszrmazottja lehet.
Az rkls szintaktikailag a kvetkezkppen nyilvnul meg. Tegyk fel, hogy az alfa
azonostj, point tpus objektum x koordintjra szeretnnk hivatkozni. Ezt a point tpus
hagyomnyos C szerinti begyazott struktrkkal trtn defincija esetn az
alfa.position.x mdon tehetnnk meg, mg C++-ban, mivel a point tpus mindent rkl
a location tpustl, az alfa.x kifejezs a megfelel hivatkozs.
Mint ahogy a C-ben egy tpussal, a C++-ban a point osztly segtsgvel tetszleges trolsi
egysgeket (jabb osztlyokat, vltozkat, tmbket, osztlyokra mutat pointereket, stb.)
definilhatunk, gy jutva klnbz objektum-pldnyokhoz:
point origin, line[80],
point *point_ptr1 = &origin;
point *point_ptr2 = line;

A C++-ban egy szrmaztatott tpus nemcsak egy stpustl rklhet (egy csaldfn pl.
minden egyednek van apja is s anyja is). Azt, amikor egy szrmaztatott tpus tbb stpusbl
kerlt levezetsre, tbbszrs rklsnek (multiple inheritance) nevezzk. A tbbszrs
rkls csak az AT&T 2.0-s verzij C++ fordtjval kompatibilis C++ rendszerekben
lehetsges. Tbbszrs rkls esetn az stpusokat egymstl vesszvel elvlasztva kell
felsorolnunk. Ha teht father s mother egy-egy ltez osztly (pldul class-knt definilt
tpus), akkor segtsgkkel a child tpust a kvetkezkppen deklarlhatjuk:
class child : father, mother
{
// Itt jonnek a 'child'-ra jellemzo
// ujabb tulajdonsagok mezoi.
};
rkli a father s a mother minden tulajdonsgt (azaz

A child teht
minden adat- s
fggvnymezjt), s egyben jabb tulajdonsgokkal (mezkkel) rendelkezhet.
A mezhozzfrs kapcsn a 2.8-as szakaszban ltni fogjuk, hogy egy szrmaztatott tpusban
az stpusoktl rklt fggvnymezk hozzfrsi szintjei mdosthatk az stpus-listban
a tpusazonostk eltt elhelyezett megfelel kulcsszavakkal ( private, protected).
Mivel a szrmaztatott tpusokkal mindent olyan mvelet elvgezhet, ami a definicija sorn
felhasznlt stpusokhoz felhasznlhat, ezrt egy szrmaztatott tpus mindig fellrl
kompatibilis az stpusaival.
sszefoglalva teht a fent lertakat: Hagyomnyos C-ben egy struktra nem tud rklni, a
C++ azonban tmogatja az rklst. A nyelvnek ez a kiterjesztse egy j trolsi egysgfajtban nyilvnul meg, amely hasonl a C-ben megszokott trterletfoglal trolsi
egysgekhez, a struktrkhoz s a -unionokhoz, de azoknl sokkal hatkonyabb. A trolsi
egysgek ezen j fajtja az osztly. Hatkonysga abban ll, hogy mg a hagyomnyos C-ben
hierarchikusan egymsbagyazott struktrarendszerben csak adatmezk "rkldnek", addig a
C++ osztlyok esetben egy objektum egyb tulajdonsgai - nevezetesen az, hogy az
adatmezkkel mit s hogyan lehet csinlni - is (azaz a fggvnymezk is) rkldnek.
Megjegyzend, hogy a hagyomnos C egymsba skatulyzott struktri esetben nincs sz
igazi rklsrl, s a skatulyzs rvn definilt jabb struktrk, s a definilshoz
felhasznlt struktrk kztt semmifle tpuskompatibilts nincs.

A C++ osztlyok tpus-kompatibilitst a point - location pros felhasznlsval az


albbiakban szemlltethetjk: egy point osztlyba tartoz vltoz minden olyan esetben
alkalmazhat, amikor egy location osztlyba tartoz rteket vrunk. Teht a
location *a;
point
b;

deklarci mellett C++-ban az a = &b rtkads helyes, mg hagyomnyos C-ben, ha point


s location egy-egy struktra, akkor a fenti rtkads helytelen.

Tbbrtsg (polimorfizmus)
A tbbrtsg (vagy sokalaksg, sokoldalsg) a C++-ban azt jelenti, hogy egy adott
stpusbl szrmaztatott tovbbi tpusok termszetesen rklik az stpus minden mezjt, gy
a fggvnymezket is. De az evolci sorn a tulajdonsgok egyre mdosulnak, azaz pldul
egy rkltt fggvnymez nevben ugyan nem vltozik egy leszrmazottban, de esetleg mr
egy kicsit (vagy ppen nagyon) mskpp viselkedik. Ezt a C++-ban a legflexibilisebb mdon
az n. virtulis fggvnyek (virtual functions) teszik lehetv. A virtulis fggvnyek
biztostjk, hogy egy adott osztly-hierarchiban (szrmazsi fn) egy adott fggvny
klnbz verzii ltezhessenek gy, hogy csak a ksz program futsa sorn derl, hogy ezek
kzl ppen melyiket kell vgrehajtsra meghvni. Ezt a mechanizmust, azaz a hv s a
hvott fggvny futsi id alatt trtn sszerendelst ksi sszerendelsnek (late binding)
nevezzk. Errl majd a 2.9-es rszben olvashatunk rszletesebben.
A tbbrtsgnek a fordtsi idben megvalsthat formja az n. overloading. (A szerintnk
is alkalmas magyar kifejezs helyett az eredeti angol kifejezst hasznljuk knyvnkben. gy
gondoljuk, hogy a szszerinti fordts, a tlterhels nem fejezi ki e fogalom lnyegt. A
overloading helyett esetleg hasznlhatnnk az tdefinils kifejezst, de mint ksbb ltni
fogjuk, ez sem precz megfogalmazs.) Nos, lssuk, mirl is van sz:
A hagyomnyos C-ben egy adott nvvel csak egy fggvnyt definilhatunk. Pldul ha
deklarljuk az
int

cube(int number);

fggvnyt, akkor kiszmthatjuk egy egsz szm kbt, de elkpzelhet, hogy egy long, vagy
egy double szm kbre van szksgnk. Termszetesen rhatnnk mg kt tovbbi
fggvnyt erre a clra, de a cube azonostt mr nem hasznlhatjuk:
long
lcube(long
lnumber);
double dcube(double dnumber);

A C++-ban mgis lehetsg van arra, hogy ugyanolyan azonostval lssuk el mind a hrom
fggvnyt. Ezt hvjk angolul overloading-nak. Ez teht azt jelenti, hogy lehetsgnk van
arra, hogy egy azonos nvvel tbb klnbz fggvnynk legyen, melyek termszetesen
klnbz adattpusokat dolgoznak fel:
int
cube(int
inumber);
long
cube(long
lnumber);
double cube(double dnumber);

Ha az azonos nev fggvnyek paramterlistja klnbz, a C++ gondoskodik arrl, hogy


egy adott tpus aktulis paramterrel mindig a megfelel fggvnyvltozatot hvja meg. gy
pldul a cube(10) hivatkozs a cube fggvny egsz rtket visszaad vltozatt hvja meg,
mg cube(2.5) hvssal a duplapontossg lebegpontos vltozatot aktivizljuk. Felhvjuk a

figyelmet arra a veszlyre, hogy igen knnyen a szndkainktl eltr fggvnyvltozatot is


aktivizlhatjuk. Pldul ha a double vltozatot akartuk meghvni a 2.0 rtkkel, de vletlenl
csak 2-t rtunk, akkor az int verzi hvst ttelezi fel a C++ fordt.
Az overloading ltalnosabban azt jelenti, hogy egy adatokon valamilyen operci
vgrehajtst jelent szimblumhoz (fggvnyazonosthoz, opertorhoz) tbb, klnbz
tpusra vonatkoz klnbz jelentst rendelnk. Hogy egy adott adathoz egy mvelet milyen
rtelmezse tartozik, az az adott adat tpustl, vagy preczebben fogalmazva az adott
opercit vgrehajt fggvny n. paramter-szignatrjtl fgg. Paramter-szignatrn azt
rtjk, hogy egy fggvnynek mennyi s milyen tpus paramtere van, s az egyes
paramterek milyen sorrendben kvetik egymst. Teht attl fggen, hogy egy fggvnyt
milyen tpus paramterekkel aktivizlunk, mindig az aktulis paramterekkel megegyez
szignatrj fggvnyvltozat hvsnak megfelel kdot generl a C++ fordt. Ezt
siganture matching-nek nevezzk. (Itt vlik nyilvnvalv a hagyomnyos C programokban a
modern stlus fggvnydefinicik, illetve fggvnydeklarcik fontossga: ezek nlkl a
fordt program nem tudja egyeztetni az aktulis paramterlistt a formlis paramterlistval.)
Az eddig elmondottakbl nyilvnval, hogy az overloading nem tdefinilst jelent, hiszen
amikor az overloading ltal egy szimblumhoz - a jelen pldnkban a cube
fggvnyazonosthoz - egy jabb jelentst rendeltnk, a korbbi jelentsek nem vesztek el.

Fggvnymezk definilsa
Ebben az alfejezetben az rkls fogalmnl hasznlt grafikus pldt folytatjuk.
Az elzekben lthattuk, hogy egy osztlynak nemcsak adatmezi, hanem fggvnymezi
(function members) is lehetnek. Egy fggvnymez nem ms, mint egy, a class defincin
bell deklarlt fggvny. (A fggvnymezket ms OOP nyelvekben, pldul a Smalltalkban, vagy a Turbo Pascal-ban metdusoknak hvjk).
Most deklarljunk egy get_x azonostj fggvnymezt a point osztly szmra. Ezt
ktflekppen tehetjk meg:
a)
vagy az osztly-defincin bell definljuk a fggvnyt (n. implicit inline
fggvnyknt),
b)
vagy az osztlydefincin bell csak deklarljuk, s azutn valahol ksbb definiljuk.
A kt mdszer klnbz szintaxissal rendelkezik. Lssunk egy pldt az els lehetsgre:
class point
{ int
x;
int
y;
colortype color;
int
get_x(void) { return x; };
....
// implicit inline definicio
};

Ez a fajta definci alaprtelmezsben inline fggvnyknt definilja a get_x-et. Ez az n.


implicit inline fggvny definici. Figyeljk meg, hogy az implicit inline fggvnydefinci
szintaxisa a hagyomnyos C-ben megszokottak szerinti.

A msodik lehetsgnl a C-szintaxissal csak deklarljuk a get_x fggvnyt a point


osztlyban, s ksbb adjuk meg a fggvny teljes definicijt:
class point
{ int
x;
int
y;
colortype color;
int
get_x(void);
// majd definialjuk
....
};
int point::get_x(void)
{
return x;
}
// Itt jobb lenne az implicit inline definicio
Figyeljk meg alaposan, hogy hasznltuk a :: hatskrt definil opertort (scope resolution
operator) a point::get_x fggvnydefinciban. A point osztlyazonost szksges ahhoz,
hogy a fordtprogram tudja, melyik osztlyhoz is tartozik a get_x fggvnydefincija,

valamint tudja azt is, hogy mi az rvnyessgi tartomnya. Ez teht azt jelenti, hogy a
pont::get_x fggvny (a hagyomnyos globlis vltozkon kvl) csak a point osztlyhoz
tartoz objektumok mezihez frhet hozz. Termszetesen ltezhet tbb, ms osztlyhoz
tartoz get_x fggvny is. (Erre a lehetsgre - br nem explicit mdon - utaltunk a
tbbrtsg trgyalsnl.) Az osztly-deklarcin belli fggvny-definici esetben
termszetesen nem volt szksg az rvnyessgi tartomnyt definil point:: eltagra,
hiszen a get_x fggvny hovatartozsa abban az esetben teljesen egyrtelm volt.
A hovatartozs definilsn tlmenen a point::-nak ms szerepe is van. Hatsa kiterjed az
t kvet fggvnydefincira oly mdon, hogy a get_x fggvnyen bell az x azonostj
vltozra val hivatkozs a point struktra x azonostj adatmezjre vonatkozik, valamint
a get_x fggvny a point osztly hatskrbe kerl (lsd a 2.6.2-es rszt).
Fggetlenl attl, hogy a fggvnymezt milyen mdon definiljuk, a lnyeg az, hogy van
egy get_x nev fggvnynk, ami szorosan hozz van kapcsolva a point nvvel elltott
osztlyhoz. Mivel a get_x-et mezknt definiltuk a point szmra, a point minden
adatmezjhez hozzfrhet. Ebben az egyszer pldnkban get_x egyszeren csak x rtkt
szolgltatja.
Elkpzelhet, hogy egy szrmaztatott tpusban loklisan deklarlunk egy fggvnymezt,
melynek azonostja s paramterlistja is megegyezik egy stpusban definilt
fggvnymez azonostjval s paramterlistjval, ugyanakkor a definci sorn fel
szeretnnk hasznlni az stpusbeli vltozatot. Mivel a ksbbi definciban lv
fggvnymez a sajt hatskrben elfedi a korbbi defincit, a szrmaztatott tpusban csak
az rvnyessgi tartomnyt definl opertor segtsgvel hasznlhatjuk az stpusban
definilt, "elfedett" fggvnymezt. Erre vonatkozan (az eddigi pldnkat egy kicsit
flretve) tekintsk az albbi deklarcikat:
class rectangle { int
...
void
};
class triangle { int
...

a, b;

// Negyszog adatai

show(void); // Kirajzolja
a, b, c;// Haromszog adatai

void show(void); // Kirajzolja


};
class house : rectangle,
// Ostipusok
triangle
{
// Egy hazat definial
......
// Tetszoleges mezok
void show(void); // Kirajzolja
};
// Az egyes fuggvenymezok definicioi:
void rectangle::show( ) { ... } // Egy negyszoget rajzol
void triangle::show( ) { ... } // Egy haromszoget rajzol
void house::show( )
// Egy hazat rajzol
{
// Itt az egyszeru 'show' azonosito a 'house' tipus
// fuggvenymezojet jelenti, a 'show' hivas rekurzio lenne
rectangle::show( ); // alap
...
triangle::show( ); // teto
...
::show( ); // Egy globalis, 'show' fuggveny hivasa
};

Amint az fenti pldbl is ltszik, ha egy hagyomnyos, nem egy osztly


fggvnymezjeknt deklarlt show fggvnyt akarunk meghvni, akkor a fggvnynv el
egy "res" rvnyessgi tartomnyt definil opertort (::) kell tennnk (azaz nem utaljuk
egy osztly hatskrbe sem, gy a teljes programra nzve globlis lesz a fggvny). Ezutn a
kitr utn a foglalkozzunk tovbb a megszokott point / location pldval.

Fggvnymezk aktivizlsa
A fggvnymezk egy adott tpus adathalmazon vgrehajtand mveleteket jelentenek.
Amikor teht a get_x fggvnyt meghvjuk, tudatnunk kellene vele azt is, hogy most ppen
melyik definilt point tpus objektum-pldny (object instance) x koordintira van
szksgnk, ppen ezrt valahogy ezt az informcit is kzlnnk kell a fordtprogrammal.
A megolds a hagyomnyos C struktra-mezkhz val hozzfrs szintaktikjnak
kiterjesztse. Ha origin egy point tpus objektum-pldny, akkor az origin.x
hivatkozshoz hasonlan az
origin.get_x( )
origin objektum-pldny get_x

kifejezs az
fggvnymezje ltal szolgltatott rtket
jelenti. A hagyomnyos C struktra adatmez-hozzfrshez hasonlan itt is a '.' (pont)
karakter jtssza az osztly mezkivlaszt opertornak (class component selector) szerept.
Az ltalnos szintaxis a kvetkez:
objektumnv.fggvnymez-nv( argumentumlista)
Az elbbiekhez hasonlan, ha p_ptr egy point* tpus mutat, akkor a
p_ptr->get_x( )

kifejezs a p_ptr ltal megcmzett point tpus objektum get_x fggvnymezje ltal
szolgltatott rtket adja.

A this nev, implicit mutat


Egy fggvnymezben direkt mdon is hivatkozhatunk arra az objektumra, amelyiknek a
fggvnymezejt aktivizltuk. Pldul a
class cc {

int m;
public:
....
int read_m(void) { return m; }

};
ha aa s bb cc

deklarci esetn,
tpusak, akkor az aa.read_m( ), illetve a bb.read_m( )
fggvnyhvsok esetn rendre az aa.m, illetve bb.m rtkeket kapjuk. A fggvnyhvs sorn
gy derl ki, hogy melyik objektum adatmezit kell hasznlni, hogy minden fggvnymez
szmra implicit mdon deklarlsra kerl egy this nev pointer. Ha teht a read_m
fggvny egy cc tpus osztly fggvnymezje, akkor a read_m-en bell this egy cc*
tpus pointer, ilyen mdon az els read_m hivatkozsnl this az aa vltozra, mg a
msodik hivatkozs alkalmval a bb-re mutat, azaz az els esetben this == &aa, a msodik
esetben pedig this == &bb.
A this mutat explicit mdon is megjelenhet a fggvnymezk defincija sorn:
class cc {

int m;
public:
int read_m(void) { return this->m; }

};

Konstruktorok definilsa
Most tekintsk t elszr a konstruktorok definilst a megszokott point tpusunk esetben;
bvtsk ki az eddigi deklarcit egy konstruktorral.
class point
{
int
x;
int
y;
colortype color;
int
get_x(void) { return x; }
int
get_y(void) { return y; }
colortype
get_color(void);
void
show(void);
void
hide(void);
point(int newx, int newy);
// konstruktor deklaracio
};
point::point(int newx = 0, int newy = 0)
{
// konstruktor definicio
x = newx;
y = newy;
color = black;
}

A konstruktort ugyangy deklarlhatjuk, mint minden egyb fggvnymezt. Figyeljk


ugyanakkor meg, hogy a konstruktor neve s az osztly neve ugyanaz, mind a kett point.

Innen tudja a fordtprogram, hogy az adott fggvnymez egy konstruktor. Figyeljk meg
azt is, hogy mint minden fggvnynek, a konstruktornak is lehetnek paramterei, a
konstruktor trzse pedig egy szablyos fggvnytrzs. Ez azt jelenti, hogy egy konstruktor
hvhat ms fggvnyeket s minden, a hatskrbe tartoz adathoz hozzfrhet. Az egyetlen,
de lnyeges klnbsg, hogy egy konstruktornak nem lehet tpusa, mg void sem! (gy
rtket sem adhat vissza.) A fenti konstruktor-deklarcit figyelembe vve az albbi mdon
deklarlhatunk egy point tpus objektumot:
point a_point(100,200);

Ez a deklarci aktivizlja a fent definilt konstruktort, s ennek kvetkeztben a pont x s y


koordintja rendre 100 ill. 200 lesz. Az overloading a konstruktorok esetben is
alkalmazhat, gy egy osztlynak tbb konstruktora is lehet, s mindig az aktulis
paramterlista alapjn dl el, hogy melyik vltozatot kell aktivizlni. Ha nem definilunk mi
magunk egy konstruktort, akkor a C++ generl egyet, amelynek nincsenek argumentumai.
Egy tovbbi C++ trkk, hogy az ltalunk definilt konstruktor argumentumaihoz egy
alaprtelmezst rendelhetnk, mint ahogy azt a point::point fggvny esetben is tettk.
Ekkor a
point a_point(5);
hatsra az x koordinta rtke

definci
alaprtelmezs szerinti 0 marad.

5 lesz, mg az y koordinta rtke az ltalunk adott

Egy specilis konstruktor az n. msol konstruktor ( copy constructor). Ha s egy osztly,


akkor a hozz tartoz msol konstruktor alakja s::s(s&). A msol konstruktor jelentsgt
megrthetjk, ha arra gondolunk, hogy sztringek trolsra hozunk ltre egy s osztlyt (teht
nem elgsznk meg a C karaktertmbjeivel, hanem pldul olyen kifinomult sztringkezel
rendszert szeretnnk kipteni, mint amilyen miatt sokan mg mindig ragaszkodnak a BASIChez). Ekkor ha a s b egy-egy s osztlyba tartoz sztringvltoz, s elvgezzk az a = b
rtkadst, akkor nem szeretnnk azt, hogy b tartalmnak megvltoztatsa maga utn vonja a
tartalmnak megvltozst. Hagyomnyos, egyszer C sztringkezels mellett a fenti rtkads
csak azt eredmnyezn, hogy egy karakter-pointer rtkt egy msik pointer vltozba
msoljuk, gy ugyanazt a karaktertmbt cmzik meg, gy a "msolat" nem vdhet meg az
"eredeti" sztringben vgrehajtott mdostsoktl.

Destruktorok definilsa
Ahogy konstruktorokat definilhatunk, ugyangy definlhatunk sajt magunk destruktorokat
is.
A statikus objektumok szmra a C++ futtat rendszer a main meghvsa eltt foglal
trterletet s a main befejezse utn felszabadtja azt. Az auto objektumok esetben a
trterletfelszabadts akkor trtnik meg, amikor az adott vltoz rvnyt veszti (teht az
objektum definicit tartalmaz blokk vgn). Az ltalunk definilt destruktorokat akkor
aktivizlja a C++ futtat rendszer, amikor egy objektumot meg kell szntetni. A destruktor
definci hasonlt a konstruktor defincira. Ha a point tpus objektumoknak
point::point a konstruktora, akkor point::~ point lesz a destruktoruk. A formai
klnbsget csak a ~ (tilde) karakter jelenti (ami a komplementls opertora).
class point
{
int
x;
int
y;
colortype color;

int
get_x(void) { return x; }
int
get_y(void) { return y; }
colortype get_color(void);
void
show(void);
void
hide(void);
point(int newx, int newy); // konstrktor
~point(void);
// destruktor
};

A fenti plda els rnzsre felesleges, hiszen elg lenne a C++ futtat rendszer
alaprtelmezs szerinti destruktorra hagyatkozni. Igen m, de egy megsznsre tlt pontot a
kpernyrl is el kell tntetni. Ez azt jelenti teht, hogy egy olyan destruktor fggvnyt kell
definilnunk a point tpus szmra, amelyik szksg esetn (pldul ha a hatterszin ==
get_color() igaz) a hide fggvny meghvsval az adott pontot le is trli a kpernyrl.

Mezhozzfrs
Ahogy a 2.1-es szakaszban az egysgbezrs kapcsn mr utaltunk r, egy osztly egyes
mezihez val hozzfrst mi magunk is kzben tarthatjuk a C++ ltal nyjtott alaprtelmezs
fellbrlsval.
A C++-ban a struct tpus osztlyokban csak rszben rvnyesl az egysgbezrs.
Nevezetesen az egysg megvan, ugyanis az adatmezk s a fggvnymezk egybe vannak
forrasztva, de nincsenek elzrva a klvilgtl. Ennek oka az, hogy az alaprtelmezs szerint
egy struct minden mezje publikus, a klvilgbl szabadon hozzfrhet. A j C++
programtervezs szem eltt tartja az adat- vagy mg inkbb az informcirejtst, azaz egy
osztly egyes mezit privtnak, vagy vdettnek deklarlja, s ezzel egyidejleg jl definilt,
krlhatrolt "hivatalos" kls hozzfrst biztost hozzjuk. ltalnos elvknt tekinthetjk
azt, hogy az adatmezk privtak vagy vdettek s a csak bels mveleteket vgrehajt
fggvnymezk szintn privtak, mg a klvilggal val kapcsolattartst publikus
fggvnymezk biztostjk. Ezrt javasoljuk a class hasznlatt a struct helyett, hiszen a
class alaprtelmezs szerinti mezhozzfrsi szintjei pontosan a fenti kivnalmaknak
felenek meg.
A C++-ban hrom, a cimkkhez formailag hasonl mdon hasznlhat kulcssz ll
rendelkezsnkre, hogy a mezhozzfrst mi magunk llthassuk be egy osztly-definci
sorn. A mezhozzfrs-szablyozs ltalnos szintaktikja a kvetkez:
hozzfrsi md : mezlista
ahol a hozzfrsi md a public, private, vagy protected kulcsszavak egyike lehet.
Pldul ha point-ot struct-knt deklarljuk, clszer az albbi mezhozzfrst belltani:
struct point {

// Ez most
private:
int
int
colortype
public:
int
colortype
point(int

csak a pelda miatt struct !!!


// Privat
x;
y;
color;
// Publikus
get_x(void) { return x; }
get_color(void);
newx, int newy);

};

Egy mezhozzfrst mdost kulcssz hatsa egy kvetkez hasonl kulcsszig, vagy az t
tartalmaz blokkzr kapcsos zrjelig tart.

Mezhozzfrsi szintek
Mint emltettk, hrom klnbz szinten rhetjk el egy osztly egyes mezit. Most
tekintsk t rszletesen, mit is jelent e hrom szint.
A private-knt deklarlt mezket csak az ugyanabban az osztlyban deklarlt
fggvnymezk rhetik el. A protected mezket az ugyanabban az osztlyban, s az adott
osztlybl szrmaztatott tovbbi osztlyokban definilt fggvnymezk rhetik el. A public
mezk korltozs nlkl elrhetk mindenhonnan, ahonnan az adott osztly is elrhet.
A struct-tal definilt osztlyok mezi alaprtelmezs szerint mind publikusak (public
elrsek), gy ahhoz, hogy az igazi egysgbezrst megvalsthassuk, a klvilg ell
elzrand mezket mi magunk kell, hogy a private kulcsszval privtnak deklarljuk (a
private rszt esetleg kvet jabb nyilvnos rszeket megint a public kulcsszval kell
megnyitnunk a klvilg szmra). Minthogy egy j C++ programoz mindent privtnak tekint
s csak azt mondja meg kln, hogy mely mezk publikusak, osztlyok definilsra
elnysebb a class-t hasznlni a struct helyett, ugyanis egy class minden mezje
alaprtelmezs szerint private. (Az egyetlen klnbsg a struct s a class kztt teht a
mezhozzfrs alaprtelmezsben van.) A point tpust class-knt definilva gy clszer a
mezhozzfrst a kvetkezk szerint szablyozni:
class point { // Alapertelmezes szerint privat:
int
x;
int
y;
colortype color;
public:
// Publikus:
int
get_x(void) { return x; }
int
get_y(void) { return
y; }
colortype get_color(void);
void
show(void);
void
hide(void);
point(int newx, int newy);
~point(void);
};

Nincs szksgnk teht a private kulcsszra az adatmezk definilsakor, ugyanakkor a


fggvnymezket public-nak kell deklarlni, hogy ltrehozhassunk point tpus
objektumokat s hogy bellk rtkeket olvashassunk ki.

Mezhozzfrs s rkls
A mezhozzfrs s az rkls egymssal szoros kapcsolatban llnak. Ennek ttekintshez
a point tpusnak a location-bl levezetett vltozatt hasznljuk gy, hogy mr a
mezhozzfrst is szablyozzuk.
enum colortype { black, red, blue, green, yellow, white };
class location {
protected:// A csak vedett mezoket a szar// maztatott tipusok is elerhetik
int
x;
int
y;
public:
// Publikus fuggvenyek a kulvilagnak
int
get_x(void);
int
get_y(void);
location(int ix, int iy); // Konstruktor
~location(void);
//
Destruktor
};
class point : public location
{ // A publikus szarmaztatas azt jelenti, hogy
// 'location' mezoinek hozzaferesi szintjei
// valtozatlanul oroklodnek.
protected: // A leszarmazottak is lathatjak
colortype color;
public:
colortype get_color(void);
void
show(void);
void
hide(void);
point(int ix, iy);
~point(void);

Destruktor

// Konstruktor
//

};

A location adatmezit - a class-ra vonatkoz private alaprtelmezssel szemben - csak


vdettnek deklarljuk, hogy a szrmaztatott tpusok - pldul a point - is hozzfrhessenek,
de azrt akrhonnan mgse legyenek elrhetk. A fggvnymezket (a konstruktort is
idertve) nyilvnosnak deklarltuk, hogy brki ltrehozhasson location tpus objektumot,
illetve hogy ki lehessen olvasni a koordintkat.
Egy szrmaztatott tpust ltalban a kvetkezkppen deklarlhatunk:
class

D : hozzfrs-mdost B { ... };

struct

D : hozzfrs-mdost B { ... };

illetve

ahol D a szrmaztatott (derived) osztly tpusazonostja, B pedig az alap osztly (base class)
tpusazonostja. A hozzfrs-mdost vagy public, vagy private lehet; hasznlata
opcionlis. Mint mr emltettk, class esetn a hozzfrs-mdost alaprtelmezs szerint

private, struct

esetn pedig public. Egy szrmaztatott osztly mezihez val hozzfrst


csak szigortani lehet az alaptpus egyes mezinek hozzfrsi szintjeihez kpest.
Egy osztlyt egy msikbl publikus vagy privt mdon szrmaztathatunk. Ha a hozzfrsmdost a private, akkor az sszes protected s public mez private lesz. Ha a
hozzfrs-mdost a public, akkor a szrmaztatott tpus vltozs nlkl rkli az alaptpus
mezhozzfrsi szintjeit. Egy szrmaztatott tpus az alaptpus minden mezjt rkli, de
azok kzl csak a public s a protected mezket hasznlhatja korltozs nlkl. Az
alaptpus private mezi a szrmaztatott tpusban direkt mdon nem rhetk el. A legutbbi
pldban location-t s point-ot gy deklarltuk, hogy megfelel informcirejts mellett
tovbbi, sszetettebb osztlyokat deklarlhassunk.
A hozzfrs mdostt clszer explicit mdon megadni, fggetlenl egy osztlyfajtra
(class-ra, vagy struct-ra) vonatkoz alaprtelmezstl.

Ksi sszerendels
Az elz rszekben egy sszetett grafikus programrendszer lehetsges alaptpusainak pldjn
mutattuk be az OOP egyes jellemzit. A point tpus a location-bl lett szrmaztatva,
ugyangy point-bl ltrehozhatunk egy vonalakat ler osztlyt, amelyet pldul line-nak
nevezhetnk, s mondjuk line-bl szrmaztathatunk mindenfle poligont. A poligonokra kt
vzlatos pldt mutattunk (triangle, rectangle), ezekbl felptve pedig mr egy
"valsgos" objektumok lersra val tpus, a house vzlatos lerst adtuk. (Ezek a pldk
termszetesen nem egy mkd program ltrehozsra, hanem sokkal inkbb egy-egy OOP
fogalom megvilgtsra voltak kihegyezve.) Az eddigi pldk tbbsgnek ugyanakkor volt
egy kzs vonsa, nevezetesen az, hogy deklarltunk bennk egy-egy show azonostj
fggvnymezt azzal a cllal, hogy az az adott tpus objektumot a kpernyn megjelentse.
Az alapvet klnbsg az ltalunk elkpzelt objektumtpusok kztt az, hogy milyen mdon
kell ket a kpernyre kirajzolni. Az egsznek van egy nagy htrnya: akrhnyszor egy
jabb alakzatot ler osztlyt definilunk, a hozztartoz show fggvnyt mindannyiszor jra
kell rnunk. Ennek az az oka, hogy a C++ alapveten hromflekppen tudja az azonos nvvel
elltott fggvnyeket egymstl megklnbztetni:

a paramterlistk klnbzsge (az n. paramterszignatra) alapjn, teht show(int


i, char c) s show(char *c, float f) egymstl klnbz fggvnyek,
az rvnyessgi tartomnyt definil opertor alapjn, teht a rectangle::show s a
triangle::show, valamint a ::show fggvnyek klnbzek,
illetve az egyes objektum-pldnyok fggvnymezit a mezkivlaszt opertor(ok)
segtsgvel.

Az ilyenfajta fggvnyhivatkozsok feloldsa mind fordtsi idben trtnik. Ezt nevezzk


korai, vagy statikus sszrendelsnek (early binding, static binding).
Egy komolyabb grafikus rendszer esetben azonban igen gyakran elfordul az a helyzet, hogy
csak az osztlydeklarcik llnak rendelkezsre forrsllomnyban (.h kiterjeszts include
file-okban), maguk a fggvnymez defincik pedig csak trgykd formjban vannak meg
(.obj file-okban). Ebben az esetben, ha a felhasznl a meglv osztlyokbl akar jabbakat
szrmaztatni, akkor a korai kts korltai miatt nem lesz knny dolga az alakzatmegjelent
rutinok megrsnl. A C++ ezt a problmt az n. ksi kts (late binding) lehetsgvel

hidalja t. Ezt a ksi ktst specilis fggvnymezk, a virtulis fggvnyek (virtual


functions) teszik lehetv.
Az alapkoncepci az, hogy a virtulis fggvnyhvsokat csak futsi idben oldja fel a C++
rendszer - innen szrmazik a ksi kts elnevezs. Teht azt a dntst, hogy pldul melyik
show fggvnyt is kell aktivizlni, el lehet halasztani egszen addig a pillanatig, amikor a
tnylegesen megjelentend objektum pontos tpusa ismertt nem vlik a program futsa
sorn. Egy virtulis show fggvny, amely el van "rejtve" egy elzetesen lefordtott
modulknyvtr egy B alaposztlyban, nem lesz vglegesen hozzrendelve a B tpus
objektumokhoz olyan mdon, ahogy azt norml fggvnymezk esetben lttuk. Nyugodtan
szrmaztathatunk egy D osztlyt a B-bl, definilhatjuk a D tpus objektumok
megjelentsre szolgl show fggvnyt. Az j forrsprogramot (amelyik az j D osztly
defincijt is tartalmazza) lefordtva kapunk egy .obj file-t, amelyet hozzszerkeszthetnk a
grafikus knyvtrhoz (a .lib file-hoz). Ezutn a show fggvnyhvsok, fggetlenl attl,
hogy a B alaposztlybeli fggvnymezre, vagy az j, D osztlybeli fggvnymezre
vonatkoznak, helyesen lesznek vgrehajtva. Lssuk ezt az egsz fogalomkrt egy kevsb
absztrakt pldn.
Tekintsk a jl bevlt point tpust, s egsztsk ki azt egy olyan fggvnnyel, amelyik egy
ilyen tpus objektum ltal reprezentlt pontot a kperny egyik helyrl thelyezi egy
msikra helyre. A point-bl azutn szrmaztassunk egy krk lersra alkalmas circle
tpust (olyan meggondols alapjn, hogy egy pont egy olyan kr, amelynek sugara 0, teht a
point tpust egyetlen adatmezvel, a sugrral kell kiegszteni).
enum
colortype { black, red, blue, green, yellow, white };
class location {
protected:
int x;
int y;
public:
location(int ix, int iy);
~location(void);
int get_x(void);
int get_y(void);

};
class point : public location
{
protected:
colortype
public:
colortype
void
void
void
point(int

color;
get_color(void);
show(void);
hide(void);
move(int dx, int dy);
ix,int iy);

~point(void);
};
// A point:: fuggvenyek definicioja:
...
void point::move(int dx, int dy)
{
// dx, dy offsetekkel athelyezi
if (color) hide( ); // Ez itt a point::hide

x += dx;
y += dy;
if (color) show( ); // Ez itt a point::show
}
class circle : public point
{
protected:
int
radius;
// A sugara
public: // Konstruktorhoz kezdeti x,y,r
circle(int ix,int iy,int ir);
colortype get_color(void);
void
show(void);
void
hide(void);
void
move(int dx, int dy);
void
zoom(int factor);
};
// A circle:: fuggvenyek definicioja:
...
void circle::move(int dx, int dy)
{
// dx, dy offsetekkel athelyezi
if (color) hide( ); // Ez itt a circle::hide
x += dx;
y += dy;
if (color) show( ); // Ez itt a circle::show
}
...
Figyeljk meg, hogy a kt move fggvny mennyire egyforma! A visszatrsi

tpusuk void s
a paramter-szignatrjuk is azonos, st, mg a fggvnytrzsek is azonosnak tnnek. Ht
akkor mi alapjn tudja a fordt, hogy mikor melyik fggvnyrl van sz? Ez esetben - ahogy
azt a norml fggvnymezk esetben lttuk - a move fggvnyeink abban klnbznek, hogy
ms-ms osztlyhoz tartoznak ( point::move, illetve circle::move). Flvetdik a krds:
Ha a kt move fggvny trzse is egyforma, akkor mirt kell bellk 2 pldny, mirt ne
rklhetn circle ezt a fggvnyt point-tl? Nos azrt, mert csak felletes rnzsre
egyforma a kt fggvnytrzs, ugyanis ms-ms hide, illetve show fggvnyeket hvnak ezeknek csak a neve s a szignatrja azonos. Ha circle a point-tl rkln a move
fggvnyt, akkor az nem a megfelel hide, illetve show fggvnyeket hvn: nevezetesen a
krre vonatkoz fggvnyek helyett a pontra vonatkozkat aktivizln. Ez azrt van gy, mert
a korai kts kvetkeztben a point::hide, illetve a point::show lenne a point tpus move
fggvnyhez hozzrendelve, s az rkls ltal a circle tpus move fggvnye is ezeket
fggvnyeket hvn. Ezt a problmt gy oldhatjuk meg, ha a show, illetve a hide
fggvnyeket virtulis fgvnyekknt deklarljuk. Ekkor nyugodtan rhatunk egy kzs move
fggvnyt a point s a circle szmra (pontosabban fogalmazva a circle tpus rklhetn
a point tpus move fggvnyt), s majd futsi idben fog kiderlni, hogy melyik show,
illetve hide fggvnyt kell meghvni.

Virtulis fggvnyek deklarlsa


A virtulis fggvnyek deklarlsnak szintaktikja nagyon egyszer: a fggvnymez els
deklarlsakor helyezzk el a virtual tpusmdost szt is:
virtual void show(void);
virtual void hide(void);

Figyelem! Csak fggvnymezk deklarlhatk virtulis fggvnyekknt. Ha egy fggvnyt


egyszer mr virtulisnak deklarltunk, akkor egyetlen szrmaztatott osztlyban sem

deklarlhatjuk jra az adott fggvnyt ugyanolyan paramter-szignatrval, de ms


visszatrsi tpussal. Ha egy egyszer mr virtulisnak deklarlt fggvnyt egy szrmaztatott
tpusban jra deklarljuk s az jbli deklarci alkalmval ugyanolyan viszszatrsi tpust s
paramter-szignatrt alkalmazunk, mint a korbbi deklarciban, akkor az jonnan deklarlt
fggvny automatikusan virtulis fggvny lesz. Termszetesen egy virtulis fggvnyt ms
paramter-szignatrval jradeklarlhatunk, de akkor erre a vltozatra a virtulis
fggvnykezel rendszer nem fog mkdni. Az azonos szimblumhoz rendelt klnbz
jelentsek (function overloading (fggvnynv tdefinil) - lsd a tbbrtsgnl) hasznlata
sok veszlyt rejthet, gyhogy ezt csak gyakorlott C++ programozknak ajnljuk.

Dinamikus objektumok
Eddigi pldinkban csak statikus objektumokkal volt dolgunk (amelyek szmra a
fordtprogram foglal le trterletet a fordts sorn), jllehet a hagyomnyos C-ben mr
megszokhattuk, hogy vltozink egy rsze szmra mi magunk foglalunk le trterletet, s a
vltozkat megszntetve felszabadtjuk a memrit, ha az adott vltozkra tbb mr nincs
szksgnk.
Termszetesen a C++-ban sem kell lemondanunk a dinamikus trkezelsrl az objektumok
kapcsn, akr hasznlhatjuk is a hagyomnyos C-ben megismert trkezel fggvnyeket,
pldul a malloc-ot is. Ezt mgsem javasoljuk objektumok esetben, mert a C++ a
hagyomnyos trkezel fggvnyeknl jval hatkonyabb mdszereket knl. Pldul
biztostja, hogy a dinamikusan kezelt objektumok esetben is aktivizldjanak a megfelel
konstruktorok s destruktorok.

Dinamikus objektumok ltrehozsa


Dinamikus objektumok ltrehozsra a C++ new opertora szolgl. Tekintsk erre a
kvetkez pldt:
circle *egy_kor = new circle(100,200,50);
Ennek hatsra az egy_kor azonostj circle tpusra mutat pointer megkapja egy
sizeof(circle) darab byte mret, circle tpus objektum szmra lefoglalt trterlet
cmt. A trterlet-foglals sorn vgrehajtsra kerl a circle( ) konstruktor-hvs is. A

ltrehozott j "kr" kzppontjnak koordinti rendre 100 s 200, mg a sugr rtke 50 lesz.
A new opertorral tmbk szmra is foglalhatunk helyet. A new-nak ez az alternatv
szintaxisa a kvetkez:
new

tpus [mret]

A kifejezs rtke az adott tpus szmra lefoglalt adott mret tmbre mutat pointer lesz.
A new-val trtn memria-foglalskor fellp hibkat a _new_handler pointer
(elredefinilt globlis vltoz) ltal mutatott fggvny kezeli le. Alaprtelmezsben
sikertelen trterlet-foglalsi kisrlet esetn new visszatrsi rtke NULL, s programunk
futsa gy folytatdhat, mintha mi sem trtnt volna, ugyanis a _new_handler-en keresztl

aktivizlt hibakezel nem csinl semmit. Ugyanakkor lehetsgnk van arra, hogy a
_new_handler-t egy sajt hibakezelre lltsuk a set_new_handler( ) fggvnyhvs
segtsgvel. Ezt a kvetkez plda szemllteti:
#include <iostream.h>
#include <stdlib.h>
// ***********************************************************
void out_of_store(void)
// Sajat hibakezelo-fv. new-hoz
// ***********************************************************
{
cerr << "operator new failed: out of store\n";
exit(1);
// cerr-t lasd 3.11.3. alatt
}
// ***********************************************************
typedef void (*PF)();
// Fuggvenyre mutato tipus
extern PF set_new_handler(PF);// _new_handler-t allitja
struct pp { double x,y,z,w;
// Nagy struktura. Ennek prolong
a,b,c,d; };// balunk sok helyet foglalni
// ***********************************************************
main()
// _new_handler atallitasat szemlelteto program
// ***********************************************************
{
set_new_handler(&out_of_store);
pp *p = new pp[65535];
cout << "Meghivtuk new-t, p = " << long(p) << '\n';
}
// cout-ot is lasd 3.11.3 allatt
// ***********************************************************

A fenti program soha sem fog "normlisan" lefutni, hanem mindig az operator new failed: out
of store zenetet kapjuk a kpernyn s visszatrnk 1-es hibakddal az opercis
rendszerhez.

Dinamikus objektumok megszntetse


Ha new-val dinamikusan hozunk ltre objektumokat, akkor a mi felelssgnk, hogy meg is
szntessk azokat, amikor mr nincs rjuk szksgnk. Erre szolgl a delete opertor. Egy
nem NULL rtk, tetszleges objektumra mutat pointerre alkalmazva a delete opertort,
aktivizldik az adott tpus objektumhoz tartoz destruktor s a pointer ltal megcmzett
trterlet felszabadul. A NULL-ra alkalmazott delete opertornak nincs semmi hatsa. Fontos,
hogy a delete csak a new-val ltrehozott dinamikus objektumok megszntetsre
hasznlhat. A delete opartornak is van a new-hoz hasonl alternatv szintaxisa:
delete

objektum [mret]

Megjegyzend, hogy a C++ nem definil memria-karbantart (garbage collector) rendszert,


gy az "elvesztett" dinamikus objektumokat nem tudjuk megszntetni.

Rokonok s bartok
Az rkls kvetkeztben klnbz stpusokbl kiindulva teljes szrmazsi fkat, mskpp
kifejezve osztlyhierarchikat hozhatunk ltre. A tbbszrs rkls azt is lehetv teszi,
hogy egy jabb tpust tbb stpus leszrmazottjaknt hozzunk ltre. ly mdon egymssal
ronkonsgban ll tpusok deklarlhatk. Elkpzelhet azonban, hogy egy programon bell
egymstl teljesen fggetlen csaldfk jnnek ltre. Az egy tpuscsaldba (szrmazsi fba,

csaldfba, osztlyhierarchiba) tartoz tpusok egyms rokonai, mg a klnbz csaldba


tartozk egyms szmra teljesen idegenek.
Az letben az ember termszetesen nem csak a rokonaival hajtja tartani a kapcsolatot, hanem
szksge van bartokra is, azaz olyan egyedekre, akikkel nincs semmifle szrmazsi
kapcsolatban, de mgis fontosak egyms szmra. Nos, egy C++ programban deklarlt
tpusok esetben is hasonl a helyzet. Ha komolyan vettk az informcirejtst, szigoran
kzbentartottuk a mezhozzfrst az egyes tpuscsaldok deklarcijakor, akkor egy adott
tpus egy fggvnymezje nem frhet hozz egy nem rokon tpus adatmezihez. Mrpedig
nem zrhat ki az az eset, amikor egy ilyen hozzfrs haszonnal jrhat. Hogy egy C++
programban ezt a hasznot lvezhessk, a friend kulcsszval megadhatjuk, hogy a
programunk nem rokon trolsi egysgei kzl melyek llnak egymssal bartsgban.
Kicsit egzaktabban: Szksgnk lehet arra, hogy egy adott osztly privt adatmezit egy
olyan fggvnnyel is manipullhassuk, amelyik nem eleme az adott osztlynak. Ezt gy
rhetjk el, hogy az osztly deklarcijakor a friend kulcsszt kveten felsoroljuk azokat a
kls fggvnyeket, amelyek szmra jogot szeretnnk biztostani az adott osztly
adatmezinek elrsre. A friend deklarci az osztly-deklarcinak akr a private, akr a
public rszben is lehet. Lssunk nhny pldt a "fggvny-bartsgra":
int ext_func(void) { ... }
...
class xx {
protected:
int data_1;
private:
int data_2;
friend int ext_func(void);
public:
xx(int d1, int d2);
int get_data_1(void);
};
Az elbbi pldban ext_func egy norml C fggvny. Az xx osztly deklarcijakor jogot
biztostottunk szmra a data_1 s data_2 adatmezk elrsre. Termszetesen egy msik

osztly fggvnymezi is lehetnek bartok:


class yy {

....
void yy_func1(void);
....

};
class zz {

....
void zz_func(void);
friend void yy::yy_func1(void);
....

};

Itt teht az yy osztly yy_func1 nev fggvnymezjt deklarltuk a zz osztly bartjnak.


Arra is lehetsgnk van, hogy az yy osztlybl ne csak egy, hanem mindegyik
fggvnymezt zz bartjv tegyk:
class zz {

};

....
void zz_func(void);
friend class yy;
....

Operator overloading
A C++-nak van egy specilis tulajdonsga, amellyel kevs ms nyelv rendelkezik.
Nevezetesen az, hogy a nyelv ltal definilt, ltez opertorokhoz jabb jelentst
rendelhetnk. Ez hasznos lehet abbl a clbl, hogy valamilyen osztlyknt definilt j
adatstruktrn is elvgeztethessk azt a mveletet, amit az illet opertortl megszoktunk az
elemi tpusok esetben. Ha pldul definilunk egy halmazok reprezentcijra szolgl
tpust, akkor nagyon kellemes, ha a + opertorral halmazok unijt, a * opertorral pedig
halmazok metszett kpezhetjk. Vagy ha a s b egy-egy mtrix tpus vltoz, akkor j
lenne, ha az a * b kifejezs szintn mtrix tpus eredmnyt, nevezetesen a kt mtrix
szorzatt szolgltatn.
A polimorfizmus trgyalsakor mr utaltunk arra, hogy egy adott mvelet vgrehajtst
jelent szimblumhoz tbbfle jelentst rendelhetnk olyan rtelemben, hogy azt a bizonyos
mveletet tbb, klnbz tpus adaton is vgre szeretnnk hajtani - ezt neveztk
overloading-nak. Gondoljunk bele, hogy az overloading nem egszen C++ tulajdonsg,
hiszen a hagyomnyos C-beli opertorok is kpesek klnbz adattpusokon is ugyanazt a
mveletet vgrehajtani. Erre egy igen kzenfekv plda az rtkads opertora (amelyik mind
klnbz sorszmozott tpus adatokon, mind pedig lebegpontos szmokon rtelmezett
mvelet), vagy gondoljunk az egyes aritmetikai opertorokra, amelyek a hagyomnyos C
klnbz elemi tpusain nagyjbl egyformn mkdnek.
Az opertor-overloading lehetsgt a C++ kiterjeszti gy, hogy az egyes opertorokhoz a
felhasznl is megadhat jabb rtelmezst egy n. opertor fggvny segtsgvel. Ez gy
lehetsges, hogy az operator kulcsszt kveten rjuk azt az opertor-szimblumot,
amelyikhez az jabb jelentst szeretnnk rendelni. gy pldul az operator+ annak a
fggvnynek lesz az azonostja, amelyikkel a + opertorhoz rendelnk egy jabb jelentst.
Nzznk erre egy pldt!

C++ I/O knyvtrak


Az stdio.h include file-ban deklarlt szabvnyos folyam jelleg formtumozott I/O
fggvnyek (mint pldul printf, scanf, stb.) mellett a C++ jabb hasonl, folyam-orientlt
fggvnyeket tartalmaz az iostreams knyvtrban. Az j C++ I/O fggvnyek deklarcijt
az iostream.h include file-ban tallhatjuk. Az j I/O knyvtr hasznlata elnyket nyjt az
stdio.h-hoz kpest. Ezek egyike, hogy a fggvnyek szintaxisa sokkal egyszerbb,
elegnsabb, olvashatbb. Egy msik tnyez, hogy a C++ folyamkezel mechanizmusa a
leggyakrabban elfordul esetekben hatkonyabb s rugalmasabb, mint a hagyomnyos C
folyamkezels. A formtumozott kimenet ellltsa az opertor-overloadingnak
ksznheten pldul sokszor egyszerbb, mint a printf-fel. Ugyanazon opertor
hasznlhat mind elredefinilt, mind pedig a felhasznl ltal definilt adattpusok
kiiratsra.
A C++-ban ngyelre definilt folyam jelleg objektum van. Ezek a kvetkezk:

cin a szabvnyos bemenet, amely ltalban a billentyzet. A hagyomnyos C-beli


stdin-nek felel meg.
cout a szabvnyos kimenet, amely ltalban a kperny. A hagyomnyos C-beli
stdout-nak felel meg.
cerr a szabvnyos hibakimenet, amely ltalban a kperny. A hagyomnyos C-beli

stderr-nek felel meg.


clog a cerr teljesen bufferelt vltozata, nincs megfelelje a C-ben.

Ezek a folyamok tetszleges eszkzre vagy file-ba tirnythatk, mg C-ben csak az stdin s
az stdout irnythat t. Az iostream knyvtr elemei hierarchikusan plnek egymsra. A
knyvtr elemei az alap-primitvtl a legspecializltabb elemig a kvetkezk:
streambuf a memriabuffereket s az azokat kezel eljrsokat tartalmazza,
ios a folyamok llapotvltozit s a hibkat kezeli,
istream egy streambuf-bl szrmaz formtumozott s ktetlen formtum
karakterfolyam konverzijt vgzi,
ostream egy streambuf-ba kldend formtumozott vagy ktetlen formtum
karakterfolyam konverzijt vgzi,
iostream istream-et s ostream-et kombinlja annak rdekben, hogy ktirny
folyamokat lehessen kezelni,
istream_withassign a cin folyam szmra definil konstruktorokat s rtkad
opertorokat,
ostream_withassign a cout, cerr s a clog folyamok szmra definil
konstruktorokat s rtkad opertorokat.
Az istream osztly az overloading segtsgvel egy j jelentst ad a >> opertor szmra a
standard elemi tpusok esetre. Ha az x vltoz tpusa standard elemi tpus, akkor a cin>>x
kifejezs mellkhatsaknt az x tpusnak (char, int, long, float, double) megfelel
konverzis input rutin az x vltoznak megfelel memriacmre teszi a standard bemenetrl
rkez adatot. A kifejezs rtkeknt cin-t kapjuk vissza.
Az elbbiekhez hasonl mdon, az ostream osztlyban tallhat a << opertor j
rtelmezse. A cout<<x; utasts hatsra az x vltoz tpusnak megfelel output rutin a
szabvnyos kimeneti llomnyra kldi az x rtknek megfelel karaktersorozatot s
visszaadja cout-ot. (Itt x tpusa szintn valamelyik standard elemi tpus lehet.)
A << s >> opertor-fggvnyek a megfelel folyam osztlyra vonatkoz referencia tpus
visszatrsi rtket adnak, gy tbb ilyen opertor lncba fzhet:
int
i = 0, x = 243;
double d = 0;
cout << "The value of x is " << x << '\n';
cin >> i >> d; // Egy int-et, utana SPACE-t,
// majd egy double-t var.

IBM PC specifikus lehetsgek

You might also like