Tanuljuk meg a C++ programozási nyelvet 24 óra alatt 9789639637382 [PDF]

Csupán 24, egy óra vagy még rövidebb idő alatt elvégezhető lecke után képesek leszünk C++ nyelvű programokat írni. A lec

134 32 76MB

Hungarian Pages [542] Year 2008

Report DMCA / Copyright

DOWNLOAD PDF FILE

Table of contents :
Scan10025
Scan10026
Scan10027
Scan10028
Scan10029
Scan10030
Scan10031
Scan10032
Scan10033
Scan10034
Scan10035
Scan10036
Scan10037
Scan10038
Scan10039
Scan10040
Scan10041
Scan10042
Scan10043
Scan10044
Scan10045
Scan10046
Scan10047
Scan10048
Scan10049
Scan10050
Scan10051
Scan10052
Scan10053
Scan10054
Scan10055
Scan10056
Scan10057
Scan10058
Scan10059
Scan10060
Scan10061
Scan10062
Scan10063
Scan10064
Scan10065
Scan10066
Scan10067
Scan10068
Scan10069
Scan10070
Scan10071
Scan10072
Scan10073
Scan10074
Scan10075
Scan10076
Scan10077
Scan10078
Scan10079
Scan10080
Scan10081
Scan10082
Scan10083
Scan10084
Scan10085
Scan10086
Scan10087
Scan10088
Scan10089
Scan10090
Scan10091
Scan10092
Scan10093
Scan10094
Scan10095
Scan10096
Scan10097
Scan10098
Scan10099
Scan10100
Scan10101
Scan10102
Scan10103
Scan10104
Scan10105
Scan10106
Scan10107
Scan10108
Scan10109
Scan10110
Scan10111
Scan10112
Scan10113
Scan10114
Scan10115
Scan10116
Scan10117
Scan10118
Scan10119
Scan10120
Scan10121
Scan10122
Scan10123
Scan10124
Scan10125
Scan10126
Scan10127
Scan10128
Scan10129
Scan10130
Scan10131
Scan10132
Scan10133
Scan10134
Scan10135
Scan10136
Scan10137
Scan10138
Scan10139
Scan10140
Scan10141
Scan10142
Scan10143
Scan10144
Scan10145
Scan10146
Scan10147
Scan10148
Scan10149
Scan10150
Scan10151
Scan10152
Scan10153
Scan10154
Scan10155
Scan10156
Scan10157
Scan10158
Scan10159
Scan10160
Scan10161
Scan10162
Scan10163
Scan10164
Scan10165
Scan10166
Scan10167
Scan10168
Scan10169
Scan10170
Scan10171
Scan10172
Scan10173
Scan10174
Scan10175
Scan10176
Scan10177
Scan10178
Scan10179
Scan10180
Scan10181
Scan10182
Scan10183
Scan10184
Scan10185
Scan10186
Scan10187
Scan10188
Scan10189
Scan10190
Scan10191
Scan10192
Scan10193
Scan10194
Scan10195
Scan10196
Scan10197
Scan10198
Scan10199
Scan10200
Scan10201
Scan10202
Scan10203
Scan10204
Scan10205
Scan10206
Scan10207
Scan10208
Scan10209
Scan10210
Scan10211
Scan10212
Scan10213
Scan10214
Scan10215
Scan10216
Scan10217
Scan10218
Scan10219
Scan10220
Scan10221
Scan10222
Scan10223
Scan10224
Scan10225
Scan10226
Scan10227
Scan10228
Scan10229
Scan10230
Scan10231
Scan10232
Scan10233
Scan10234
Scan10235
Scan10236
Scan10237
Scan10238
Scan10239
Scan10240
Scan10241
Scan10242
Scan10243
Scan10244
Scan10245
Scan10246
Scan10247
Scan10248
Scan10249
Scan10250
Scan10251
Scan10252
Scan10253
Scan10254
Scan10255
Scan10256
Scan10257
Scan10258
Scan10259
Scan10260
Scan10261
Scan10262
Scan10263
Scan10264
Scan10265
Scan10266
Scan10267
Scan10268
Scan10269
Scan10270
Scan10271
Scan10272
Scan10273
Scan10274
Scan10275
Scan10276
Scan10277
Scan10278
Scan10279
Scan10280
Scan10281
Scan10282
Scan10283
Scan10284
Scan10285
Scan10286
Scan10287
Scan10288
Scan10289
Scan10290
Scan10291
Scan10292
Scan10293
Scan10294
Scan10295
Scan10296
Scan10297
Scan10298
Scan10299
Scan10300
Scan10301
Scan10302
Scan10303
Scan10304
Scan10305
Scan10306
Scan10307
Scan10308
Scan10309
Scan10310
Scan10311
Scan10312
Scan10313
Scan10314
Scan10315
Scan10316
Scan10317
Scan10318
Scan10319
Scan10320
Scan10321
Scan10322
Scan10323
Scan10324
Scan10325
Scan10326
Scan10327
Scan10328
Scan10329
Scan10330
Scan10331
Scan10332
Scan10333
Scan10334
Scan10335
Scan10336
Scan10337
Scan10338
Scan10339
Scan10340
Scan10341
Scan10342
Scan10343
Scan10344
Scan10345
Scan10346
Scan10347
Scan10348
Scan10349
Scan10350
Scan10351
Scan10352
Scan10353
Scan10354
Scan10355
Scan10356
Scan10357
Scan10358
Scan10359
Scan10360
Scan10361
Scan10362
Scan10363
Scan10364
Scan10365
Scan10366
Scan10367
Scan10368
Scan10369
Scan10370
Scan10371
Scan10372
Scan10373
Scan10374
Scan10375
Scan10376
Scan10377
Scan10378
Scan10379
Scan10380
Scan10381
Scan10382
Scan10383
Scan10384
Scan10385
Scan10386
Scan10387
Scan10388
Scan10389
Scan10390
Scan10391
Scan10392
Scan10393
Scan10394
Scan10395
Scan10396
Scan10397
Scan10398
Scan10399
Scan10400
Scan10401
Scan10402
Scan10403
Scan10404
Scan10405
Scan10406
Scan10407
Scan10408
Scan10409
Scan10410
Scan10411
Scan10412
Scan10413
Scan10414
Scan10415
Scan10416
Scan10417
Scan10418
Scan10419
Scan10420
Scan10421
Scan10422
Scan10423
Scan10424
Scan10425
Scan10426
Scan10427
Scan10428
Scan10429
Scan10430
Scan10431
Scan10432
Scan10433
Scan10434
Scan10435
Scan10436
Scan10437
Scan10438
Scan10439
Scan10440
Scan10441
Scan10442
Scan10443
Scan10444
Scan10445
Scan10446
Scan10447
Scan10448
Scan10449
Scan10450
Scan10451
Scan10452
Scan10453
Scan10454
Scan10455
Scan10456
Scan10457
Scan10458
Scan10459
Scan10460
Scan10461
Scan10462
Scan10463
Scan10464
Scan10465
Scan10466
Scan10467
Scan10468
Scan10469
Scan10470
Scan10471
Scan10472
Scan10473
Scan10474
Scan10475
Scan10476
Scan10477
Scan10478
Scan10479
Scan10480
Scan10481
Scan10482
Scan10483
Scan10484
Scan10485
Scan10486
Scan10487
Scan10488
Scan10489
Scan10490
Scan10491
Scan10492
Scan10493
Scan10494
Scan10495
Scan10496
Scan10497
Scan10498
Scan10499
Scan10500
Scan10501
Scan10502
Scan10503
Scan10504
Scan10505
Scan10506
Scan10507
Scan10508
Scan10509
Scan10510
Scan10511
Scan10512
Scan10513
Scan10514
Scan10515
Scan10516
Scan10517
Scan10518
Scan10519
Scan10520
Scan10521
Scan10522
Scan10523
Scan10524
Scan10525
Scan10526
Scan10527
Scan10528
Scan10529
Scan10530
Scan10531
Scan10532
Scan10533
Scan10534
Scan10535
Scan10536
Scan10537
Scan10538
Scan10539
Scan10540
Scan10541
Scan10542
Scan10543
Scan10544
Scan10545
Scan10546
Scan10547
Scan10548
Scan10549
Scan10550
Scan10551
Scan10552
Scan10553
Scan10554
Scan10555
Scan10556
Scan10557
Scan10558
Scan10559
Scan10560
Scan10561
Scan10562
Scan10563
Scan10564
Scan10565
Scan10566
Scan10567
Papiere empfehlen

Tanuljuk meg a C++ programozási nyelvet 24 óra alatt
 9789639637382 [PDF]

  • 0 0 0
  • Gefällt Ihnen dieses papier und der download? Sie können Ihre eigene PDF-Datei in wenigen Minuten kostenlos online veröffentlichen! Anmelden
Datei wird geladen, bitte warten...
Zitiervorschau

Az operátorok precedenciája és asszociativitása

ACésaC+ + kulcsszavai

A táblázatban elóbb szere p lő operátorok magasabb precedenciával rendelkeznek, mint a kéKulcsszavak felbukkanók. A C+ + szabályai szerint egy kifejezés leg belső zárójelén belül található műve l eteket a program az operátorok precedenciájának sorrendjében vég zi el úgy, hogy and' (&&) a legmagasabb rangú operátorral e lőírt műve l etet hajtja végre előszö r, majd csö k kenő sor- and_e,,' (&,, ) rend szerint folytatja. tv. egyoperandusú plusz (+) és minusz (-) a precedencia-lista maso- .,m dik szintjén szerepelnek. vagyis - teljesen logikusan - mege l őzik az aritmetikai megfele l ői­ a u to sőbb

ket, amelyek az ölödik szinten kaptak helyet. A második szinten található & operátor a "címe" operátor, míg a g, szinten látható ugyanilyen jel a bitenkénti AND művelet operátora, A 2, szinten látható " a mutató által cfmzett tartalom kiolvasását végzi, míg a 4. szinten lát· ható ugyanilyen jel a szorzás, Amennyiben a műve letek végrehajtásának sorrendjére nem utalnak zárójelek, úgy az azonos precedenciaszinthez tartozó műveleteket a program jobbról balra. vagy balról jobbra haladva hajtja végre a táblázatban megadottnak megfelelöen, Szint 1 (magas)

2 3

'0"

static

friend'

statiC, cast'

goto

struct switch

bool'

"in l ine'

break

'ne

template ' this '

case

long

throw'

mut a ble'

true '

Kiértékelési sorrend

( ) ::

balról jobbra balról jobbra

char

names pace

try'

class'

new'

typedef

campl' (-)

not '

const

not,eq' ( I,,)

typename '

const, cast '

operator'

union

continue

or' (I I )

unsigned

default

or, eq' (I ,, )

us!n g '

delete '

private'

virtual'

do

protected'

void

· [ l

-> ++ --

type i d keyword, typecast * & ! - + ... -- ... aizeof new delete

)

«

17 18 (alacsony)

bitor' ( I)

size, t

Operátorok

,-

16

(&)

s izeo f

float

catch'

4 5 6

8 9 10 11 12 13 14 15

bitand'

false'

jobbról balra balról jobbra balról jobbra balról jobbra balról jobbra balról jobbra balról jobbra balról jobbra balról jobbra balról jobbra balról jobbra balról jobbra jobbról balra jobbról balra

· * ->* • /% »

< >= ='" I ",

••

••

"

?,

= * = /= ... = -= %= «=»;&=A=I= throw , (vessző operator)

balról jobbra balról iobbra

(l)

public' double dynarnic, caet' re gister

type id'

volatUe' wch ar, t

else

reinter -

while

on=

pret, cast'

xor '

explidt'

return

xor, e q'

export'

short

extern

eigned

TIpus

16 bit

32 bit

Tartománv

uneigned short int short int uneiqned long int long int int

2 2 4 4 2

2 2 4 4 4

unsigned int s i ze_ t char wchar_t bool float double l ong d ouble

2 bájtoe 2 bájtoe 1 bájtoe 2 bájtoe l bájtos 4 báj t os 8 bájtos 10 bájt o s

O-tól 65 535-ig -32 768-t6l32 767-ig O-tól 4294967 295-ig -2147483 648-t612147 483647-ig (16) :-32768 - tóI32767 - ig; (32) :-2147483 6 4 8 - tól 2147483 647 - ig (16) : O- tó165 535 - ig; (32) : Q-tól 4 294 967295-ig (16) : 0 - tó165 535 - ig; (32) : Q- tól 4 29 4 9672 9 5 - ig 256 karak ter 65535 karakter Tr u e va gy False 1, 2*1 0·>1 tó13,4"10 " ig 2, 2 *10 -"'- tól 1, 8 * 10'''- i g 3 , 4 *10 ·"" -t6l l, l *10"" -ig

bájtos bájtos bájtos bájtos bájtos

4 bájtos 4 bájtos l bájtos 2 bájtos 1 bá j tos 4 b ájtoe 8 b ájtoe 10 bájtos

(A;; )

, Csak a C++ nyelvnek része, Azok a kulcsszavak, amelyek után zárójel szerepel, a zárójelben található operátor szinonimái.

Adattípusok a C+ + nyelvben bájtos bájtos bájtos bájtos bájtoe

(A)

TARTALOMJEGYZÉK I. rész

Bevezetés a C+ + programozási nyelvbe

l. óra

Kezdő

lépések

E!őkészülctck a programozáshoz ....... . A C++ nyelvjárásai (C++, ANSI C++, ISO C++ és a Windows) A fordító telepítése és beállítása Telepítés a CD-r61 . , ................ . A Borland C++BuilderX fordító beállítása ...... .

Fordít.'Ís a Borland C++BuilderX-szel

A fordítóprog ram és a szövegszerkesztő

Fordítás és linkelés Fordítás az integrált fejlesztői környezetben

linkelés (ősszeszerkeszl(:s) A fejlesztési ciklus. , .. HELLO.CPP -

Az els6 C++ programunk

Fordítási hibák ...... . Kérdések és válaszok

Gyakorlatok

Kvíz Feladalok Válaszok a kvízkérdésekre .

2. óra Mitő!

· 3 .4

.5 . ..... 6 · .. 6 ..... 8

..... 9 ......... 10

.10 .......... . .......... 11 . ..... II

· 13

15 16 16 17 17 17

Egy C++ program részei

lehet jó választás a C++ nye lv. · . 19 Procedurális, strukturált és objektum-központú programfejlesztés . · 21 A C++ rwelv és az objekmm-központú programozás . 22 Beágyazás (encapsulation) . . . . . . . . . . . . . . . . . . . .. . ......... .. .... 23 Öröklődés és újrahasznosítás .................... . . .... 2.~ Többalakúság (polimorfizmus) .... . .. . . ..• . . . .. · . 24 Egy egyszeru program részei .......... . · . 24 Az #indudc utasítás viz.vényekre vonatkozó mutatók . . . . . . . . . . . . . . . . . . . . . .. 394 Tagfüggvényekre vonatkozó mutatókhól álló tömbök ....... . ..... 397 Kérdések és válaszok .. ............... . ........ 400 Gyakorlatok . . . . . . . . . . . . . . . . . . . . . . . . . . . . . • . . . . .. . .. 400 Kvíz. . . . . . . . . . . ....... . ........•............ . ......... 400 Feladatok ....... ... ... ..•.. .•.. . . •... . ...... 401 Válaszok a kvízkérdésekre . . ..................... . ......... 401

21. óra

Az előfeldolgozó

Az előreldolgozó és a fordító ......... •.. .......... . ................ 403 . . . . . . . . . . . . . . . . . • . . . . . . . . . . . . . . 404 .......................... . .... 404 A . define használata álland6kkal kapcsolatban . . . . . . . . . . . • . . . . . . .. 405 A -*define és az '#ifdcf használata vizsgálatok végzésére. . ........ 405 Az #else direktíva .............................. ..... .... 406 Beszúrás és annak vezérlése .. . . . . . . . . . ........... • .......... 407 Szimbólumok definiálása a parancssorban .......... . .... . .......... 109 A meghat~irozotts{lg rnegszüntetésc .. . . . ................ 409 Feltételes fordítás ......................... . ... . .... . . . ........ 409 Makróként megvalósított fü~>vényck ........ . . . ........ 410 Mi ez a rengeteg zárójel? ..... .•.......... 41 1 Makrók, függvények, sablonok .. . .......... 413 . ............... 414 Karakterláncok kezelése .......... . A szöveggé ala kító (slringizing) operátor. . . . . . .• . ..• . . . . . . . . .414 Az összefúző operátor. . . . . . . . . . . . . . . . . . . . . . . . ... 414 Előre meghalározoa makrók . . . . .. . . . . . . . .. . . . . . .. . .. . .. 415 Az aS5ertO beépített makró . . . . . . .. .......•.... . ..... . .116 Nyomkövetés az assertO makr6 segítségével .418 A makrók mellékhatásai ....... . . ................ 418 Osztályinvariánsok ............ . . ... 420 Köztes értékek kiíratása ...... . . ... ... 425 Nyomkövetési szintek .. ... .... .. ... •. •... . . .. •. . . . . . ... 426 Kérdések és válaszok ...................... .432 Fe1adatok . .... .. ......... ... . . ..... . ...... . .... . . 4.l3 A köztes állapot mentése . A #de nne direktíva használata.

I

Tanuljuk meg a C+ + programozási nyelvet 24 6ra alatt xiii Kvíz , ...... . Gyakorlatok . , ...... . Válaszok a kvízkérdésekre ..

22. óra

........ 433 .. ... .... ..433 . ............ ........... . ........ 434

Objektum-orientált elemzés és tervezés

A fejlesztési ciklus . . . . . . . . . . . ........ , . , 435 E~,')' riaszt6rendszer szimulációja ... ..... . ............ , . . . . , 436 Konce[Ki6lelV ..........• ... •... .. •..• . .. ........ 437 Elemzés és az igények felmérése ........ • ......•..... . ........... 437 Magas és alacsony szinnl teJVezés ....... ••.• .... .. ... •. . .•.. • .... 438 Egyéb objektumok . . . . . . . . . . . . . .•. .. ..•... . . .. 439 Milyen osztály.link lesznek? . . . . . . . . . ............... 4,,9 Hogyan jelezzük a ri:lsztásokat? ........•. , . 440 Eseményhurkok ............ . 441 PostMaster: egyesettanulmány . . . . . . . . . . . .... . . • ' , 443 Mérj kétszer, vágj eb'Yszer . ......... .. ... .. ... .•. .. , ... 444 Oszd meg és uralkodj. . ... ... .. . ..•..•.. , ... 444 Üzenetform;'itum ................. . ........ . , .. , ...... 445 Az osztályok kezdeti telVC ....... . .•...... .. . . , ...... 446 Egy vagy több kiindulópontú hier'dfchia .. . ...•..... . .......... 447 Interfészek tervezése .................. . . . ... ...• , .•. . . ....... 449 Prototípus létrehoz.1S:l ................. ... ... ..•.. . .. 450 A 8O/80-as szabály .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . • . . . . . . . . . . 451 A PostMasrerMessagc os;t.t{ily tervezése ......... . . 452 Az alkahnazásfejle.~;t.tGi interfész. . ..... . ..... . , . .. , .... 452 Progmmozás nagy csoportokban ......... , .... , . • . . . . . . ... 454 A tervezési folyamauaJ kapcsolatos szempontok. . . . . . . • . . . . . . ....... 454 TelVezési döntések. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .... 455 Mikor hozzunk döntéseket? ..... . . . . . . . . . . . . . . . • . . . . . . . 455 . . 456 Munka a vezé rl őprogramokkal . . . . . . . . . . . • . . . • . . • . . . . . • . . . . Kérdések és válaszok .... . •......•..... • .. , . . . 463 Gyakorlatok. ........ . . . . . . . . . . . . . . •. . . . . ..... 463 Kvíz .. . .... , . . . . . . . . . . . . ...•.. , . . . .. ...... 463 Feladatok . . . .. ........ ... .. ..•.. ....... 464 Válaszok a kvízkérdésekre ..... ....• . .. .. . .. , . . . ....... 464

23. óra

Sablonok

Mik azok a sablonok? ........ . . . .. . ... .. .. . .. 465 A sablon példányosítása ....... . ... .. . • ' . . .. . ..... , 466 A sablon definíciója . . . . . . . . . . . . .. . ...•... , . . ........ , 466 .......... . ..... .. . • ' . . . . . . . , 474 Sablontípus használata A szabványos sablonkönyvtár .......... ... ..•. , 480

xiv ITanuljuk meg a C++ programozási nyelvet 24 6ra alatt Kérdések és vála.o;zok

Gyakorlatok ..... . Kvíz . . ...... ........ .

Feladatok Válaszok a kvízkérdésekre

24. óra

.... . .... .. ......... . 481 .. .. .. .. .. .. .. 481 .. .. 481 ..... . . ... 482 ..... " ..... ".482

Kivételek, hibakezelés és néhány tanács

Programhibák, tévesztések, k6dmegromlás . . . . . . . . . . . . . . . . . . . ... 483 Váratlan események kezelése ... ... .. ..•.... .. ... .. . . 485 Kivételek . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . • . . . . • . . . . . 485 Hogyan val6sitsuk meg a kivélelkezelést? . . . . . . • . . . . . 486 ..... 491 A try és catch blokkok használata A kivételek elkapása ................ . . . . . . . . . . . . . . . .. . .. 491 Több catch megadása. . . . . . . . . . . . . . 492 Hivatkozás elkapása - többrétúség a kivélelkezelésben ....•. . . •.... .. 492 Hogyan írjunk professzionális minőségű programo kat? . . . 496 Zár6jelek ......................... . . .• . . .•...... 497 Hosszú sorok . . ........ . . .. .. . . • .......... 498 A switch utasítások. . . . . . . . . . . . . •. . .. . . . . •.... . . 498 A program szövege ................. .. 498 Azonosít6nevek . . . . . . . . . . . . . . . . .. . ....• . .. .. . . . . •...... 499 A nevek betO"zése és a nagybetuk kérdése . . . . . . . . . . . . . . . . 499 Megjegyzések ... .. ... .... ..•...•. . 500 Hozzáférés ....... ................ . 501 Osztálydefiníd6k .......... .•.. ... ... ... . 501 Beemelend6 állomá nyok .. ..• .. . .. •.... . ... • .. . ... . . •. ...... 501 assenO . . . . . . . . . . . . . . .................... . . 502 const ... . .. . ... . ........ . . . . . . . . . .. . . . • . .. . . . 502 További források . . . . . . . . . . . ... ... ... .. ... .... .. .. . .. . . . 502 Hol kapunk segítséget és tanácsokat . . . . . . . • . . . . . • . . . . . . .. 502 Ajánlott olvasmányok ....... ... ... .•. ... . .... . 503 Kérdések és válaszok ....... . . . . . . 504 Gyakorlatok. . ........ 504 Kvíz. . . . ..•... . . . ..... 504 Fe1adatok ... ... ... ... ..•.. . . ....... 504 Válaszok a kvízkérdésekre . ... ... ... ...•. ....•. . . .. 504

VII. rész A függelék B függe lék

Tárgymutató .

Függelékek A bináris és a hexadecimális számrendszerek ..... . .. . ...... 507 Gyakran használt kifejezések. . . 519

531

A SZERZŐKRŐl Jesse Liberty számos szoflverfejlesztéssel kapcsolatos könyvet írt már, amelyek között akad néhány kiugróan népszerű is. Ez utóbbiak elsősorban a CH nyelvvel illetve a .~TI technológiával kapcsolatosak. 6 a vezet6je a Ubeny Associates [nc. nevű cégnek, amely egyedi programok fejlesztésével , tanácsadással és oktalással foglalkozik. David B Horvath eCCp)

vezető

tanácsadó Philadelphiában, Pennsylvaniában éL Több

mint 15 éve dolgozik az informatikában illetve

részmunkaidőS

egyetemi tanár néhány

helyi ilIerve távoktatással m(íköd6 egyetemen. Az áilala oktatott tá rgY'd.k el sősorban a C++ nyelvvel, a Unix/Linux operációs rendszerrel, valamint adatbázisokklll kapcsolatosak. Diplomáját szervezeti dinamikából szerezte a University of Pennsylvanián 1998ban. Több nemzetközi szemináriumot és szakmai összejövetelt vezetett már SZgy dedikált példányt, de ellltíz6doll a projekt. - David B. HOIVa/h

Köszönetnyilvánftás Minden könyv kivál6 alkalmal teremt arm, hogy köszönetet mondjunk benne azoknak, akik nélkül garantáltan nem jÖll volna létre. Esetünkben a Staccy, Robin és Rachel Liberty állnak az élen. Ezen kívül szeretnék köszönetet mondani mindazoknak, akik a különböző kiadókSams, Que, O'Reilly, \'('rox - munkatársaiként segítenek abban, hogy eddigi ffitlveim megjelenhessenek. A Sa ms Kiadó szerkesztői valamennyien kiváló munkál végeztek, ám külön szeretném közülük kiemelni Carol Ackermant, Chrisly Fr..mklint és Pau l Striclandel. Szintén hálával ta!lozom Rieh Halpertnek. Végezetül szeretném megköszönni Mrs. Ka1is munkáját, aki 1965-ben, hatodik oszt{llyos koromban megtanítolIa nekem, hogyan kelJ keHes számrcndslerbcn összeadni és kivonni, miközben sem 6, sem mi nem tudtuk, hogy ez pontosan mire is jó. -Jesse liben)'

Mindazok mellett, akiknek Jesse az imént köszönetet mondoLL valójában még sokan lehetnek II Samsnél, akiket kifclejtcttlink. Tőlük cz úton is elnézést szeretnék kérni. Jómagam Songlin Qillval és Lorella Yatcs-Slel dolgoztmn ezen ;1 projekten. Ez a könyv természetesen nem jöhetett volna létre a csa!{Ic.!orn, killönösképpen pedig feleségem Mary támogatása és megértése nélkül. Sajnos a könyvír.'is már csak ilyen. Az embernek leginkább esténként meg hétvégén van ideje és hangulata az alkotáshoz, amikor a csa láddal kellene lennie. Ilyenkor jön aztán a ~bocs de most nem tudok velelek menni, mert a könyvön kell dolgoznom" szöveg. -/)cwid B. Horoath

I

Tanuljuk meg a C++ programozási nyelvet 24 óra alatt xvii

Kfváncsiak vagyunk az Ön véleményére! Mint a könyv olvasója, Ön, kedves olvasó a mi legfőbh kritikusunk. Éppen azért nagyr.! értékeljük az Ön véleményét. Tudni .szeretnénk, ha valamit jól csináltunk, és persze a7.t is, Ita nem. Tudni szeretnénk, milyen más teriilctekr61 olvasna szívesen könyvekct ebben a sorozatban, és termésZdesen örömmel fogadunk minden egyéb megjegyzé.

5)

&&

(y :> 5

II z > 5)

)

A korábbi éltékeket behelycltesítve HAMIS lesz a feltétel, hiszen x nem nagyobb 5-nél, így az ÉS nem lehet IGAZ. Az ÉS-nél mindkét oldalnak igaznak kell lennie. Hiába szeretünk egy ételt, ha nem jó az íze, nem esszük meg.

Apropó

Csoportosflás zár6jelezéssel

Érdemes plusz zár6jelekkel csoportositani a kifejezéseket. Ne feledjük, a cél egy olyan program létrehozása, amely működik , könnyü olvasni és átlátni. Bővebben

az igazság természetéről

C++-ban a O reprezentálja a hamis értéket, minden más pedig igaz logikai értéknek felei meg. Számos C++ programozó ki is használja ezt az i t-es szerkezeteiben, Íme erre egy ~szép" példa: II ha x igaz (nem nulla)

i f (x)

x

O;

=:

EZl tehát valahogy úgy ken olvasni, hogy "ha x értéke nem nulla, akkor állítsuk nullá!"'",", Itl persle kicsit csaltunk, és valójába a következől al:lkot kellett volna használnunk: i f (x ! = O) x =: O;

II ha x nem nulla

Igazából mindkét megoldás helyes, de az utóbbi talán könnyebben átláthatÓ, Érdemes inkább logikai ki€=nékel€=sre használni a CH ezen tulajdonságát, semmint egy változó nem nulla én€=k€=t ellenőrizni vele, Az alábbi két sor jelentése szintén azonos: if if

( !x ) (x

=:=:

O)

II ha x hamis (nulla) II ha x nulla

A második utasítást ezzel együll va lamivel könnyebb megérteni és hiszen sokkal kifejezőbb .

7s l l. rész • Bevezetés a C+ + programomsi nyelvbe

Kérdések és válaszok Kérdés: Mié,-t haszlláljakfe!esleges ziú'Óje!ezést, lia úgyis a precendia határozza meg az operátorok kié,tékelésél? Válasz: Noha 3 fordítóprogram természetesen ismeri a precedenciáját és a progmmozó megtal111lhatja azt, megfele16 zárójelezéssel azért sokkal könnyebben tarthat juk karban a programjai nkat Kérdés: Ha a relációs operátorok él1éJ.>e l-et llagy O-át ad, a t6bbi éltéJ.'Cl lIlié/t tekillfji/k igaznak? Vú/asz; Relációs operátorok l-et vagy O-ál adnak vissza, de minden kifejezés ad vissz:! értéket, így akár az if ut:lsításban is ki én(! kelhelő. íme erre egy példa: if (

(x .. fl

...

b) =" 35 )

Ez egy szabályos CH utasítás_ A bels6 zárójelben szere pl ő hozz::'irende1és még akkor is lefut, ha maga a feltéle1viugálat hamis eredményt ad. Kérdés: II tabuláto/; a szóköz és az 1íjsor milyen. hatással V(lIl a p rogral11unkra? Válasz: A tabulátor, a szóköz és az újsor - ezeket nevezzük üres karaktereknek - nem befolyásolják a program múködésél, csupán olvashatóbbá teszik a forrásk6dllnkat. Kérdés; A negatív számok igaz vagy h(,llllis logikaI é/1éket jelentel/ek? Válasz: Minden nem nulla szám - legyen az pOZitív vagy negatív - igaz értékként viselkedik.

Gyakorlatok MOST, hogy már rudunk egyet s mást a kifejezésekr6l és az utasításokr61, válaszoljuk meg a kvízkérdéseket és a !"'Yakorlatok segítségével mélyítsük el a megszerzett tudást.

Kvfl l. Mi a különbség az XH és a HX között? 2. Melyik más nyelvekben gyakori operátor hiányzik a CH -ból? 3. Mi a különbség a 001- és jobbérték között? 4. Mit csinál a modlllo operátor?

4. óra • Kifejezések é, uta'fiá,ok! 17

Feladatok 1. Írjunk egy programot, amely a három tanult módon (a "'3+1, 3+ =1 ét; aH) növeli egy változó értékét. Fordítsuk [e, linkeljük és futtassuk. Más leLt a méretük? Észleltünk a futási sebességben különbséget? 2. Gépel jünk be egy matematikai kifejezést az integrált fejlesztői környezetben. Pozicionáljuk a kurzort a valamelyik matematikai operátorra és nyomjuk meg az Fl billentyűt. Mennyire hasznos a kapott információ? 3. Írjunk egy programot, amiben egyszerre növelji.ik prefix és pOSlftx módon egy

változó értékét egy lépésben (++x++). Lefordul? Van értelme? Mi történik, ha egyszerre használjuk a növelést és a cs6kkentést?

Válaszok a kvfzkérdésekr. 1. Az első ut6tagkénl való (posrfix) növelés. Ekkor e l őbb kiolvassuk emenetként. Fúggvényhívflskor argumcnlumké nt bármely a C++ nyelvben értelmes kifejezést meg.dharunk. Ebbe bcll:tartoznak :t konstansok, a matematikai és logikai kifejezések, illel\-e egy bármely mis függvény ;Utal visszaadott érték is. Tegyük fel például, hogy van eg}' li1ggvényünk, melynek a deklarációja a következőképpen fest: nt MyFunctioll(int thclntegerParam. bool theBoolean) ;

Ezt számos különbö7.6 módon hívhat juk meg, amely le het6sC:gckb61 i l l csupán hármat mutatunk be: _nt

II deklaráljuk az argumentun,ként ha9znál t /I változ6kat : " MyFunction(x,y); II egy int és egy bool változ6t adunk át MyFunction (32, true) ; II két álland6t adunk át ;: " MyFunction(23.9, tOO>5); II a:;o: els6 érték 32, a másik igaz :;0: ,

X

,.

3 , y " 5:

\z utolsó hívás kirnenelelél lekinlve leljes O && smull < Mi\XSMlILL)

if

(small 1; 5000 == O) II 5000 soronként kiír egy pOttyOt std : : cout « • . • .

23 : 24 : 25 : 26 : 21 :

'khIebb: • «

small+ +;

large-:2 ;

110 II. rész· Bevezetés a C+ + programozási nyelvbe 29 : 30: 31 :

std: :cout « "\nKisebb : " « small « " Nagyobb: " « large « std: : endl; return O;

32 :

írjon be egy kisebb számot: 2 írjon be egy nagyobb számot: 100000 Kioebb : 2 ..... Kisebb:33335 Nagyobb : 33334

• EZ;J program egy egyszen1 játék. Beírand6 egy kisebb és egy nagyobb szám. A kisebb egyesével növekszik, a nagyobb kettesével csökken. A játék célja annak kitalá lása, hogy hol találkoznak. A 10-13. sorban írhatjuk be:il számokat. A 'IH. sor egy olyan ciklusfehételt tal'talmn, mcly esak az alábbi három feltéte l egyidejű teljesülése eserén engedi meg a ciklusmag kfutásál: • a sma11 nem n:!gyobb a large-nál • a large pozitív • a sma11 kisebb MAXSMALL-n{11 (ami a kis egészek

m~rethal1lrd)

A 21. sorban II small SOQO-es maradékát sz.1mítja ki :il program. Ez csak akkor nulla, ha a small egész számú többszöröse 5000-nek. Ne feledjük , hogy ez:! viz..GetAge ( )

d elete Frisky ; return O;

44 :

Frisky 2 éves Frisky 5 é ves

A Simp1eCat osztálynak két tagváltoz6ja van, mindkettő egészeket címez. A konstruk-

tor (a 20-24. sorban) inicializálja ezeket a mutat6kat úgy, hogy a dinamikus mem6 riaterületre mutassanak, és a változ6khoz hozzá rendeli a megadou kezd6érrékekcl.

188 1111. rész • Mem6riakezelés A destnIktor (a 26-30. sorban) felszabadítja a lefoglalt memóriaterOletekcl. Minthogy ez a destruktor, nincs értelme nullázni a mutatókat, hiszen ezek a későbbiekben már nem lesznek elérhetőek. Ez egy bizlonságosan vállalható kivétel azon szabály alól, hogy a törö lt mutatókhoz érdemes null értéket rendelni ; persze nem okoz gondor a szabály követése se m.

A hívó függvény - jelen esetben a main () - mit sem rud arról , hogy az itsll.ge és az itsWeight a dinamikus memóriára irányuló mutatók. Egyszenle n meghívja a GetAge () és a GetWeighL () függvényeket, mint eddig is; a mem6 riake zelés részlet.ei el vannak rejtve az osztály megvalósításában - ahogy annak lennie kell . Amikor F'risky törlődik a 42. sorban, egyből meghív6dik a destruktOJ:l. A deSlmklor minden adattag-mutatót töröl. Ha ezek kimutatnak egyéb objektumokra is, melyek a felIl:lszn{116 {tltal definiált oszt51yok példányai, akkor azok destruklorai is meghfv6dnak. Ezen a p6kl{tn jólláthat6, hogy miért érdemes saját destruktort írni (a fordít6 progr.:tn1 állal fclaj{tnlotl alapértelmezés helyett). Alapértelmezetten a 28. és 29. sorban láthat6 törl(:sek n~m tört(:nnének meg; a programozómik kell ezeket ll1itsLcngth = length ; int GetLength() const ( return this->itsLength; void SetWidth(int width) ( itsWidth = widt h ; ) int GetWidth() const { return itswidth ; } private: int itsLength; int itsWidth ; ); Rectang1e : : Rectang1e ()

( i t s Wid th = 5 ; itsLength;; 10 ;

Rectangle : : -Rectang1e() () int main() ( Ractangle t haRect ; cout « "Tógla 1apom « • láb cout « "Téglalapom « " láb

theRect . $et Length(20) ; theRect . SctWidth(lO); cout « "Tégla!apom • « thcRect . GetLcngth(l « " láb hosszú . " « endl ; cout « "Téglal a pom " « t h cRect . GetWidth() « • láb széles . " « e ndl ;

42 :

43: 44 :

" « theRect . GetLength() hosszú ." « end1; • « theRect . GetWidth() széles . " « endl;

return O,

Téglalapom Tégl alapom Téglalapom Tégl alapom

10 láb hosszú . 5 láb széles . 20 láb hosszú . 10 láb széle s .

190 III. rész • Mem6riakezelés

-

A SetLength () és GetLength() hozzáfér6 fü&!,,,,ények kifejezetten a this mutatót használják a Rectangle objektum tagváltozóinak elérésére, ellentétben a SetWidth (J és GetWidth () hozzáfér6 függvényekkel , melyek másként dolgoznak. Nincs különbség a viselked ésükben, csak abban, hogy a this nélküli metódus kódja talán olvasl1at6bb. Tudta hogy...?

Mire is val6 tehát ez a this mUlat6?

Ha csak ennyi értelme lenne a this használatának, nem lett volna érdemes megemlfteni. A this mutató hordozza az adott objektum memóriacfmét - ez igen hatékony eszköz lehet! A könyv egy késő b bi (14.) fejezetében láthatjuk majd ennek a gyakorlati felhasználását az operátorok túlterhelésénél. Egye l ő re elég annyi is, ha tudunk a this mutató l é tezéséről, és arról. hogy magára a szóban forgó ob jektumra mutat. Semmi dolgunk vele, nem kell létrehoznunk vagy törölnünk - ezt elvégzi helyettünk a fordítóprogram.

Gazdátlan vagy "lógó" mutatók A programhibák egyik forrása a gazdátlan mutatókb61ered, melyeket nehéz és kellemetlen felkutami. Gazdátlan mutató akkor keletkezik, amikor törjünk egy mutat6t (deleteleO - ily m6clon felszabadít juk a hivatkozott memóriaterillelet - és kés6bb anélkül kisércljük meg újra használni ezt a muratót, hogy bármit is hozL1rendeltünk volna. Olyan ez, mintha egy cég elköltözne telephelyér61, és egy ügyfelük a régi sti'imon próbálna telefonálni nekik. Lehet, hogy semmi különös nem történik - csöng egy telefon egy elhagyott irodaházban. De az is lehet, hogy ezt a számot már valaki más használja, aki esetleg v~gigdoJgozta az éjszakát, és ez a telefoncsörgés ébreszti legszebb álmából. Röviden: ne használjunk olyan mutatókat, melyeket e16z6leg töröltOnk. A mulató továbbra is a mem6ria egy bizonyos területére mutat, de ;1 fordítóprogramnak joga van oda más adatokat tenni, így ennek a mtJtatónak a használata II progl"J.m összeomJásához vezethet. Ennél is rosszabb, ha a program vígan fut tovább, és a hiba csak néhány perccel kés6bb következik be. Ezt időzített bombának hívják, és nem túl vicces. A bizlonslig kedvéélt érdemes NULL-ra állítani (és ezzel lefegyverezni) a használaton kívül helyezett mutat6kat.

Apropó

K6bor mutat6k

Az. gazdátlan mutatókat kóbor vagy lógó mutatóknak is hívják.

10. óra • A mutatók kifinomult használata 191

Konstans mutatók Mutatók esetében a const kulcssz61 ti típus előtt , után, vagy mindkét helyen hat juk. Az alábbi deklarációk mind helyesek:

használ~

const int • pOne ; int • con s t pTwo ; c onst int • const pThree ;

Ezek különooz6 mutatókat eredményeznek. pOne ch'Y konstans egészre mutat. A hivatkozou értéket nem lehet megváltoztarni a mutatón keresztül, azaz nem m űködik az alábbi sor: ' pOnc = 5

Ha eZI kís6reljük meg, hibát ad a forJít6 progmm.

pTwO

konstans mutató egy egészre.

A hivatkoZQII szá m értéke megváltoztathal6, de a p'I'wo nem mutathat sehová máshová.

Ko nsWns mutat6hoz nem lehet más változót rendelni. Azaz nem ~p'rwo

..

működik

a következ{}:

&x

pThree konstans mutató egy konstans egészre. A hivatkozott szám értéke sem válloztatható mcg, és a pThree sem mutathat semmi másra. Húzzu nk egy képzeletbeli függ61eges vonalat :l csillag jobboldal án. Ha a cons t szó a vomtlt61 ba lra esik , akkor az objektum konstans, és ha jobbr-.l, akkor pedig a maga mutató változtathatatlan const int· pl ; II A hi vatko.,;ott egé!lz konstans i nt • const p2; I I p2 ko nsta ns , ne m mu tat hat semmi másra .

Konstans mutatók és konstans tagfüggvénv.k A 7. 6rán tanultunk az osztályok alapjair61. Oli volt szó arrol, hogya const kulcsszót lehet tagfüggvényekre is vonalkOZL1.tn i. l ia egy függvényt konstansként dekladlunk, a fordíl6progr-.un hibajelzésselm3sít viSsza minden kísérletet, amellyel az adon függvény változtatni akama az objekrumon. Ha konstans objcklumra hivatkoz6an deklará lunk egy mutatól, akkor ezt csakis konstam; mctódusokkallehet használni. A 10.5 Lista ezt illusztrálja.

10.5 Usta - const objektumot cimz6 mutatá használata (constptr.cpp) o : !! 10 . 5 Lis ta l : I I ko n s tans objektumot c i mzo mu tat6 ha s.,;ná l ata 2 : 'incl ude 3, 4 , class Rec t angle 5: { 6 : public ,

192 1111. rész • M.móri.koze~s 7: 8: 9: 10 : ll : 12: 13 : 14 : 15 :

16 :

Rectangle() ; -Rectangle() ; void SetLength( int l e ngt h) ( itsLength = leng t h ; int GetLength() const { re t urn itsLength ; } v o id SetWi d th {int wi dt h) l itsWid th - wi dth; i nt Get Widt h() c on s t { retu r n i t s Wid th ; )

private : int itsLength ;

int itsWidth ;

17 : 18 : 19 : 20 : 21 : 22 : 23 : 24 :

25 : 26 :

}; Rectangle: : Rectangle () : itsWidth(S) , itsLength (10) (l

Rcc t angle : : _Rectn ng l e () {}

27 : 2B :

int main()

29 :

30 :

31 : 32 :

Rectang!a* pRect = new Rectanglc; const Rectangle * pConstRect • new Rectangle ; Rectangle • const pConstPtr = new Rectangle ;

33 :

34 : 35 : 36 : 37 : 38 : 39 : 40 : 41 : 42 , 43 : 44 , 45 : 46 : 47 :

48 : 49 : 50 , 5 1: 52 :

std : : cout «

'pRect szélessége : " pRect ->GetWidth()« láb"« std : : endl ; std : : cout « "pCon s t Rect szélessége : « pCo n stRect->Cctwidth() « ' láb' « std , , endl; stó : , cout « ' pCo n stPt r szé l essége , « pConstPtr->CetWi d th () « ' láb ' « std :: endl ;

«

pRect->setWidth(10) : II pConstRect->SetWidth(lO) ; pConstPtr->SetWidth(lO) ; std : : cout «

'pRect szélessége: pRcct->GetWidth()« láb'« std : : endl ; std , , cout « 'pConstRcct szélessége : « pCo n s t Rect->Get Width() « • l á b " « std :: cndl , s td : : cout « 'pCon s tP t r szélessége : « pConstPt r - >Ge LWidth() « • láb' « s td : : endl ; return O; «

pRect sz élessége : 5 láb pConstRec t szélessége : 5 l áb pConstPtr szélessége : 5 l á b pRect szélessége : 10 láb pConstRcc t szélessége , 5 láb pCo n s t Pt r s zé l essége : 1 0 l áb

10, óra • A mutatók

A 4- 18. sorokban deklarálunk egy téglabpot. A 13. sorban a GetWidth () tagfüggvényt konstansként deklaráljuk A 30. sorban cgy mutatóva! hozzuk IéIre a pRect téglalapot. A 31. sorban deklarált pConstRect egy konstans téglalapra hiv:ltkozó mulató. A 32. sorban létrehozott pConstPtr pedig egy téglalapra hivatkozó konstans mulató. 11.34-39. sorok kiírják a három szélesség-értéket. A 41. sorban a pRect segítségévcl álállitjuk az els6 téglalap szélességét 10-fe. A 42. sorban a pConstRect használatával tennénk u~,'yaneZlJ de ez II mUlató egy konstansként felveti téglalapra hivatkozik, melynek é rtéke nem változtatható, és nem hívható meg rá nemkonstans L:tgfüggvény. Ez a sor tch:1t megje,gyzéssé van alakitv:-I, A 32. sorban 3 pConntPtr konstans mutatóként lett lélfehozvGetAge (). A ~ m utat " ( - » operátor jobb, mivel ránézésre is nyilvánvalóan mutatja a programozó szándékát. 4. Gazdátlan mutatóról akkor beszélünk, ha azután kíséreljük meg amemória használatát egy mutató révén , miután már azt a mulatót töröltük. Ilyenkor nem tudhat juk, hogy az adott memóriaterület milyen szerepben áll!

11.

ÓRA

Hivatkozások Ebben az órában a kővetkezókróllesz szó: •

Mik azok a hivatkozások

• Miben különböznek a hivatkozások a mutatóktól • Hogyan lehet hivatkoz.'isokat létrehozni és használni • Milyen korlátai vannak a bivalkozásoknak • Hogyan lehet a függvényeknek értékeket és objeknllnokal átadni és t510k átvenni hivatkozások segítségével

Mi az a hivatkozás (referencia)? Az elmúlt két órán áttekintettük a mutatók használatár; hogy segítségükkel miként lehel a dinamikus memóriában lévő objektumok kal bánni, és hogy hogyan lclu;!( ezekre az objektumokra közvetett módon rámutatni. A hivatkozások, melyről ezen az órán sz6 lesz, a rnutatókhoz hasonlóan hatékony eszköZT adnak a kezünkbe, csak jóval egyszeníbb szintaxissal.

196 1111. rész • Memóriakezelés A hivatkozás egy alternatív név ( alias). A hivatkozást egy másik objektum, a célobjektum nevével lehet inicializálni. Ettől a pillanattól kezdve a hivatkozás úb.'Y viselkedik, mintha maga a célobjektum lenne; bármi , amit a hivatkozással teszünk, megtörténik a célobjektummal is. Ennyi az egész. Néhol úgy emlegeti a hivatkozásokat, mintha azok mutató k le nnének, de ez nem pomos. Bár gyakran tényleg mutatóként valósítják meg 6kel, ez csak a fordítóprogmmok gyártóira tartozik. I'rogmmozóként el kell mdni különíteni a két fogalmat.

mUlatók olyan változók, melyek egy másik objekmm memóriacímét tárolják. A hivatkozások ezzel szemben egy másik objektum névváltozatai.

A

Hivatkozások létrehozása Hivatkozást úgy hozh:nunk létre, hogy megadjuk a

20)

value = 1 ; else

35 :

·pSquarcd = n*n: *pCubed n*n*n:

36:

Valuc '" O;

37 : 38 :

39 :

re t urn Value;

1

20e III. rész • Mem6riakezelés

Enter a number (O-20) : 3 number: 3 square : 9

cubed: 27

A 8. sorban lélrehozzuk a number, squared és a cubed (szá m, négyzete, k6be) egész változókat. A number--nek a felha sználó bemenő adata ad értéket. Ezt a számot, valamint a squared és a cubed címét átadjuk a Factor () függvénynek. A Factor () megvizsgálja az érték szerint áladolt els6 p;mun éterl. Ha ez nagyobb húsznál (v:lgyis a maximumnál, amit ez a függvény még kezeln i ~ llld "), akkor II visszatérési vá ltoz6t (va.lue) egy egyszelű hibajelz6 értékre állítja. rigycljük meg, hogy a Factor () visszatérési értéke vagy ez a hibajelz6 érték, vagy nulla (ami azt jelzi, hogy minden rt..:ndben zajlott). A 38. sorban kerill visszakoldésre a Value ért6kc. A két ténylegesen várt ~v isszatérési érték~, a szá m négyzete és köbe nem a return révén jut vissza a fl5program ba, hanem a fuggvénynek átadott mut..tók révén lehet6vé vált közvetlen C:n6kvá ltoztatással. A 34. és 35. sorban bekerülnek a kiszámított értékek a mutatók álUl! hivatkozott mcm6riacímekre. A 36. sorban a visszatérési énéket (value) sikeres állapotra állíljuk, és a 38. sorban vissz..küldjük. A progmmot továbbfejleszlhetjOk azzal, hogy felvesszük az al ábbi deklar.'lci6t: enum ERROR-VALUE ( SUCCESS, FAILURE): Ezek után már nem O vagy l értéket kellene visszaadnia a t"üggvénynek, hanem SUCCESS-t (sike,t) vagy FAILURE-t (híbtit). Ahogy korábban láthattuk, II fcl sorolásos típus első eleme (SUCCESS) O, második eleme (FAILURE) l értéket vesz föl.

Több visszatérési érték használata hivatkozásokkal Bár a 11 .7 Lista programja működik, könnyebb olvasni és karbantartani, ha mutatók helyett hivatkozásokkal dolgozunk. A 11.8 Lista mutatja az átín programot, amely már hivatkozásokat használ, valamint szebb hibakezelést valÓSít meg az ERR-CODE révén.

". ó.. • Hivatkozások 1209

11.81.is1a - A 11.71.is1a úlnlrúa: _ _ ""'"'" _

... h i t _ a l

(-..withnof.cppl o : /I 11. 8 Lista l ; 1/ FOggvények felruháloása 2 : II tObbszOrös visszatérési értékkel hivatko zások révén

3:

•• 5:

tincludc enum ERR-CODE ( SUCCESS, ERROR ) 1

6.

7: ,.

ERR-CODE Factor(int , int&, int&) ;

9:

int m",in() {

10 :

int number , squared , cubed : ERR-COOE res ult :

ll : 12 : 13 ; 14 :

std : : cout «

15 : 16 :

std : : cin »

17 : 18 ,

re!lult • Factor(number , squared , cubed) ;

19 : 20 : 21 : 22 : 23 : 24 :

i f (reGult

25 :

else

26 : 27 :

return O,

,

"Enter a number (O - 20) :

number ;

..

SUCCE$S)

std : : cout «

"number :

std : : cout «

·square : ·cubed:

Btd : : cout

«

std :: cout«

.

« «

number « • \n "; squared « • \n" ;

«

cubed

«

• \n';

"Error encountered!!\n" ;

28 :

29 : 30 :

3L

,

ERR.....CODE Factor (int n, int &rSquared, int &rCubed)

32 : 33 : 34 : 35 :

36 : 37 : 38 :

i f (n > 20) re t ur n ERROR; else

,

r Squared :: n *n ; r Cubed '" n"n*n ; return SUCCESS ;

39 : 40 :

Enter a number (O-20) : ] nwnbe r : ]

square : 9 cubed : 21

II simple error code

210 1111. rész • Mem6riakeze~s

A 11.8 ü sta megegyezik a 11.7 Listával , kél kivételle1. Az ERR-CODE felsorolásos típus átlálhat6bbá teszi a hiba jele ntéseke t (33. és 38. sor) , valamint a 19. sor hibakezelésél.

A jelentősebb vá ltozás azonban abban áll, hogya Factor () függvényt most úgy deklaráltuk, hogy mutatók helyett hivatkozásokal vár a squared és a cubed helyére. A pamméterek kezelése íh'Y sokkal egyszerűbb és érthetőbb.

Kérdések és válaszok Kérdés: Miért IJtlsználjl/llk hivatkozásoka" Ita CI

cl

mutat6k mindarnl képesek, amire

hfvatl.lozások?

Válasz: A hivatkozásokat könnyebb használni és megérteni. A címfeloldás rejtenen tör-

ténik, nincs szükség isméte lt címfeloldó operáto rokra . Kérdés: Aná,., hasz/lálj/.m k akkor /IIuUllókat, ha egyszerl1bbek CI lIiv(l lkoz!üok?

Válasz: A hivatkoz{!sokat nem lehet nu llázni, sem pedig újra felhasználni. A mutatók rugalmasabbak, de valamivel nehezebb a használatuk.

Gyakorlatok Most, hogy megismerkedfÜnk a hivatkozások használatával , válaszoljunk meg néhány kérdést és végezzünk el néhány feladatO[ Uldásunk e l lenőrzésére!

Kvfz 1. Mi az a hivatkozás? 2. Milyen operátorral hozunk létre egy hivatkozást? 3. Mi egy hiv"koz's mem6"ocime' 4. Mi a függvények alapértelmezett paraméterátadási módszere a C++-ban? Milyen módon lehet ennek korlátait átlépni?

Feladatok 1. Egyesítse a passbyptr. cpp és a passbyref. cpp (11.5 és 11 .6 Lista) programjaiban használt módszereket úgy, hogy az egyik é rtékel mutató, a másikat hivatkozás segítségével adja át a swap () függvénynek! Ez jól mutatja, hogy e kél módszer teljesen átjá rható .

l1.6ra • HivatkOLls.kl 211 2. Módosírsa úgy a returnwithptr. cpp programot (11.7 Lista), hogy mutatók helyeu hivatkozásokat használjon! 3. Bontsa három részre a returnwithptr. cpp programot Cl 1.7 Lista) oly módon, hogy HZ eredeti néven maradjo n meg a főprogram (returnwithptr . cpp), a Factor () függvény megv.d6sítása kerüljön át egy külön fájlba (factor. cpp), és legyen egy fejlécállomány is a Factor {} függvény proTolípusával (fa ctor . hpp). Vegye fel a factor. cpp-t a projektállomá nyok közé, (:$ fordítsa le a progmmot! Ez azt szemlélteti, hogy hogyan lehet megoszta ni a fü ggvény- és osztálykönyvtárakat. A függvény lefordítható és a gépi nyelv{[ progmmkód a fejlécállománnyal (bclUle a ruggvényprototípussaD együtt közzélehe16 a termelékenység javítására.

Válaszok a kvfzkérdésekre 1. A hivatkozás valamely váltOl6 vagy obje ktum szinonimája, névvá ltolat.1, 2. Al ~és" jel (&) használatávallehec hivatkozást deklarálni. A hiv:ltkozásokat inidalizálni kell a deklaráláskor. Nem lehet nu ll hivatkozásu l,k, csak le nulIázott mutat6nk. 3. A hivatkozás címe annak a változónak vagy objektumnak a címe, amelyre utal. Ha :1 . cím(/' operátorl alkalmazzuk egy hivatkozásra, akkor (a mutat6kkal ellentétben) úgy tűnik , hogy semmi helyet sem foglal el a memóriában. 4, Az é rté k szerinti pamméter:'uadás. Ilyenko r az átadott vállOZó másolatával dolgozik a függvény, így nem lehet felülírni az átadott változ61. Ezen kétféle m6don le het felülemelkedni: egyrészt a mutatók használatával, ugyanis ilyenkor az obje ktum címe kerül átadásra. Másrészt hivatkozások átadásával, hiszen ezzel az eredeti változó névvá llozatál kapja meg a filggvél1y.

12.

ÓRA

A hivatkozásokról és mutatókról - mélyebben Ebben az 6rában a következőkrőllesz sz6: • • • •

llogyan tehetjük hatékonyabbá programjainkat cím szerinti paramétecitadással Mikor érdemes hivatkozásokat használni, és mikor mutatókat Hogyan Icgyiln k úrrá a mcmóriagondokon a mutatók ha.~ználata közben Hogyan kerüljük el a hivatkozásokka l kapcsolatos csapdákat

Hatékonyabb a cfm szerinti paraméterátadás Az érték szerinti paramétcrát:tdáskor másolat készül az objeklumr61. Ha a függvény visszatérési értéke egy objektum , akkor megint egy újabb másolat keletkezik. Nagyobb mércrú, felhasználó általlétrehozou objekrumok esetén ezeknek a másolások a száITÚtásigényc már igen számottevő is lehel. A szükségesnél több memóriát használ a program, és végs6 soron sokkal !assabban fut.

214 1111. rész • Memóriak.,.lé. Egy, a felhasználó által definiált objektum mérete a veremben az egyes tagváltozók méretének összege. Ezen tagvállozók akár nagy objektumok is lehetnek. Egy efféle gigantikus struktúra átadása (azaz a verembe másolása) igen sokba kerülhet memória és futási idő vonatkozásában. Másféle költségek is fellépnek ilyenkor. Az oszt{llyok pélclányosításakor készül róluk t'b'Y ideiglenes másolat; ilyenkor a fordít6progmm meghív egy speciális konSlnlktOI1: a másoló konstruktort. A 13. órán, a Ixmyolulwbb függvényeknél megtanul juk, hogy hO!''Yan működnek ezek a másoló konstnlktorok, és hogy hogyan készíthetünk magunknak ilyeneket; most azonban elég annyit tudnunk, hogy egy objektum ideiglenes másolatának a verembe másolásakor meghív6GetAge()I std : :cout « ' years old \n' ; II theCat->SetAge(8); const! return thecat;

Making a cat ... Simple Cat Constructor ... Fris ky i s 1 years o l d Fris ky i s 5 years o l d Calling Fun ct i onTwo ... Function Two . Returni n g . Fris ky i s now 5 years old Frisky is 5 years old Simple Cat Destructor . .

12. 6ra' A hivatkozásokr61 és mutatókr61 - mély.bb.n 1219

A SirnpleCat számára két hozzáfér6 függvényt deklaráltunk: a GetAge () -el a 11. sorban, amely konstans függvény , és a SetAge () -et a 12. sorban, amely nem az. Van egy saját tagváltozója is, a 15. sorban deklarált egész itsAge. A konstruktor, a másoló konstn Jktor és a destrukwf úgy lett megírva, hogy kiírja a saját nyomje\z6 üzenetél. A másoló konstruktor azonban sohasem kerül meghívásn:I; prog-

ramunkban ugyanis csak dm szerinti paraméterátadás tönlmik, és ehhez nincs szükség másolat készítésére. A 4Q. sorban létrejön egy macska; az alapértelmezeu életkorát ki is nyomtat ja a 41-42. sor. A 44 . sorban a SetAge () segítségével átá!1íljuk a korát (it~Age) 5-re, és az en..>(lmf:nyt megjelenítjük a 45-46. sorban. A FunctionOne ( ) -l nem haszn:íljuk ebben a programban, csak a FunctionTwo () -t, amelyet egy kicsit átírtunkj a 34. és 35. sorban láthatjuk visszatérési értékét és átadand6 paraméter6t: mindkett6 egy konstans objektumra utal6 konstans mutató.

Minthogy az átadandó pamméter és a visszatérési érték is cím szerint kerUl ,ítad:'isl"""d , nem készülnek m:'isolatok, és nem hív6tlik meg a másoló konstmktor. A FunctionTwO () -beli mutató azonban konstans, így nC:!m lehet bel6le meghívni a nemkonsta ns SetAge () -et. Ha az ezt megkísérl6 61. sort kivesszük a megjegyzésb61, nem fordul Ic a program. Érdemes megIIgyeini, hogy a main () f6programban létrehozott Frisky objektum nem konst:ms, így például átáJlítható a kora, meghívhat6 rá a Setll.ge () . Ennek a nemkonstans Frisky objektumnak a eimét kapja meg a FunctionTwo (), és mivel ez úgy lett dC:!klarálva, hogy konstansra hivatkozó ll1utat6ra számít, az objektumot konstansként fogja kezelni!

Hivatkozások, mint a mutatók kényelmes altematfvái A 12.2 Lista megoldja a felesleges másolás (és ezzel a másoló konstmktor és destruktor indokolatlan meghívásá nak) problémáját. Konstans objektumra mutató konstans mutat6t használ, így nem kell tartanunk att61, hogya függvény jogosulatlanul megválloztatja a paraméterként átadott objektumo{ka)t. A módszer azonban még mindig nem tú l elegá ns, mivel mégiscsak mutatókat kell átadnunk a függvénynek. Mivel azt is tudjuk, hogy az átadandó paraméterek nem lesznek null értékűek , könnyebb lenne az élet, ha mutatók helyett hivatkozásoka t adhatnánk át. A 12.3 Lista ennek szellemében korrigálja a 12.2 Listát.

220 1111. rész· Mem6riakezelés

o:

II 12.3 Lista 1: II Objektum hivat ko zásának az átadása 2: ftinclude 3, 4: class SimpleCat 5: { 6 : public : 7: SjmpleCat() ; 8: Simp leCa t (SimpleCat&) ; 9: -simp1eCat() ;

10 : int GetAge () co n st void SetAgc( int age)

ll: 12 :

retur n itsAge : } { i tsAge • age; )

13 : 14 :

15 : 16 :

private : int itsAge:

);

17 : 18 :

simpleCat : :Simp1eCat()

19 :

(

7.0 : 21 : 22:

std : : cout « itsAge = 1 ;

'Simple Cat Constructor ... \1'1 ';

23: 24 :

SimpleCat: :Simplecat(Simp1eCat&)

25 : 26 : 27 : 28 : 29 : 30 :

(

31 :

std: : cout«

"Simple Cat Copy Constructor ... \n";

Simp1eCat : : -Simplecat () { std : : cout « 'Simple Cat Destructoc .. . \n' ;

32 : 33 : 34 : 35 : 36 :

37 : 38 : 39 : 40: 41 : 42 : 43 : 44: 45: 46 :

const SimpleCat & Func tion'l'wo (const SimpleCat & theCat) ; int main()

( std :: cout« 'Making a cat ... \ n '; Simpl eCa t Fr i s ky; std : : cout « "Frisky is ' « Frisky . CetAge() « ' years 01d\n' ; int age", 5; Frjsky.SetAgc{age) ; std : : cout « 'Frisky is ' « Fri sky . GetAge() « ' years 01d\n' ;

47 :

48: 49 : 50 :

std : : cout « 'Ca11ing FunctionTwo ... \n" ; FunctionTwo(Frisky) ; std : : cout « "Frisky is " « Frisky.Geti\ge()

12. 6ra • A hi_omokról és mutat6król- mé~ebb,n 1221 • years old\n" ;

«

51: 52 :

return O;

53 : 54 : 55 : 56 : 57 : 5B : 59 : 60 : 61 : 62 :

1/ functio nTwo.

const SimpleCilt

konstansra utal6 hivatkozást kap és ad vissza FunctionTwo (const SimpleCat (. theCat l

&

(

std :: cout«

' Punction Two. Returning ... \n' ;

std : : cou t «

'Frisky is now ' « « • years old \n "; /1 thecat . SetAge(B); const! return theCat;

theCa t . GetAgc()

63 :

Making él ca t . .. Simple eat constructor ...

Frisky lS 1 yoars o ld Frisky is 5 years old Calling FunctionTwo FunctionTwo . Returning ... Frisk.y is now 5 years old

frisky is

~

years old

simpl e eat Destructor ...

A kimenet megegyezik a 12.2 Listáéval. Az egyetlen emJílt!sre mélt6 külónbség az,

hogy most a FunctionTwo () függvény konsta ns objektumra utaló hiv,ltkoz{lsl vár és ad vissza. Ezen II példán is láthatj\lk, hogy hivlltkoz.'isokkal könnyebb dolgozni, mint mutat6kkal ; a ko nstansok által elérhct6 nyereség, hatékonyság és hizlonság azonban itt is megval6su1.

Mikor használjunk hivatkozásokat, és mikor mutatókat? A C++ programozók általában sokkal szívesebben használnak hivatkozásokat, mint mutat6kat, mivel ezek átláthat6bbak és hasznáJhat6bbak. A hivatkozásokhoz azonban nem lehet új objektumot hozzárcndeJni. Ha a program futása közben változtatni kell II célobjektumon, kénytelenek vagyunk mutatót használni. A hivatkozás nem lehet null értékű; így, ha van esély arra , hogy acélobjektum nul1áz6dik, akkor sem tudunk hivatkozást használni, csak mutatót. Ha a dinamikus memóriából szeretnénk területet foglalni, akkor is mUlatókra van szükség, ahogy arról az előző órákon már szó volt.

222 1111. rész' Memóriekezelés

Ne adjunk vissza hivatkozást!

megszűnt

objektumra mutató

Ahogya C++ programozók megtanulják a eim szerimi par.lméterátadásl, vérszemet kapnak, és id6nként hajlamosak túlkompenzálni ifjúkori lévedéseikel. Ne lévesszük szem eid!, hogya hivatkozás csupán egy névvá llOZSetAge (2 *i +1) ; 26: Family[i) = pCat ; 27 :

)

28 : 29 : for (1 = O ; i < 500; i+ + ) 30 : std : : cout « "Cat ff' « i +l « " : 31 , « Family[ i]->cctAge() « s td, : end l ; 32 : 33 : for (i = O; i < 500 ; i ++ )

34 : {

15. 6ra • Tömbök 35 : delet e Family [i l ; NULL ; 36 : Family[i ] 37 : ) ~

]8 :

39 , return 0 , 40,

menet Cat fl, Cat c.t

l

'2 : 53 '3 :

Cat M499 : 997 Cat ~500 : 999

A CAT osztályt a 3-15. sorokban deklaráljuk. Ez a form .. amClgy mindenben megegyezik

a 15.3. Listában bemutatott:!!. Ugyanakkor ez alkalommal a 19. sorban talá lható tömb neve m!lf Family, és a dekl:lrációja szerint 500 darab CAT típlJSÚ objektumot dmz6 mulató! képes tá rolni. A nyitó ciklusban C22-27. sarok) 500 új CAT objektumot hozunk létre, amelyek a dinamikus memóriában kapnak helyet. Valamennyi új ohjektumban beállírjuk az életkort is, mégpedig a sorszám kétszeresl:nél eggyel nagyobb értékre. Az els6 CAT objektumnál tehát az é rték 1 lesz (a sorszám nulla!), a másodikná13, a harmadiknál 5 és így tovább. A dklusmag Ulols6 tömbt:le mbe n.

műveletével

az objektu mot

címző

mulatót elhelyezzük a

megfele l ő

Figyeljük meg tehát, hogy ebben az esetben nem maga az objeknnn (eAT) kerül bele a tömbbe, hanem csa k egy azt címző mutat6, ami a tömb deklarációja alapján pcrsze nem is lehet másként. A második ciklus (29·3 1. sorok) kiírja az egyes eltároh é nékeker. Ehhez ebben az esetben kétlépésrc van szükség. El őször kivesszük a megfelelő objektu m dmét a tömbból (Family lil), majd ezen kereszCi.iJ meghívjuk a Ge tAge () tagfüggvé nyt, ami visszaadja a kívánt é rté ket. Példánkb-.1O a Family tömb és n abban tárolt valamennyi mutat6 a vermen kap heIyel. Ugyanakkor az 500 darab CAT objektum a dinamikus memóriában van. Ennek a módszernek :~ verem tehermentesítésén fÚl megvan az az el őnye is, hogy megfelelő progmmszervezéssel csak annyi memóriát kclllefoglalnunk a CAT objekollnok számárn, nmennyit ténylegesen használunk is. Igaz ugyan, hogya fenti k6dban nem ez történik, hanem egyszeruen egy dklussallétrehozunk 500 ilyen obje ktumot, de a dklusváltozó felső határát akár a fe lhasználótól is bekérhellük volna. Bizonyos esetekben cz nyilván sokkal gazdaságosabb módszer, mint eleve létrehozni adott számú objektu mot.

278 1 IV. rész • Haladó eszközök Végezetül egy harmadik ciklusban töröljük a memóriából mind az 500 CAT objektumot, a Family tömb elemeit pedig null értékre 5l1íljuk

Dinamikus memóriában tárolt tömbök deklarálása Arra is

lehetőségünk

van, hogy a teljes tömböt a dinamikus memóriában [ároljuk, ne csak a bCl1ne elhelyezett objektumokat. Ehhez a new operátorL kell használnunk de úgy, hogy aZI kombinMjuk a tömbindex megadásával. Ennek a műveletn ek az eredménye egy mulató lesz, amely :17.1 ól memóriateriilelet címzi, ahova ti [őmb került. Lássunk egy példát: CAT *Family = new CAT15001;

Ez a deklaráció azt mondja, hogy Family egy muLatÓ, amely egy 500 darab Cl\T típusü objektumot t'iro16 tömböt dmez. Másként fogalmazva Family nem egyéb, mint a Family[OJ elem dmI:!.

,I

Ennek megoldásnak az egyik nagy előnye az, hogy ettől kezdve Inumtóaritmetikát is használhatunk a tömbelemek dmzésére. Lássunk erre is egy példát: C1\T "Family = new ClIT(5001 ; CAT *pCaL = Family; II pCat a Family[OI e l emre mutat pCat->Setllge(lO ); II F«mily[O ] érLékét lD-re á ll it juk pCat++; II advance to Family [l ] pCat->SetAge(20); /I Pamily(ll értékp.t 20-ra állit juk A femi els6 művelet létrehoz egy 500 CAT típusú demet tároló tömböt a dinamikus memóriáb:m és egy mutatÓl, amely ennek a tömnek az cls6 elemét címzi. A harmadik sorban ezen a mut:1tón (pontosabba n a másolatán) keresztül hívjuk meg az első ilyen CA'l' objektum SetAge () nevű tagfüggvényét, és heállítjuk vele a 1Q-es értéket. A mlllalól ezután inkrementáljuk, melynek hal.ís{ira immár a következő CAT objektumot címzi. EZl ismét a már látott módon használjuk, vagyis megint meghívjuk az aktuálisan címzett objektum Set1\ge () tagfü~'Vényét, de immár a 20 értéket adjuk neki bemenelkénl.

Tömb mutatója és mutatók tömbje Vi:t.Sgflljuk meg a következ6 három deklarációt: 1 : Cat FamilyOne[500l 2: CAT • FamilyTwo[SOO]; 3: CIIT • Family'l'hree = new CAT[500] ; FarnilyOne egy 500 CAT objektumot tároló tömb. FamilyTwo 500 olyan mutatót lárol, amelyek CA'r típusú objt!ktumokat címeznek. FamilyThree maga egyetlen mulató egy olyan tömbre, amely 500 CAT objektumol tárol.

15.6ra • Tömbök A három de klaráció közti eltérések drámaian befolyásolják a három dolog múködését. Ami talán még e nnél is meglepőbb az az, hogy flÚg FamilyThree rulajdonképpen FamilyOne valamiféle variá nsának is felfogható, addig FamilyTwo·tól gyökeresen különbözik. Mindezzel el is jutottunk ahhoz a kérdéshez, hogy miben is egyezik illetve tér cl egymástól egy tömb és egy mutató. FamilyThree egy mutató, amely egy tömböt címez, vagyis tanalma nem más, mint e tömb e l ső elemének a címe. A FamilyOne esetében szó szerint ugyanez a helyzet, vagyis maga a tömbnév nem c!''Yéb, mint a tömböt címz6 mutató.

Mutatók és tömbnevek C++-ban a tömb neve ncm egyéb, mint egy konstans mutató, amely,) tömb els6 elemét d mz!. N(:zzük a következ6 deklnrációl: CA'r Family l S0 1 ;

lu Family ncm egyéb, mim egy mmaló, mégpedig egy olyan mm:Hó, amelynek t:utalmaz az a cím, amit a &Family 101 mllvelettel is megkaphatn5nk. Kicsit egyszenlbben : a tömb nevét leírva ml::~kapjuk a tömb c1s6 elemének címét. A C++-b:m teljesen elfogadott, ha egy tömbnevet állandó nllltatókénr használunk , vagy épp fordítv:l. A Family + 4 forma tehát ebben a nyelvben ugyanazt jelent i, mint a Family r41, ugyanúgy hivatkozhatunk vele bárhol a tömb ötödik demére. Ha egy mulalÓ értékéhez hozz:'iadunk egy számoL, inkrememáljuk, v:tgy dekrementáljuk aZl, az ehhez szükséges Imlvelete a fordít6progra m végzi el. EZl azért fon tos hangsúlyozni, mert a Family + 4 forma természetesen nem egy olyan dmet jelent, ami 4 bájtnyira van a Family tömb e1ejét61. Ha például minden, a tömbben tárolL objekmm 4 bájt hosszlIságú, a kkor a Family + 4 cím 16 bájtnyirn lesz a tömb kezdetét61. Ha viszont a Family tömb CAT típusú elemeket tárol, és minde n CA'!' 20 bájtnyi tárhelyet igényel, :lkkor Family ~ 4 jelentése egy a tömb elejét6180 bájt távolságra nmtaeó CÍm lesz. A 1S.5. Lista e~y o lY'1n k6clor mutat be, amelyben a dinamikus me móriában hozunk lélre egy tömböt.

15.5. Lista - Tömb létrehozása 8 new operátorral (oewarrav.cpp)

o:

II 15.5 Lista - TOmb a dinamikus memóriában 1 : Hinclude 2, 3 : cla.ss CAT 4: {

5 : public :

1279

280 l iV. rész · Halad6 eszközök 6: CA'!'() { itsAge = 1; itsWeight=5; } 1/ alapértelmezett konstruktor 7: ~CAT() ; /1 destruktor S : int GetAge() const ( retllrn itsAge ; ) 9 : int GetWeight() const { return itsWeight; 10 : void SetAge(int age) 11 : 12 : private : 13 : int itsAg-e :

{ itsAge '" age ;

}

14 : int itsWeight ; 15 : J ; 16 : 17 : CAT : : ~CAT() 18 : ( 19 : /1 std " eout«

"Destructor called!\n' ;

20 : ) 21: 22 23 24 25

: int main() : : Cl\T * Fl.lmily .. new CAT [ 500j ; : int i;

26 : CAT • pCat ; 27 : for (i '" O; i < 500 ; iH) 28 : {

29 : pCat = new CAT ; 30 : pCat->SatAqe(2 * ]

+1};

31 : Fumily[ll ,. ' pCat ;

32 : delete pCat; 33 : l 34 : 35 : for (i .. O; i < 500; iH) 36 : std :: cout « 'Cat ." « 1+1 «

': •

37 : «Family[ij.GetAge() « s t d :: endl ;

38 : 39 : deletc [I Family; 40 : 41: return O; 42 :

Kimenet Cat U: 1

Cot 1/2 : 3 Cot B: 5 Cat "499 : 997 COL 8500: 999

A 24. sorban deklaráljuk a F'amily tömböt, amely 500 CAT típusú objektumot képes tárolni. A new CAT[SOOI utasítás hatására ebben az esetben az egész tömb a dinamikus memóriába kerül.

Apropó

Egy mGszaki részle!...

Technikai értelemben a 24. sorban tulajdonképpen egy a dinamikus memóriában le· vő névtelen tömböt deklarálunk. A Family mufafóba csupán a tömb első elemé· nek d me ke rűl. Ennek ellenére általiIban azonosnak teki ntj űk ezt a mutatót magával a tömbbel, ami azért nem helytelen, mert maga a C++ fordító is ~így gondolkodik". Amikor létrehozunk egy tömböt -legyen az akár a vermen, akár a dinamikus memóriában - annak a neve tulajdonképpen nem más, mint egy mutató, amely az elsó elemét clmzi. A tömbbe kerül6 CAT objektumokat szintén a dinamikus memóriában hozzuk létre (29. sor). Figyel jük meg ugy,makkor, hogy I:!bbl:!n az I:!setben nem az új objektumok mUlat6i kerülnek a tömbbe, hanem m:Lguk az objl:!ktumok. Ez a tömb tehát nem mUlalótömb, amelynek ekmci Cl\T típusú objektumokat címeznek, hanem CA'I' objektumok tömbje. Áltah'iban a [ l operátor( helyeltesíthetjük a * operátorra l Gndirekdó) is. A Family [3 J tehát cbben a helyzeten ugyanazt jelenti, mint a * (Family + 3) forma.

Dinamikus memóriában létrehozott tömbök törlése A Family név tehát nem egyéb, mit egy mutató, amely egy a dinamikus memóri!ib:u, talál ható, CAT objektumokat tarta lmazó tömb els6 elemét címzi. Amikor a 15.5. Lista 31. sorában használjuk a pCat mlllatót, akkor az garantáltan egy II dinamikus memóriában létrehozou CAT objektl.lmra mOIat, ami most bekerül a megfelelő tömbelembe. ( Eddig ugye semmi meglepö nincs 3 dologban, elvégre pont arról van szó, hogyan kell a dinamikus memórifib:m objektumtömböket kezelni .) Csakhogy a pCat mutatót ti ciklus következ6 iterációjában is feihasználjlIk. Nem jár ez azzal a veszéllyel hogy az el6zó CIIT objeknllnra már nem mutat semmi, és soha többé nem fildjuk felszabadítani az {t1t:da lefoglalt memóriát? Ez valóban nagy gond lehetne, de valójában nem kell t61e tartanunk. A fordítóprogram elég okos ahhoz, hogyemlékezzen az össze dinamikusan kezelt objektumra, így biztosak lehetünk benne, hogy az objektumtömb valamennyi eleme törölhető, és programunk vissL1kapja az általuk lefogla lt memóriát. Hogy megbizonyosoclhasSlmk err61, módosítsuk egy kicsit a 155. Listában bemutatott kódot. Először is változtassuk meg a tömb méretét 500-r61 IQ-rc a 24., 27. és 35. sorokban. Aztán vegyük ki a megjegyzésjelct a 19. sorban láthat6 cout utasítás elől. Amikor a program futása a 39. sorhoz érkezik, a tömb már nem létezik, a rendszer meghívta az abban tárolt valamennyi CAT ohjektum deslruktorál. Amikor a dinamikus memóriában létrehozunk. egy objektumot a new operátorral, azt a delet e utasítással lehet onnan törölni, amit az elem neve követ. Ehhez teljesen ha-

282 l iV. rész • Halad6 eszközök son!óan ha a new [l utasítással hozunk létre egy objekmmtömböt, akkor azt a delete [J utasítással lehet törölni. Az üres :z.'lr6jelpár jelzi a fordítónak aZl, hogy in egy egész tömb törlésé ről van szó. Ha véletlenül kifdejtjük a zárójeleket, akkor a mcrvelet csak az objektumtömb első elemét fogja törölni. EZl szintén beláthatjuk ~ kísér1elileg~ is, ha a 15.5. Lista 39. sorábó] eltávolítjuk a megje~,'yzésjeleL Ha ezzel párhuzamosan átszerkesztjük a 21. sort is úgy, hogya destruktor a képernyőn jelezze, ha lefut, akkor láthat6, hogy csak egy ilyen jelzés jelenik meg, vagyis csak cb'Y CAT objektum tÖrl6dÖtt. Sz6val gr..ltulálunk! Épp most sikerültl étrchozni cgy mcmór;akczclési hibát (memory leak).

Helyes

Helytelen

Ne felejtsük e l, hogy egy n elemű tö mb elemei O-lól n-J-ig sz5moz6dnak. Tö mbö k indexelését csa k olyan mutatókon keresztül végezzük, amelyek valóban az adott típusú tömbre Ilmtatnak.

Ne próbáljunk egy tömb vége után írni, vagy onnan olvasni. Ne keve rjük össze a tömböt dmző muta tót a mlllat6 tÖmbbe l.

Karaktertömbök A kar.lktcrl:'inc ne m egyéb, mint karakterek sorozata. Eddig C.'i upán névvcl nem rcndelkező karakterláncokkll ltalálkoztunk, általában a eout utasítással kapc.'>Ohnhan. íme egy példa e rre: cout «

"hel lo world. \n";

C++-ban a kal"oIkterlánc tulajdo nképpen egy karakte rtö mb, amelynek végét egy null karakte r jelzi. (A null karakter jelö lésére - megkülönböztetend6 a NULL értékU mutatótól- a '\0' használ:1tos.) Ennek megfelel6en egy kal"oIktcrláncot deklar.'ilhatunk és ini· dalizá lhntu nk is ugyanúgy, mint egy tömböt. Helyes tehát a kövctez6 forma: char Grccting [l .. { ' H', ' e ', ' W' , ' o ', ' r' ,' l ' , ' d ', ' \0 ' } ;

'l' ,

'l ',

'o ' ,

'

A sort záró i \0 ' karakter az a bizonyos null kllrakter, ami alapján a C++ függvényei meg tudják mo ndnni, ho gy hol van a karakterlánc vége. Bár a fe nti módszer működő­ képes, sem kényelmesnek, sem biztonságosnak nem nevezhet6. Sz{unos helyen el le· het gépelni, arTÓI nem is beszélve, hogy egy szöveget betfinként, vesszők kel elválaszt· va begépelni inkább gépír6i bravúr, mint értelmes mcgoldás. Éppen ezért a C++ biztosít egy sokkal kézenfekvőbb lehetőséget a karakterláncok megadás."ira : char Greeting[) "

"Hello World" ;

15, 6ra • Tömbök 1283

Ezzel a szintaxissal kapcsolatban két dologra szeretnénk fölhívni a figyelmet: • Az előző módszt:rlől eltérően itt nem egyszeres, hanem keltős idézőjeleket kell használni, a vessz6k és a kapcsos zár6jelek pedig nem kellenek. • Nem kell külön kiírnunk a záró null karaktert, az II fordítóprogram automatikusan beilleszti a karakterlánc végére. A "Hello World n karaktedánc 11 bctűb61 áll , tehát 12 bájt hosszúságú. A Hello 5 b{ljtot tesz ki, II sz6köz egyet, a World újabb ÖlÖl, a záró null kardkter pedig egy bájlOS.

Deklarálhatunk inicia1i7..áci6 nélkül is kar:.lktertömböket. Ezeket szokás puffereknek is nevezni. Mini ffiindtm lömbnél, természetesen ill is ügyelnünk kell arra , hogy nem a karjuk több karaktert elhelyezni egy ilyen lárban, mint amekkora a mérete. Az inici:llizáció nélkü ! dck!arálL karaktertömbük használatára mU lat példát a 15.6. Lista.

15.6, Usta - Egy karaktertömb feltöltése (arrayfilled.cpp) O; /1 15 . 6 . Lista KaraktertOmbOk pufferkánt való használata l ; linclude

"

3; 4, 5; 6: 7: 8: 9: 10 :

i n t main () { char buffer[801 ; std : : cout « "Enter the string ; ' : std : : cin » buffer : std : : cout « " Here ' s the buffer , • « return O; }

buffer «

std : : endl;

Kimenet Enter the string : Hello Wo r l d Here ' s t he buffer : Hello

Az S. sorban létrehozunk egy puffert, amely 80 karAkte rt képes tárolni . Ez azt jelenti,

hogy ebben a tömbben egy legfeljebb 79 bettls szövegel helyezhetünk el, hiszen kell egy bájt a lezár6 null karaktcrnek is. A 6. sorban bekérunk a felhasznál6tól cgy szövegel, amit a 7. sorban el is helyezünk imént kialakított pufferben. A cin automatikusan elhelyezi a karakterlánc végét jelz6 null karakte r, ezzel tehát nem kell tör6dnOnk.

37..

A 15.6. Listában bemutatott kóddal két probléma is van. El6ször is nem tudjuk, hogy mit fog gépelni a felhasználó. Ha 79 karakternél többet ad meg, akkor a puffer túlcsor-

284 1IV. rész' Haladó aszközök dul, hiszen a c in nem érzékeli a végél. A másik probléma, hogy ha a felhasználó szóközt is gépel, akkor a cin azt fogja a bemenet végének tekinteni , és a maradékot be sem írja a pufferbe.

Ezeknek a problémáknak a megoldásra kicsit át kell alakítanunk a programot: a cin egy speciális metódusát, a get () -et kell használnunk. A c i n . get () három paramétcn vár bemt!nelké nl: •

A kitöltcnd6 puffer nevét

• •

A beolvasni kívánt karakterek legnagyobb számát Azt a jck:t, amit a bemenet végének kell tekinteni

Az alapértelmezett "bemenet vége jel az újsor. A módosított kód a 15.7. Listában látható. 15.1. Lista - Karaktertömb feltöltése (második változat) larrayfilled2.cpp) o : 111 5 .7. L i!l t ól A ci n . get (} met6dus ha szná léltv. l : #i nc l udc 2. 3 : int ma in() 4: 5: 6: 7: 8: 9:

I char buffer[80] : std : : cout « " Enter the st r ing : "; std :: cin . get!buffer, 79) : II get up to 79 or newlinú /ltd : : cout « "Here ' s the buffer : • « buffer « std : : endl ; return O;

10 :

menet Enter the sLri ng : Hello World Here ' s the buffer : Hello Wo r l d

A ci n osztá ly ge t () rnetódusát a 7. sorban hívjuk meg. Ennek az első argu rnenmma az a puffer, amit az 5. sorban deklarálrnnk. A második bemenő paraméter a bekérhet6 karakterek maximális száma . Esetünkben ez 79, mivel a pufferben így még é ppen elfér a záró null karakter is. A bemenet végét jelző karakte r megadására itt most nincs szükségünk, mivel az alapértelmezett újsor erre a célra éppen megfelel. A cin-ről és annak mindenféle különlegességér61 majd a 21. órában sz6lunk részletesebben.

Az strcpyO és az stmcpyO függvények A C++ örökölte a C nyelvtől a karakterláncok kezelésére szolgáló függvényeket. A számos lehetséges mO"velet közül iti csak kettőt szeretnénk kiemelni, amelyek karakterlán-

lS.6racok másolásra szolgálnak. Az c&'Yik az strcp () fijg&'Vény, a másik az s t rncpy ( ) . Az strcpy () működése viszonylag egyszenT: veszi a megadott kamkLerláncot, és a teljes tartaImát átmásolja a szintén megadott pufferbe. Használatát a 15.8. Lsta szemlélteti.

15.8. Lista - Az strcpyll függvény használ... (..ingstrepy.epp)

o:

1/ 15 . 8 . Lista - Az s trcpy() fo.ggvény használata l : #include 2 : #inc l ude

)

.

4: int main ()

5: { 6. chnr Stringll] = "No man is an island"; 7: char String2lBOJ ;

,.

9 . strcpy (String2 , Stri ngl) ; 10: « ll : s td : :cout « · string1 :

12: std : : cout « l): return O; 14:

"String2 :

«

Stringl « Stri.ng2 «

std :: endl ; std: : endl ;

JGmanot Stringl : No man iy an island String2 : No man is a n island

A 2. sorban beemeljOk a STRING . H fejlécállományt, amely tartalmazza az strcpy () függvény prototípusát. Az strcpy () bemenetként két karakte rtö mböt vár, melyek közü l az első il másolás c;(:lja, és a második a forrlIs. Ügyeljünk amI is, hogy ha a forrns

több adatot tartalmaz, mint nmennyi a célpufferben elfér, akkor az strcpy () en túlírja azt.

egyszerű­

Ennek a lchel,>éges hibának a kiküszöbölésére a szabványos könyvtár tartalmaz egy strncpy () nevű változatot is, amelynek a másolni kívánt kamkte rck maximális számlIt is mcg lehet adni. A fü ggvé ny az első null karakterig másol, vagy nmíg el nem é ri ezt az e l ő re rögzíLeu számot. Az strncpy () függvé ny használa tM szemlélteti a 15.9. Lista .

15.9. Lista - Az strncpyO függvény ha""lata (usingstrncpy.epp)

o: II 15 . 9 . Lista Az strncpy() fo.ggvény használata 1 : öinc1ude 2 : *lnclude ) .

4 : int main() 5: {

6 : const int MaxLength : 80; 7 : char Stringl [] : "No man is an island";

I

286 IV. rész • H~ad6 eszkÖ2Ök 8 , char String2[MaxLength+l1; 9.

10 : strncpy(String2,Stringl,MaxLength); ll: 12 : 13 : 14 :

String2[strlen(Stringll] std : : cout «'Stringl : s t d :: cout« 'String2 : return O;

' \0'; II add a null to the end String! « std : :endl; «String2« std : : endl;

Speak(l; 70: } 71 : 72 : void RefFunction (Mammal & rMammal) 7]: { 74 : rMammal . Speak (); 75 : )

Kimenet (l)dog (2) cat (O)Quit : 1 Woof Woof MilIMlal Speak! (l) dog (2lcat (O)Quit : 2 Meow! Meow! Hammal Speak! (ll dog (2)cat (O)Quit : O

322 1V. rész· Öröklődés és többalakúság

A 3-23. sorban az em lős, kutya és macska oszlályok leeb'Yszerusíleu változatait deklaráljuk. Három függvényt is deklarálunk, PtrFunc t ion (). Re fFun ct i on (), és Va lue Func tion (l nt'!ven. Ezek egy eml6s mutatót, e ml6s hivatkozást illetve eb'Y eml ős objektumot várnak par-améterkénl. Mindhárom függvény ugyanntteszi: meghívja a Speak () metódusl. A fel hasznflló választhat kutya és macska közötti választásának megfelel6en készül el egy mulató a megfelelő típus!".! a 38-52. sorban. A kimenet első sora szerint a felhasználó a kutyát v{L!aszlja. A kutya objektum a dinamikus mem6riatertlleten készül el ti 44 . sorban. Ez a kutya azlán mut;ltóként, hivatkozásként és érték szerint keiii i átadásra Speak () függvény kelill meghívásra. Ez látszik a felhasználó első választása utáni két sorban. A feloldott mutatót már érték szerint adjuk át. A függvény egy eml5s objektumot vár (err61 tanúskodik a paraméter-szignatúrája), így a fordítóprogram lccsonkítja a kutya objektumOt llZ emlős . részére". Ily m6don Purr() ; else cout«

'Húha,

6í! :

delete Zoo [ i] ; cout « "\ n";

63 : 64 :

65 : 66 : 67:

rcturn O;

68 :

IGmenet (I)Kutya (2)Hacs ka : l

Hammal (eml6s) konstruktor. Dog

(kutya)

konstru ktor . . .

ez nem

macska!\n';

334 1V. rész • Öröij6dés és többalakúság (llKu t y a

(2) Mac!lka : 2

Hammal (em16s1 kons truktor .. . Cat (macska) konstru ktor .. . (l)Kutya (2)Macska : 1

Mammal (emlos) konstruktor ... Dog (kutya) konstru ktor ...

Vaú ! Húha, ez nem macska ! Hammal (cm16s) destruktor ..

Mijáú rrr r r rrrrrr Hammal (em16s1 deHtru ktor ... Vaú ! Húha ,

Mamma l

EI.

~Z

n em maCSkll !

(em16s) des t ru kt o r .

S

A 38.·48. sorokb:Ln :l felhasználó választása szerint adunk hozzá Cat vagy Dog objekrumokat a Mammal típusú mutatók tömbjéhez. Az 52. sorban végigmegyünk a tömb ek.... mein, majd az 54. sorban mindegyik objektum speak () mCl6c\usát meghívjuk. A tagfüggvények többaJ:.kúként viselkedve különböz6 eredményekkeltérnek vissza: A kutyák ugalnak, :I m:,cskák nyávognak. Az 59. sorban egy Cat típusú objektumon szeretném meghívni ;1 purr () (dorombolás

tagfüggvé nyt , dc nem szeretném abban az esel!)en, ha Dog típusú objektummal van do lgom. Az s6. sorban has7.0áll dynamic_cast operátor gondoskodik r6 1a, hogy az objektum, aminek a purr () tagfüggvényét hívju k, biztosan Cat típusú legyen. És in található a kulcsmomentum: Ha eat lípusú , a rnutató ~néke nem null, így megfelel az 58. sorb:m találhmó fe ltételvizsgálatnak.

Elvont adattfpusok Gyakr:m készítünk osztályhierarchiákat. Ha például létrehozunk egy Shape (síkidom) osztályt alaposzlály gyanánt, majd ebből származlatjuk a Rectangle Úéglal:.1p) és Circle (kör) osztályokat, máris hierarchia keletkezett, ha nem is valami bonyolult Ezután a Rectangle osztályból tovább származtathatjuk a Square (négyzet) osztályt, nunt a négyszögek egyik speciális képvisel6jél. Mindegyik sZiÍ rmaztatOlt osztály felüldefmiálja a Draw () (rajzo!), és a getArea () (teruletszámítás) metódusokat és még másokat. A 18.3. Lista a Shape osztály lecsupaszíton megval6sítását mutatja a szánnaztaton Cir c1e és Rectangle osztályokkal.

18. óra • A

kifinomult használata 335

18.3. Ut.. - SIkldom autítyok (.h.pecl....cpp) O, 1, 2,

II 18 . 3 . Lista - Sikidom osztályok lincludc

3:

class Shape

4: 5, 6:

( public : Shapc() (l

7: 8: 9: 10 :

virtual virtual virtual virtual

11 :

);

12 : 13 :

class Circle

-Shape(){) long GetArea() { return -1 ; } II hiba long GetPcrim{) { return -1; } void Draw() {)

public Shape

14 :

15 : 16 : 17 : 18 :

19 :

20 : 21 :

22 :

public : Circlc (int radius) : i tsR!!Idius {radiusl (l -Ci rel e () {}

long GetArea{) ( return 3 • itsRadius long GetPerim() void Draw ( ) ; privata: int i tsRadiu$ ;

23 :

{ return 9 * itsRadius;

itaRadius ; }

int itsCircumference ;

24 :

};

25 : 26 : 27 : 28 : 29 :

void Circ!e: :Draw() ( std: : cout « "KOr rajzolását végz6 utasítások helye! \n";

30 : 31:

32 :

class Rectangle

33 : 34 : 35 : 36 : 37 : 38 : 39 : 40 : 41 : 42: 43 : 44 : 45 : 46 : 47 : 4B : 49 : 50 ,

(

public Shape

public : Rcctangle(int len, int width) : itsLcngth (len), itswidth(widt h) () virtual -Rec tangle{) {} virtual long Ge tArea () ( return itsLength * i tsWidth; ) virtual long GetPerim() (return 2 *i tsLength + 2 *i tsWidth; v irt ual int GetLength{) ( return itsLength; virtual int Gctwidth() { return itsWidth; } virtual void Draw ( ) ; private : int itsWidth ; int itsLength ; ); void Rectangle : : Draw() for (int i

='

O; iEat () ; pAnimal->Reproduce() ; pAnimal->Move() ; pAnimal->Sleep() ; delete pAnimal ; std : : cout « "\n"; return O;

140 :

menet (l) Ku tya (2) L6 (3)Hal (O)KiIópós: 1 AnimaI konst r ukto r . Mamma! konstruktor . Dog konstruktor ... Vaú ! ...

A kutyák étkezési szokásai ... A kutyák szaporodása . A kutya futni szokot t . . . A kutyák a lvás i szokásai . Dog destru k tor ... Mamma! destru ktor . . . AnimaI destruk tor . . . (1)Oog (2)Horse (3)Bird (O)Quit: O

349

A 6-20. sorok közön adtuk meg az Animal osztály, mint elvont adattipus meghatározásál. Tartalmaz egy i tsAge () (kora) nem űres virtuális függvényt , valamint öt másik ürese!: Sleep (l, Eat (), Reproduce (), Move (), és Speak (). A Hammalosztály az Animal-b61 származik, a 28-36. sarok között található a meghatármása. Nem hoz létre új tulajdonságokat, de felüldefiniálja a ReprOduce () függvényt, általános formában leirva a sznporodásl az összes eml6sre vonatkozóan. A Fish osztálynak (elül kell clefinb'ílnia :l Reproduce () tagfüggvényt, mivel az közvetlenül az Animal OSZtá lyból szá rmazik, és nem tudja felhasználni a Mamma! osztály szaporodására vonatkozó !llliveleteket (ami egyébként így helyes). A Mammal-b61SZ!lrma7.Latoll osztályoknak nem keJl felü ldefini5lni II Reproduce () függvényt, de meglehetik, ha afra nn szükség (mint a Dog osztá ly esetében a 95. és 96. sorban). A Fish, a Horse és Dog osztályok mind felüldefiniálják az összes maradék tagfüggvényt, amelynek következtében ezek az oszt,1]yok példányosíthat6k. A program tönsében egy Anim!lltípusú ml..nat6t használunk a különböző szá rmaztatott objektumok e lé résé hez. Amikor a virtuális ragfüggvényckcl meghívjuk, a futásid6beni hozzárendeléseknek megfelel6en mindig a kívánt osztályok tagfüggvényei futnak le. Az AnimaI és M!lrnrMl osztálYOk példányosítására teu kísérlet fordítási hibához vezetne, mivel mindkett6 elvont adattípus.

Mely trpusok elvontak? Az egyik programban az Animal elvont oszttily, a másikban nem az. Mi hat5rozza mcg azt, hogy mikor kell egy oS7.tályt elvontként meghatároznunk? A kérdésre adott válasz nem a val6 világ valamely lényeges tényezője 2. 3: *pFunc) delete ptr;

81 : 82 : 83:

return O;

(J ;

(J)horse:

";

20. 6ra •

menet (O)Qu i t (1) Dog (2)CaL (1)Speak (2)Move : 1 Woof! (O)Quit (1)oog (2)Cat (1)Speak (2)Move : 1

(3}Horse : 1

(3)Hor sc :

2

(3)!-!orse:

3

(3)Horse :

o

Meow! (O)Quit ( 1) Oog (2)Cat ( 1 )Speak (2)Movc : 2

Galloping (O)Quit

(1)Oog

(2)Cat

Az 5-14. sorban a Mammal (emlös) absLtr..kt adattípust deklar:lljuk két tiszt~n virtll{llis metódussal; ezek a Speak () és a Move () . A Mammal alosztúlyai a Dog, ;1 Cat és a Horse (azaz a klltya, a macska és a 16), mindegyik feIOlírj:\ a Speak () -et és a Move ()-ol. A f6program megkérdezi a felhaszná lót, hogy melyik áJlatfajtát ho zzuk létre. Ekkor létrejön 11 mum6riában az AnimaI-nak megfelel6 ~J[:l!oszt{lly, és címe bukerül ti ptr nmtmóba a 49-63. sorban. Ezután eldöntheti a felhasz.náló, hogy melyik metódlIst szerelné meghívni. A döntésének megfele l ő metódus címe bekerül ·DogFunctionsIMethod-lj) () ;

Valljuk be, ez így egy kissé ezoterikus, de ha a programban valami miau éppen ragfü8b",ényekb61 álló táblázatm van szükség, ez Cf,'Yszeruöbé és 0lvashat6bbá teszi a kódot.

I

400 VI. rész· Különlegességek

Kérdések és válaszok Kérdi'!>: Miél1 haszllá/llánk slatikus vállozókal, ha lehel globálisakails lIasZ/lálni? \fáIasz: A statikus változók ha16köre egy osztályra ko rlátozódik, igy csak ezen osztály példányaiból érhetóek el: nyilvános változ6 csetén explicit és teljes osztálynév-megadással, vagy esetleg egy statikus tagfüS&",ényen keresztüL A statikus adatok típusa az osztályhoz kÖl6dik, és a szigorítou elérés, illetve :I Z erds típusoSs{lg miatt b iztonságoslibban használh:Hók, mint a globálisak. Kérdés: ANér/ "aszt/álnúnk slaukus lagfüggvényel-.:cI, lIa lehet glo/:Jálisakal is !taszllál"i? Válasz: A statiku.s lagv:i lloz6k egy osztály hatókörébe tm1.07;nak, és Csak az adott osz-

t(lly objektum{m keresztül érl1et6ek el, vagy kifejezett és teljes osz!álynévvel, mi nt példúu l C1U8sName: : Funct;.ionName ( ). Kérdés: Miér/ nCIII Icsszf}k mindcll osztályul/kal aZOIl osztá{}'Ok barálaivá, amelyeket használllak? Vúlasz: Egy o..o;ztály baráuá nyilv{mít:'isa napvilágra hozza a megval6.sítás részleteit és la7.ítja az egységlx:zárást. A cél :lZ, hogy az osztályok megvalósításának a részletei lehet6leg maradjanak rcjrvc más osztályok eI6t1.

Gyakorlatok Az elmúlt órában megisrnerkedtünk a különleges osztályok, fí.iggvények és mUlatók világával. Yíllaszoljunk meg néhány kérdést és végezzünk cl nC:hány fel::tdatot, hogy el1l1élyíL itsLen) return itsString[itsLen - 1 ]; else return itsString[offset) ; ASSERT(Invariants(); )

AnimaI : : Anima1 (int age , const String& name) : 199 : itsAge( age),

200: itsNallle(name) 201 : {

21 , 6ra • kl 202 : ASSERT(lnvariants(» ; 203 : }

204 : 205 : bool Animal :: Invariants () 206 : { 207 : PRINT ( • (AnimaI Invariants Checked) ') ; 208 : return (itsAge > O && itsName.GetLen{» 209 :

;

210 : 211 : int main() 212 :

2 13: const int AGE = 5; 214 :

EVAL(AGE) ;

215 : AnimaI sparky(AGE . 'Sparky') : 216: std : : cout « " \n' « sparky . GetNarne() . GetString() ;

217 : 218 : 219 : 220 , 221 :

std :: cout«' is ' I std :: cou t «sparky . GetAge() «

AGE:

5

• years old . ' ;

spnrky . SetAge (8) ;

std: : cout « std :: cout « 222 : std :: cout « 223 , return Oi 224 :

' \n " « sparky .GetName( ) . GetString() ' is' , sparky .GctAgc() « • years old ."

(String Invariants CheckedI (String Invariants Checked) (String Invariants CheckedI (String Invariants Checked) (String Invariants Checked) (Stri ng Invarianto Checked) (String Invariants Checkcd) (String Invariants Checked) (String Invariants Checked) (String Invariants Chec~ed) Sparky is (AnimaI Invariants Chec kedl 5 Ycars old . (AnimaI Inv",ri",nts Checkcd) (AnimaI Invarisnts Checkcd) (Animul Invariants Checked) Sparky is (lmirnal Invaria nts Checked) 8 years old . (String Invaria nts Checked) (String Invariants Checkcd) II run again with DEBUG : MEDIUM AGE :

5

Sparky is 5 years old . Sparky is 8 years old .

i

431

432 1VI. rész • Különlegességek

Apropó

A fordftáskor figyelmeztető üzeneteket kaphatunk

Ennek a kódnak a fordítása közben is felb ukkanhatnak ugyanazok a figyel meztető üzenetek, a melyekről a 21.4. Lista kapcsán már volt szó. Az. ok természetesen ugyanaz.

Elemzés Az assert () makró k6dját a 8-18 sorok tartalmazzák. Ez ebben az esetben úgy van kiahtkítva, hogy Im a DEBUGLEVEL énéke alacsonyabb mint LOW(vagyis NONE), akkor a nyomkövetési kódok egyáltalán nem kerülnek bele a fordítandó állományba. Ha a nyomkövetés bármilyen szinten megengedett, akkor az assert () ml1ködésbe lép. A 20-25 sorokban híthat6 EVAL nem kerül bele a k6dba , ha DEBUGLEVEL énéke alacsonyabb mint MEDIUM. Ez tehát azt jelenti, hogy ha DEBUGLEVEL énéke NONE vagy I.OW, akkor EVAL nem kerül bele a k6dba. Végezetül a 27-32 sorokban látható PRINT makró aktjválásá hoz DEBUGLEVEL HIGH ~r­ léke szükséges. Ez tehát azt jelenti, hogy cz a makró még a MEDIUM nyomkövetési szinten is hatást.dan , miközben ezeken aszinteken EVAL és assert () már ml1ködnek. A PRINT makrót az InvarÍcl. Ha egy Ozenerobjektum elkészült, a konstruktor munkája véget ér. A szerkesztő met6clusnak a ko nstruktorból való meghívása c5 theOtherObject.myValue) kleLarger; kIsSame ;

52 :

53 : II Egy másik osztály, amit szintén a listában kívánunk tárolni II Ebben a láncolt listában is a korábban említett két met6dusra II lesz szakség : II Show : Kiírja az objektum értékét . 58 : II Compare: Osszehasonlítja két objektum értékét. és relatív .. podci6t ad vissza . 59 : 60: class Cat 61 : { 62 : public : 63 : Cat(int age} : myAge(age} (j 6 4: _Cat() 65 : { std : : cout « myAge « " éves macska tOrlése\n" ; 66 : 67 : 68 : i n t Compare (const Cat &) ; 69 : void Show() 70 : 71: std , : cou t « "Ez a macska': std : : cout « myAge « • éves\n": 72 : 7] : 74 : private: int myAgű ; 75: 76 : } ; 77: 78 , 54 : 55 : 56 : 57 :

1 23, óra • 79 : II A Compare met6dust arra használjuk , hogy egy adott objektum 80 : II listában elfoglalt helyét megállapits uk . 81 : B2 : B3 : B4: BS : 86 : 87 : 88 : 89 : 90:

int Cat : :Compare (const Cat

&

theotherCat )

if (myAge < theO therCat . my Age) return k IsSmaller ; i f ImyAge > theO therCat .myAge) return kIsLarger; else return kIsSame;

91: 92 : 93 :

94 : 95 : 96 : 97 : 98 : 99 : 100: 101: 102: 103: 104: 105: 106 : 107 : lOS : 109 : 110 : lll :

112: ll3:

II A liűta táro16objektumának absztrakt adattipusa II Minden származtatott tipusnak falűl kell defint~lnia

Sz Insert

.. és Show met6dusokat tcmplate class Node { public : Node () () virtual -Node I) I) virtual Node ~ InsertIT· theobject)zO; virtual void Showl) = O; private : };

ternp1ate class Interna lNode : public Node public : InternalNode(T * theObjcct , Node • next); -Interna1Nodel){ deleta n~Next; delete myObject ; virtual Node • InsertiT · theobject) ; virtual void Show ( ) (

114 : myObject - >Show(): 115 : myNex t->Showl); 116 : II delegálás 117 : private : US : T • rnyObject ; II Maga az objektum 119 : Node * myNex t ; II a lista kOvet kez6 t áro16e l emére muta t 120 : ) ; 121 : 122 : II A konstru ktor csak inicializál 123 : tcrnplate 124 : InternaINode:: InternalNode IT * theObject, Node * nex t) : 125 : rnyObjectltheübject),myNext(next) 126: ( 127 : ) 128 : 129 : II A lsita velej e 130 : II Amikor a l i s t ába új objektumot tes zü n k, 131 : II átadju k a táro16elemnek , amely ki ta l álja

470 11n, rész • Kiilönlegesség.k 132 : /1 a helyét. és beszúrj a a listába. 133 : templat c 134 : Node ~ InternalNode : : Insert(T * theObject) 135 :

136 : 137:

/1 Az új szerzet kisebb vagy nagyobb nálam? i nt rcsult = myOhject->Colnpare(*thcObjec t) ;

138 :

139 : 140 : 141 :

14 2 : 143: 144 : 145:

switch(result) { 1/ 11. tradició szerint, ha egyen16ek vagyunk, övé az els6bbség. case kisSame : / I {gy ez az ág átvezet arra az esetre, .. amikor nagyobb nálam case kisLarger: 1/ Az új objektum elém kerül ( IntcrnalNode • ObjectNode =

146 :

new InternalNode(thcObject , t his):

147 :

return Objcc t Nodc l

1.48 :

149 : II Nagyobb nálam , tehát adju k át a kOvetkez6 táro16elcmnck 150 : 151 : case kisSmaller : 152 : myNext = rnyNext->Insert(thOObjcct) ; 153 : return this; 154: 155, return this; 156, 157: 158 , II A Tail tárolóelern csak őrszem szC!repet játszik 159 , template 160: class Tai1Node : public Node 161 : ( 162 : public : 163: TailNoda(){} 164 : virtuel -TailNode(){} 165 , virtual Node • Insert (T .. theObject) ; 166 : virtual void Show() { } 167 : private: 168 : }: 169 : 170 : II Ha az Object típusú objektum hozzám kerül, mindenképpen elém 171: /1 lesz beszúrva, hiszen én vagyok a zár6elem , .. aki IllOgOt t már semmi sincs. 172 : templat e 173 : Node • TailNode :,Insert( T .. LheObject} 174 :

175 : 176 : 177: 178 :

Interna1Node • ObjectNode = new InternalNode(theObject, this); return ObjectNode;

179 : 180 , II A kezdd táro16elemben nincs objektum,

181 : 1/ csupán a lista 1ege ls6 el emére mutat 182 : templat e 183 : class HeadNode : publ ic Node

23. óra • Sablonok 471 184 : 185 : 186 : 187 : 188 , 189 : 190 : 191 : 192 : 193 : 194 , 195: 196: 197 , 198: 199: 200 : 201 , 202 : 203 : 204 , 205 : 206 : 207 , 208 : 209 , 210: 211 : 212 : 213 : 214 , 215 : 216 , 217 : 218 : 219 , 220 : 221 : 222 : 223 , 224 : 225 : 226 , 227 : 228 : 229 : 230 : 231 : 232 : 233 : 234 : 235 : 236 : 237 :

public: HeadNode(); virtual ~HeadNode() { delete myNext; } virtual Node * Insert(T * theObject) ; virtual void Show{) ( myNext~>Show() ; ) private: Node ~ myNcxt; }; / / Mihely 16trejön ti kezd6elem, / / az nyomban maga mögé teszi zár6elemct is template HeadNode: : HeadNodc() { !lIyN!:lxt : new TailNode ;

/1 A k ezd6elem el6tt nincs semmi, :így az objektumot II rögtön továbbadhatjuk a k övet kez6 táro16e l emnek . template Node * HeadNode :: Insert (T • theObject) ( myNext : myNext - >Insert(theObject) ; return this;

II Minden munkát delegálok, de enyém a dics6ség template class LinkedList

{ public : LinkedList(); -LinkedList() { deiete myHead ; } void Insert(T ~ theObject) ; void Showl\l1() ( myHead->Show() ; private : HeadNode * myHead ; }; II Születésemkor létrehozom a kezd6eleme t . a mely maga mögé II h e lyezi a zár6elemet . II Az üres lista tehát egy kezd6e lcmb6l áll . amelyet azonnal a /1 zár6elem követ , köztük pedig ninc s semmi . template LinkedList: :LinkcdList() ( myHead = new HeadNode ;

1/ oelegálj , delegálj, delegálj template void LinkedList :, Insert(T * pObject) {

472 1VI. rész • KilI6nl'llosségek 238 : 239 : 240:

myHead->Insert(pObject ) ;

241 : 1/ Tesztprogram 242:

243: 244: 245 : 246: 247 :

int main ()

• pCat; Data * pData; int val ;

C~t

Li nkedList

ListOfCats ;

248 : 2 4 9: 250: 251:

LinkedList ListOfOata:

252 253 254 255 256

for (;;)

: : : : :

1/ a felhaszná16t61

bekérűnk

pár értéket

1/ és elhelye2:zük azokat II l i stában { std :: cout« "Adj meg' egy értéket std :: cin »va l; i f (ival) break: pest ~ ncw Cat(val); pOata: new Data (val) ;

257 : 258: 259:

260: 261: 262: 263 :

(O vége):

";

ListOfCats.lnsert(pCat); ListOfOata.lnsert(pData):

264 : II végigmegyOnk a listán és kiírjuk az e l emek értékét . 265: std: : cout « ' \n ' ;

266: ListOfCats.ShowAll(); 267: std: :cout «

"\n",

268: ListOfData.ShowAll(); 269 : std :: cout « "\n ****,,***." •• \n\n"; 270: return O; II A listák kikerülnek a hatókOrb61 , és megsemmisülnek. 271:

Adj Adj Adj Adj Adj

meq meg egy meg egy meg egy meg egy Adj meg egy E, a macsk.!! a macska E, a macska a macska E, a macska

"'

"'

"""

értéket é'rtéket értéket értéket értéket értéket 2 éves 5 éves 7 éves 9 éves 13 éves

(o (o {o {o (o (o

vége) vége) vége} vége} vége) vége)

: : : : : :

5 13

2 9 7

O

Data objektum törlése, melynek é rt éke: 13 Dato objektum t ö r lése, melynek é rtéke : 9 Data objektum törlése, melynek értéke: 7

23. óra • Sablonok 1473 Data objektum törlése, melynek értéke: 5 Data objektum törl ése, melynek értéke : 2 13 éves macska t órlés e 9 éves macska t Or lése 7 éves macska törlése 5 éves macska t ö dés e 3 éves macska tOrlé se

Mindenekelőtt,

vegyük észre, mennyire hason lít a 23.1 Lista a 19. órán bemutatOllhoz.

A legnagyobb változás, hogy minden osztály- és metódusdcklaráci6 el6tt a következ6 preAx áll: Lempl ate c 1ass

Ebb6 1 ludja II fordító, hogy olyan típussal parnmétereztük a listál, amelyet c&1.k a példányosítás pillan:náhan fogunk megmondani. A lárol6elem Node osztályának deklarációja most például íh'Y néz ki: template class Node

Eszerint :1 Node osztály önmagábrtn nem létezik, de példányosítani fogjuk a Cats és a Data oszlállyaL A paramélCrczeshez használt típust T jelöli. Hasonlóail, az Interna lNode helyett most InternalNode áll (T típus InternalNode - ja). Továbbá, InternalNode nem egy Data objeklumra es egy másik Node-ra mutat, h.mem egy T típusú objektumra és egy Node objektumm. Ez lámató a 118. és a 11 9. sorban. Nezzük meg alaposabban a 133-156. sorban definiált Insert mel6duSl. A logika ugyanaz, de ahol korábban konkrét típust (Data) használrunk, Olt most T szerepel. Tehát, a 134. sorban a paraméter mulató egy T típusú objekrumra. Később, a példányosít{\skor, a fordító T helyére behelyettesíti II megfelel6 típust (Data és Cats). A lényeg, hogy az Internal Node az adattípustó függetlenül elvégzi a feladatát. Tudja, hogyan hasonlílSa össze az objektumokat. Egyáltalán nem érdekli, hogy a Cats objektumok pontosan úgy hasonlítják össze egymást, mint a Data objekrumok. Valójában, a Cats osztályt újraírhatjuk úgy, hogy a kort nem tárolja, hanem a születési id6ból szükség szerint kiszámítja. Az InternalNode-ól ez egy cseppet sem érdekli.

474 1VI. rész • Külön~g.sség.k

Sablontípus használata A sablontípus úgy használh:tt6, ahogy a többi típus. Átadható függvénynek paraméte rk~n\, de lehet vis.~zaté rési érték is, mindkét esetben énékkel vagy referenciávaL Ezt mutatja be a 23.2 Lista. Hasonlítsuk össze a 23.1 Listával!

23.21J1111- Pa_1Isto ~......... (16aCOIt- _ _ 6YoI1

f--.

l

1 : II 23 . 1 példa

2 : II 3 : /1 Paramétere2ctt lista bemutatása 4: / I

5 : II 6 : II 7, / I 8, / I 9: II 10, II 11: II 12, II 13 : /1 14 : II 15 : II 16 : II

Paraméterezctt lista objektum-orientált megva16s1tása. A List az absztrakt Node táro16elemnek delcgálja a munkát.

Háromf61c táro16elemet használunk: kczd6t. zár6t és kOzba!s6t. Csak ez utóbbiban tárolunk hasznos objektumot. A Data osztályt azért hozzuk létre , hogy példányait a listában tároljuk.

II 18 : II **** ************** ********* **.**** ****** -******

17 :

19 : 20 : 'inc1ude 21 : 22 ; enum { kIsSma1ler. kIsLarger , kIsSame} ; 23 : 24 : II A listában tárolható Data osztály 25 : II Minden olyan osztálynak, melyet ebben a listában szeretnénk .. tárolni , rendel kezni e kell a kOvetkez6 két metódussal , 26 : II Show : Kiírja az objektum értékét. 27 : II Compare: OsszehasonH tja két objektum értéké t, és meghatározza _ a relatív poziciót . 28 : class Data 29 :

30 , 31 , 32 : 33 : 3 4: 35 :

public : Data{int val),myValue{val){) -Data () ( std : : cout « 'Data objektum tOrlése, melynek értéke: '; std: : cout « myVa 1ue « '\n ' ;

36 :

37 : 38 ,

int Compare(const Dat a & ) ; void Show() ( std : : cout « myValue «

std : : endl ; )

-

- --

-

-

-

-

23. óra • Sablonok 1475 - - - -- -- --=-=---==""'-''----------' ..

39 : prlvate : 40 : int rnyValue ; 41 :

J;

42 :

43 : II A Compare met ódust arra hasz ná ljuk, hogy egy adott objektum 44 : II listában el f ogl al t helyét megá l l apit suk . 45 : i nt Da t a : : Compa re (const Data & t h e OtherObj ect ) 46 : 47 :

48 : 49: 50 : 51 : 52 : 53 :

{

i f (myVa l ue < theOthcrObject.rnyValuc)

return kIsSmaller ; if (myValue > theOtherObject . myValue) retu r n kIsLarger ; else return kIsSame; l

54 :

55 : 1/ Egy másik osztá l y , ami L szint én a listában kívánunk tárolni 56 : II Ebben él láncol t lisLában i s a korábba n említett ké t met6dusra 57 : II l esz

szű k ség :

58 : /1 Show: Kiírja az objektum értékét . 59 : /1 Compare : Összeha sonlítja két objektum értékét, ... és relatív poziciót ad vissza . 60 : 61 : class Cat 62 : ( 63: public : 64 : Cat(int age) , myAge(ag-e) {} 65 : -Cat() 66 : ( std : : cout « !nyl\ge « 67 :

r.~l ~:;~:
Compare( *theObject) ; 138 : 139 : switch{rcsu1t l 140 : { 141 : II A tradició szerint, ha egyen16ek vagyunk , 6vé az els6bbség. 142 : case ItlsSame : II ez az ág átve zet arra a z esetre, .. amikor nagyobb nálam

23. óra • Sablonok

146 : 147 :

case kIsLarger : /1 Az új obj ek tum e lém ke rul ( InternalNode * ObjectNode : new InternalNode (theübj ect, this) ; return ObjectNode;

148 : 149 :

/1 Nagyobb nálam. tehát adjuk át a következ6 táro16elemnek

143 :

144 : 145 :

150 :

case kIsSmal1er:

151 :

myNext = myNex t->Insert( t heübject) ; rcturn this ;

152 : 153 : 154 : 155 : 156 : 157 :

rcturn thic ;

158 , 159 : /1 A Tail táro l óe l em csa k úrszem szerepet játszik 160 : temp] ate

161:

class TuilNode : public Node

162 :

(

163 :

publ ic :

164 :

TailNode() (l

165 : vir t ual ~TailNode() (j 166 : virtual Node.:T> * Insert(T * theobject) ; 167 : virtual void Show { ) { } 168 : privata : 169 : ); 170: 171 : II Ha az Object tipu!'Iú objektum hozzám kerül, mindenképptm elém 172: II lesz beszúrva, hiszen én vagyok a zár6e1em, aki mOgOtt .. m6.r semmi sincs , 17] : temp1ate 174 , Node ~ Tai1Node :: Insert(T • thCObject) 175 : ( 176 : Interna1Node • ObjectNode ~ 177 : new Interna 1Node(thCObjec t, this) ; 178 : return ObjeCtNOde ; 179 : 180 : 181 : II A kezd6 táro16e1emben n incs ob j e k t um, 182 : II csupán a l i s t a lege1s6 e l emé re mu t a t 183 : t e mplate 18 4 : c l ass HeadNod e : p ub l ic No de 185 : 186 : p ublic : 1 67 : Head Node{) ; 168 : virtual -HeadNode() { d e lete myNext; } 169 : virtual Node .. I nsert {T * t heübject) ; 190 : virtual void Show () ( myNe xt- >Show () ; } 191 : private : 192 : Node * myNe x t ; 193 : }; 194 ,

1477

I

478 VI. rész • KlIlönl.g.sség.k 195 : 1/ Mihelyt létrejön il kezd6 elelll, az nyomban 196 : 1/ maga mögé teszi zár6elemet is

197 : template 198 : HeadNode : : HeadNode (J 199:

(

200 :

myNext '" new TailNode;

201 : 202 : 203 : II A kezd6elem e16tt nincs semmi, igy az objektumot rOgtOn 204 : II továbbadhatjuk a következő táro16clemnek. 205 : template

206 : Node • HeadNode :: Insert(T " theObject) 207 , { 208 :

myNcxt ., myNcxt->Inscrt (thcObject) ;

209 : 210 :

return this ;

211 : 212 : II Minden munkát delegálok, de enyém a

213 : 214 : 215 :

template elauG LinkedLi ot

216 :

public :

217 : 218 :

LinkedList() ;

219 :

void Insert (T " theObject) ;

220: 221 : 222 : 223 : 224 :

void ShowAll() ( myHead->Show() ; private:

~LinkedList()

HeadNode

~

diCsőség

( delete myHead; )

myHead;

);

225: II SzOletésemkor létrehozom a kezd6elemet,

am~ly

226: II helyezi a zár6elemt. 227: II Az Ores lista tehát egy kezd6elemb6l áll . 228 : II záróelem kOvet. kOztOk pedig nincs semmi.

maga mOgé

am~lyct

229: templat~ 230 : LinkedList : : LinkedList() 231 : ( 232 : myHead =: new HeadNode ; 233 : 234 :

235 : /1 Oalogál j . delegálj , delegál j 236 : 237 : 238 : 239 : 240: 241 : 242 : 243 : 244 :

tcmplatc void LinkedList : : Insert( T * pObject) ( myHoad->Inser t (p Object) ;

void rnyFunction(Lin kedList& ListOfCats); void myOtherFunc tion (LinkedList< Data>& ListOfData);

245 : II Tesztprogram 246: 247 : 248 :

int main{) LinkedList

ListOf Cats ;

azonnal a

23. óra • Sablonok 479 249 : 250 :

Lin~edList

251 :

myFunction(Lis t OfCats): myOtherFunction(ListOfData);

252 :

ListOfData ;

253: 254 : 255:

256 : 257 :

256 : 259 : 260 :

II VégignézzOk a listát, és kiírjuk az elemek értékét. std : : cout « "\n" ; ListOfCats . ShowAll(); std : :cout« "\n" ; !>lsLOfData . ShowAll () : std::cout « "\ n *~**~**** .. *. \n\n"; return O; I I A listák kikerOlnek a hat6kOrb6l, és megsel1lllisülnek.

261 : 262 : 263 : void myFunction(LinkedList& ListOfCats) 264 : 265 : Cat • pCa t; 266 : int val; 267 : 268: 1/ A felhasznál6 adjon meg néhány értéket, 269 : II amit II listába teszünk 270: for l;:) 271: 272 :

273 : 274 : 275 : 276 : 211 : 218 : 219: 280: 281: 282 : 283 : 28-t : 285: 286: 287: 288: 289: 290 : 291 :

292 : 293: 294: 295 : 296: 297 : 298 : 299 :

{

std : :cout « " \nHány éves a macskád? (O vége): std: : cin » val; i f (Ivel) break: pCnt .. new Cat(val); ListOfCats . lnsert{pCat);

void myOtherFunction (LinkedT"ist& ListOfData) { Data .. pData ; int val; I I A felhasznál6 adjon meg néhány értéket, /1 amit II listába teszünk f or ( :; ) { std : : cout « 'Adj meg egy értéket (O vége) : ' . std : : cin » val; i f (!val) break ; pData = new Data{val); ListOfData . lnscrt(pData);



I

480 VI. ,ész' Külőnlegességek

Hány éves a macskád? Hány éves a macskád? Hány éves macskád? Hány éves a macskád? Hány éves a macskád?

,

(o (o (o (o (o

vége) v ége) vége) vége)

: 12 : 2 : 14 : 6

váge) : O

meg egy értéket (o vége) : 3 meg egy értékat (o vége) : 9 meg egy értéket 10 vége) : 1 meg egy értéket (o vége) : 5 meg egy értéket (o vége) : O

Adj Adj Adj Adj Adj

E,

a macska 2 évec E, a macska 6 éves

,

Ez macska 12 éves E, a macska 14 é ves LOrlése , melynek értéke : 9 Dat a ob jektum törlése , melynek é r té ke : 5

Da\.a objekt..um

Data objektum tOrlésc , melynek értéke : 3 objektum tOrlése , melynek értéke : 1 14 éves macska tOrlése 12 ével:! macska tOrlése Dl;ltu

6 éves macIJka tOrlése 2 éves macsk", tOrlésc

Ez a példa majdnem ugyanaz, mint az e16z6, azt leszámítva, hogyaLinkedList objeknunokat refcrendával adjuk át az azokal feldolgozó függvényeknek. Ez rendkívül fontos tulajdo nság. Miut:ín a listákat péld,ínyosítotluk, teljesen definiált típusú objckrumokként kezelhet6k: függvény paramétereként és visszmérési 6nékeként.

A szabványos sablon könyvtár A szabványos sablonkönyvtán (Standard Template Library - STL) a C+ + szabvány definiálja. Minden fordító , amelyről azt állílják, hogy szabványos, tartalmazza az STL-l . Az STL sablonnal megvalósílott tárol60sztályok, például tömbök, lisUík, sarok, vermek stb, továbbá számos közös algoritmus, például rcndez(:s, keresés stb. gytijteménye. Az STL célja az, hogy ezeknél a gyakran e l őforduló feladatoknál ne kelljen újra feltalálnunk a spanyolviaszt. Az STI.-t tesztelik és javítják, jó a teljesítménye, és nem utolsósorban ingyenes! Ennél is fontosabb, hogy az STI újrahasznosítható. Mihelyt megtanulluk és megértettük a használatát, minden programunkban alkalmazhatjuk, ahelyett, hogy újra és újra magunk megirnánk.

23.6ra • Sablonol1481 Mindig emlékezzünk rá, hogy a termelékenység és a az újrahasznosítás!

könnyű

karbantarthatóság kulcsa

Kérdések és válaszok Kerdés: Mié11 használjunk sablonl, amikor makróval is mego/dhatunk egyjeladatot? Válasz: A sablon!"... típuscllcn6r..:és vonatkozik, és integrált részét képezi a nyelvnek. Kérdés: Mi ti lu1 lő1lbség a paraméterezltetó jüggwllysabloll és a szokvtillyosjligsvény panl1néterei között? Válasz: Szokványos függvé ny (nem függvénysablon) előre megadott típusú paramétereken végez /Jniveleteket, A függvénysablon ellenben azl is lehet6vé leszi, hogya pammétereket paraméterezhessü k. Kérdés: M/I...'Or hasz náljunk sablol/t, és mikor öröklődést? Válasz: Használjunk s.1.blont akkor, ha a művel etek halmaza azonos, csak az oszclly másmás típusm alkalma zz.1. azokaL Ha azon k:-tpjuk m:lgunkat, hogy kóclot m:'isolunk, és csak egy-két tag típus.1t v:.\ltoztatjuk meg, ideje elgondolkodnunk a s.1.blon haszn:'i.lat1n .

Gyakorlatok A sablonok megismerése után pr6báljuk megv:.\laszolni, illetve megoldani az alábbi kérdéseket és feladatokat, hogy a tárgyban szerzett ismeretek megszilárdulj:mak.

Kvrz 1. Honnan tudja a fordító, hogy nem swkványOl:i osztályt, hanem sablont definiálunk? 2. A 22.1 példában szerepl6 láncoltlista-sablon honnan tudja, hogy az új e lemeket milyen sorrendben kelJ beszúrnia? 3. Hogyan cleklarálunk egy osztálysablonból objektumot, és hogya n jelezzük, milyen osztályt kell ehhez használnia? 4. Honnan tudja a fordító, mikor kell megsemmisítenie a listában tárolt objekmmokat?

482 1VI. rósz' K11lönl'g,ssóg,k

Feladatok 1. HasonlíL'iuk össze a 21.1 (parmlist . cpp) és 19. 1 (linkedlist . cpp) Hstákat! Észre fogjuk venni, hogy milyen sze mbetűnó a hasonlóság. 2. Ellenő rizzük a fordítónk dokumentáci6jában , hogy a szabványos sablonkönyvtár mely osztályai vannak me bJ\la16sítva! Borland fordító esetében, használja a súg6t (Help) a f6 menüben, majd válasszon témakört (Help Topics) és végül a bal oldali ablakban hivatkozást ( Reference)! 3. Hasonlít.'>a össze II 22.1 példa láncolt listájának sablonját a fordító dokumentáci6j{lban szereplő list STL-oszlállya\1 Keresse mcg a hasonlóságokat és a különbségeket!

Válaszok a kvfzkérdésekre l. A fordító a template prefIx miatt tudja , hogy sablont defil1i{llunk. 2. A ké rdéses obje ktumok Compare () metódlls:'\n:lk hívása :1 137. sorban ! :ílh~H6. A függvény é rtelemmel megtöltése a programozók, naz a mi feladatunk (vcgyük szemügyre a 44 . és a 81. sorban kezd6d6 filggvényekeÜ. Ha egy kutyákat rcprczentl'iló osztá lyt is szeretnénk :I listában tárolni, ahhoz is meg kelle ne írnunk az összehasonlító függvényt. 3. Nézzük meg a 22.1 LiSla 247. és 248. sorM A recept a következ(}: oablonnév sablonobjektumnév. 4. Amikor a main függvény visszatér, a láncolt lista elhagyja a l1at6 kört':t, így :IZ osztály destruktor.! lesz végrehajlv.l. Minthogy a táro lt elemeke t a lista dinamikusan hozta létre, a törlésük is a lista feladata. Ezt ot 23:1 Lista 110. soriiban láthatjuk .

24.

ÓRA

Kivételek, hibakezelés és néhány tanács Ebben az órában a következőkrőllesz szó: • Mik azok 1:1 kivételek • Hogyan használjuk a kivételeket, és használatuk milyen kérdéseket vel fe l • Hogyan í~llnk hibátlan kódot • Merre tovább

Programhibák. tévesztések. kódrnegromlás Könyvünk példaprogramjai illuszlrációs céllal születtek. Szándékosan kerültük a hibaforrások taglalását , hogy ne vonja el figyelmünker az éppen tárgyalt témáktóL Az éles programoknak azonban figyelniük kell a hibalehet6ségekrcj sőt, a valódi é l etből veU programkódok legnagyobb részét a hibákra való felkészülés és a hibakezelés teszi ki.

484 1VI. rész • Különlegességek Azt mondják, hogy ha a városok is úgy épülnének, mint a szoftverek, akkor az első arr.:!. járó harkály romba dömené a civilizációl. Mindenesetre tény, hogy szinte minden kereskedelmi program, köztük a legnagyobb gyártók termékei is tartalmaznak hibákat. Komoly programhibákat. Attól még, hogy ezt tudjuk, ez nincs így rendben. Bárkinek, aki komolyan programozásra adja a fejét, elsődleges fontossággal afnt kell törekednie, ho&'Y robusztus, hib;1 nélküli programokat írjon. Állítom, hogya szoftveripar legnagyobb és kiemelked6 problémáját a hibás, inswbil k6dok jelentik. Az mindenesetre tény, hogya program megírásának legkölcségesebb rés7.e a tesztelés, hibakeresés és a hibák kijavítása. Számos olyan apró hiba van, ami gondot okozhat egy progr.lIn futásakor. Az első a rossz logika: a program azt csinálja, amit a progr.HTloz6 szeretne; csakhogy (5 nem gondolta végig dég alaposan II mcgval6sítotl algoritmust. A második II szintaktika: rossz kifejezésm6dot, függvényt vagy struktúrát használtunk. Ez a két leggYllkoribb, és a legtöbb programozó ezek megt:ll~lására törekszik. Sokkal mvaszabbak azok :1 hibák, medyek csak akkor ütköznek ki, amikor a felhasználó valami váratlan dolgot múvel. Ezek a piciny, logikai tapos6aknák csendesen és zavartabnul meglapulhatnak. Amikor már úgy tűnik, minden rendben van, egyszer csak hirtelen - BUMM! - valaki rossz helyre lép, és progr.uTlunk megfeneklik. A kutatások és a gyakorlati tapasztalat egyaránt azt mutatjá k, hogya fejlesztés minél kés6bbi stádiumában kerül el6 egy hiba, annál drágább a kijavítása. A lego1csóbbak azok a problémák és hibák, amelyeket sikerül még a progmm megírásakor elkerülni. Csak alig drágábbak azok, melyeket a fordít6program kidob. A C++ szabvány afra tö· rekszik, hogy .1 fordít6progmmokb61 a lehet6 legtöbb hibajelcntést és fi gyelmeztetést kipréselje (még fordítási időben). A IcfordílOu programoknak azok a hibái sokkal olcsóbbak, amelyek rögtön az e l ső futtatáskor kideriiinek (amelyek mindig összeomlást okoznak), mim amelyek csak nag)' ritkán okoznak problémát. A logikai és szintaktikai hibáknál nagyobb gondot jelentenek az esetleges hibák; amikor például a programunk remekül múködik, ha számol ad meg a felhasznál 6, dc összeomlik, ha belűt ír be, Más progmrnok akkor fagynak le, ha kevésnek bizonyul a mem6ria, vagy ha kint felejtettilk a hajlékonyJemezl, esetleg ha a modem éppen bontja a vonalaI. A programozók az effajta törékenység ellen úgy küzdenek, hogy próbálják programjukat ~golyóállóvá ~ tenni. Golyóá1l6 az a progmm, amely minden futásidóben elképzelhet6 esetre fel van készítve, kezdve a bizarr felhasználói bemeneuől egészen a memóriahiányig. Ez a fajta programozás hasonlít a "defenzív vezelésre~, amely abból áll, hogy nem bízunk a másik sofőr (esetünkben felhasznál6 vagy rendszer) udvariasság:i-

_ __

_

_ _ _ _ _ _ _ _ _ _"'24"-"",6ra,,-0-"Kiv ..é...'."""I....~,.h""ib..,.k"eze=lé... s .., és"n..,éh..,é...nyL'...an...' ... csCJ

I,,48"''s--__--"""

ban, hanem azt feltételezzük, hogy bármilyen meglepá esemény is megtönénhet. Ha azonban elórelál6ak vagyunk és felkészülünk az effajta dolgokra, akkor elkerülhető az összeütközés. Fontos különbséget tenni, a progrdmhibák közön. Vannak ol}"dnok, amelyek abból adódnak, hogy a programozó szintaktikai hibát vételt. Vannak logikai hibák, amelyek onnan erednek, hogy a programozó félreértette a feladatot vagy a megoldás módját. Végül vannak olyan kivételek, melyek szokatlan (ám nem megjósolhatatlan) események miatt lépnek föl, mint például az erőforrások (memória vagy merevlemezhc\y) hiánya.

Váratlan események kezelése A programozók hatékony fordít6progr.lmoka t haszn:ílnak, és külö n böző biztosítékokka l rakják tele a kódot, amely Icbct6vé teszi a programozási hibák felfedezését. Újra és újra áuekintik a tervet, 6s kimcrít6 tesztelést folytaUlak, hogy megtaláljlik a logikai hibákat A kivételek azonb:m más jelleguek. A kivételes körülményeket nem lehet teljesen kiküszöbölni, csak felk(!szülni lehet clJuk, Felhasználóink számítógépein id6nként belelik amemória; ilyer,kor az il kérdi!s, hogy mit csináljon a program. Az alábbi lehet6ségek közül lehet váJaszt:mi: • Hagyjuk összeomlani a programot • Jelezzük a helyzetet il relhasználónak, és elegánsan lépünk ki • Jelezzük a helyzetet a relhasználónak, és lehetővé tesszük s7Jlmára, hogy megkísérclje a helyreállításI éS a folytatást • A progrnm maga javítja a problémáI, és tovább fut a felhasználó megzavarása nélkül Nem muszáj, S61 nem is kívánatos, hogy minden programunk automatikusan (!5 csendben maga küszö\)öljön ki minden váratlan helyzetet, az azonba n nyilvánvaló, hogy többet kell tennünk, mint hogy hagyjuk csak (Igy összeomlani a programot. A CH kivételkezelés típusbiztos és szervesen beépülő módszert biztosít arra, hogy megbirkózzunk a program fu tása közben fell épő ritka, de megjósolható eseményekkel.

Kivételek A C++ nyelvben a kivétel egy olyan objektum, amely a kód egyik részér61 a másikra adódik ál: a hibát kiváltó reszr61 a lubát kezelő részre. Amikor bekövetkezik a kivételes esemény, akkor azt mondjuk, hogy a program .továbbdobon egy kivételtH; a kivétel kezelését pedig .a kivétel elkapásának mondjuk. H

486 1VI. rész· Különlegességek A kivétel típusa dönti el, hogy melyik kódrészlet fogja kezelni a problémát; a továbbdobott objektum tartalma (ha van), visszajelzést nyújthat a fdh