HOÏ C VIEÄ N COÂ NG NGHEÄ BÖU CHÍ NH VIEÃ N THOÂ NG
CÔ SÔÛ TAÏ I TP. HOÀ CHÍ MINH
Baø i
giaûng:
LAÄP TRÌNH
HÖÔÙ NG ÑOÁ I TÖÔÏ NG
Taø i lieä u duø ng cho heä Ñaï i hoï c
ngaø nh Coâ ng ngheä thoâ ng tin & Ñieä n töû – Vieã n thoâ ng
ñaõ ñöôï c Hoä i ñoà ng khoa hoï c Khoa Coâ ng ngheä thoâ ng tin 2
thoâ ng qua ngaø y 16/1/2002
(Taäp 1)
Bieân soaïn:
Th.S. NGUYEÃ N VIEÄ T CÖÔØ NG
LÖU HAØ NH NOÄ I BOÄ
Tp. Hoà Chí Minh – Naê m 2002
ii
Lôøi noùi ñaàu
Baøi giaûng ñöôïc bieân soaïn döïa treân caùc taøi lieäu cuûa Herbert Schildt vaø Bjarne
Stroustrup do coù tính sö phaïm cao vaø döïa treân moät soá taøi lieäu khaùc.
Noäi dung baøi giaûng coù 12 chöông, giôùi thieäu caùc khaùi nieäm caên baûn, caùc neàn taûng
cuûa laäp trình höôùng ñoái töôïng (Object-Oriented Programming) bao goàm :
•
tính ñoùng goùi (Encapsulation)
•
tính keá thöøa (Inheritance)
•
tính ña hình (Polymorphism)
•
quaù taûi haøm vaø toaùn töû (Function & Operator Overloading)
•
template vaø ñieàu khieån ngoaïi leä (Exception Handling)
•
vaán ñeà phaùt trieån heä thoáng höôùng ñoái töôïng
•
minh hoïa moät soá öùng duïng cuûa laäp trình höôùng ñoái töôïng vôùi C++ trong moâi
tröôøng DOS vaø Windows.
Ngoân ngöõ laäp trình C++ ñöôïc söû duïng trong baøi giaûng nhaèm minh hoïa caùc yù töôûng
cuûa laäp trình höôùng ñoái töôïng, do ñoù caùc kieán thöùc veà C++ ñöôïc trình baøy ñan xen
trong moät soá chöông giuùp sinh vieân deã daøng lónh hoäi caùc khaùi nieäm khaù tröøu töôïng
cuûa laäp trình höôùng ñoái töôïng.
Baøi giaûng khoâng coù tham voïng ñi saâu moïi khía caïnh cuûa laäp trình höôùng ñoái töôïng,
chæ trình baøy caùc kieán thöùc caên baûn vaø qua caùc ví duï minh hoïa hy voïng seõ giuùp ích
cho sinh vieân ngaønh coâng ngheä thoâng tin vaø ñieän töû vieãn thoâng böôùc ñaàu tìm hieåu theá
giôùi laäp trình.
Caùc ví duï minh hoïa ñaõ chaïy toát treân caùc trình bieân dòch Borland C++ 4.5 hoaëc Visual
C++ 6.0
Baøi giaûng ñöôïc phaân laøm hai taäp, taäp 1 töø chöông 1 ñeán chöông 8, taäp 2 töø chöông 9
ñeán chöông 12.
Raát mong caùc ñoàng nghieäp vaø caùc sinh vieân ñoùng goùp yù kieán xaây döïng ñeå baøi giaûng
ñöôïc hoaøn thieän hôn trong caùc laàn soaïn thaûo veà sau.
Thaùng 8 naêm 2001
Th. S. Nguyeãn Vieät Cöôøng
E-mail: nvc@ptithcm.edu.vn
iii
Muïc luïc
Taäp 1
Chöông 1
Toång quan veà Laäp trình höôùng ñoái töôïng
I. Vaøi neùt veà söï phaùt trieån cuûa caùc ngoân ngöõ laäp trình............................1
II. Caùc khaùi nieäm cô baûn cuûa laäp trình höôùng ñoái töôïng ..........................4
1.
Lôùp vaø Ñoái töôïng (Class & Object).........................................4
2.
Thoâng baùo (Message)...............................................................5
3.
Tính ñoùng goùi (Encapsulation) .................................................5
4.
Tính keá thöøa (Inheritance)........................................................6
5.
Tính ña hình (Polymorphism)...................................................7
III. Toång quan veà ngoân ngöõ laäp trình höôùng ñoái töôïng C++ .....................7
1.
Xuaát/Nhaäp (Console I/O) .........................................................7
2.
Chuù thích (Comment) .............................................................10
3.
Khaùi nieäm veà quaù taûi haøm (Function Overloading)................11
4.
Caùc töø khoaù (Keywords) trong C++........................................14
Chöông 2
Lôùp, Ñoái töôïng vaø Tính ñoùng goùi.................................
15
I. Lôùp .................................................................................................17
II. Haøm taïo, haøm huûy ..........................................................................22
III. Tham soá cuûa haøm taïo .....................................................................30
IV. Noäi tuyeán töï ñoäng ..........................................................................37
V. Gaùn ñoái töôïng .................................................................................39
VI. Truyeàn caùc ñoái töôïng sang haøm......................................................45
VII. Traû ñoái töôïng töø haøm ......................................................................53
VIII. Haøm friend......................................................................................56
IX. Baøi taäp chöông 2 .............................................................................62
Chöông 3
Maûng , Con troû vaø Tham chieáu
.......................................67
I. Maûng caùc ñoái töôïng ........................................................................69
II. Con troû ñoái töôïng ............................................................................72
iv
III. Con troû this......................................................................................75
IV. Toaùn töû new vaø delete ....................................................................78
V. Tham chieáu (reference) ..................................................................86
VI. Truyeàn tham chieáu cho ñoái töôïng ...................................................91
VII. Traû veà caùc tham chieáu.....................................................................95
VIII. Caùc tham chieáu ñoäc laäp vaø caùc haïn cheá..........................................98
IX. Baøi taäp chöông 3 ...........................................................................100
Chöông 4
Quaù taûi haøm
.....................................................................103
I. Quaù taûi haøm taïo ...............................................................................105
II. Haøm taïo baûn sao ..............................................................................109
III. Söû duïng caùc ñoái soá maëc ñònh (default argument) ...........................119
IV. Söï quaù taïi vaø tính khoâng xaùc ñònh (ambiguity)................................126
V. Ñiaï chæ cuûa haøm quaù taûi...................................................................130
VI. Baøi taäp chöông 4..............................................................................132
Chöông 5
Quaù taûi toaùn töû
.................................................................135
I. Quaù taûi toaùn töû ................................................................................137
II. Quaù taûi toaùn töû nhò nguyeân ..............................................................138
III. Quaù taûi toaùn töû quan heä & luaän lyù ...................................................144
IV. Quaù taûi toaùn töû ñôn nguyeân .............................................................146
V. Haøm toaùn töû friend...........................................................................149
VI. Toaùn töû gaùn......................................................................................155
VII. Baøi taäp chöông 5..............................................................................158
Chöông 6
Tính keá thöøa
...................................................................163
I. Giôùi thieäu tính keá thöøa.....................................................................165
II. Ñieàu khieån truy caäp lôùp cô sôû..........................................................171
III. Söû duïng caùc thaønh vieân ñöôïc baûo veä ...............................................176
IV. Haøm taïo, haøm huûy vaø tính keá thöøa ..................................................181
V. Tính ña keá thöøa................................................................................189
VI. Lôùp cô sôû aûo.....................................................................................196
VII. Baøi taäp chöông 6..............................................................................201
v
Chöông 7
Heä thoáng Nhaäp/Xuaát C++
............................................. 207
I. Cô sôû Nhaäp/Xuaát C++ ..................................................................... 209
II. Nhaäp/Xuaát coù ñònh daïng.................................................................. 210
III. Söû duïng width(), precision() vaø fill()............................................... 218
IV. Söû duïng boä thao taùc Nhaäp/Xuaát....................................................... 220
V. Taïo boä cheøn..................................................................................... 223
VI. Taïo boä chieát..................................................................................... 230
VII. Baøi taäp chöông 7.............................................................................. 234
Chöông 8
Nhaäp/Xuaát C++ naâng cao
.............................................. 237
I. Taïo Boä thao taùc Nhaäp/Xuaát............................................................. 239
II. Nhaäp/Xuaát File................................................................................ 243
III. Nhaäp/Xuaát File nhò phaân khoâng ñònh daïng ..................................... 251
IV. Caùc haøm Nhaäp/Xuaát nhò phaân ......................................................... 258
V. Truy caäp ngaãu nhieân........................................................................ 261
VI. Kieåm tra traïng thaùi Nhaäp/Xuaát........................................................ 265
VII. Nhaäp/Xuaát theo ñôn ñaët haøng vaø caùc File....................................... 269
VIII. Nhaäp/Xuaát theo maûng ..................................................................... 272
IX. Baøi taäp chöông 8.............................................................................. 277
Taäp 2
Chöông 9
Tính ña hình
.................................................................... 281
I. Con troû vaø Lôùp daãn xuaát ................................................................ 283
II. Daãn nhaäp caùc haøm aûo ...................................................................... 285
III. Caùc haøm aûo thuaàn tuùy...................................................................... 295
IV. AÙp duïng ña hình .............................................................................. 299
V. Baøi taäp chöông 9.............................................................................. 309
Chöông 10
Template vaø ñieàu khieån ngoaïi leä
................................. 311
I. Haøm template.................................................................................. 313
II. Lôùp template ................................................................................... 319
vi
III. Ñieàu khieån ngoaïi leä .........................................................................326
IV. Bieán tónh ..........................................................................................339
V. Töø khoaù extern vaø asm ....................................................................344
VI. Haøm chuyeån kieåu.............................................................................346
VII. Nhöõng khaùc bieät giöõa C vaø C++ ......................................................349
VIII. Baøi taäp chöông 10............................................................................350
Chöông 11
Phaùt trieån caùc heä thoáng höôùng ñoái töôïng
......................351
I. Giôùi thieäu.........................................................................................353
II. Caùc moâ hình höôùng-thuû tuïc..............................................................354
III. Caùc coâng cuï phaùt trieån höôùng-thuû tuïc..............................................357
IV. Moâ hình höôùng ñoái töôïng.................................................................359
V. Caùc kyù hieäu vaø ñoà thò höôùng ñoái töôïng............................................361
VI. Caùc böôùc phaân tích höôùng ñoái töôïng ...............................................365
VII. Caùc böôùc thieát keá höôùng ñoái töôïng..................................................371
VIII. Caøi ñaët .............................................................................................378
IX. Moâ hình nguyeân maãu.......................................................................379
X. Toùm taét ............................................................................................380
XI. Baøi taäp chöông 11............................................................................381
Chöông 12
Moät soá öùng duïng OOP
....................................................383
I. ÖÙùng duïng treân moâi tröôøng DOS.......................................................385
1.
Sorted container example source file...................................385
2.
Text cross referencing example .........................................389
3.
Updates and displays the contents of a mailing list..............398
II. ÖÙùng duïng treân moâi tröôøng WINDOWS ...........................................411
1.
Instructions for the IDE example MULTITRG.IDE.............411
2.
Common Dialogs example in C............................................419
3.
Demo True Type fonts..........................................................427
4.
Demo sound APIs ................................................................447
5.
Creating a window application (TODO) ..............................456
III. Ñoà aùn moân hoïc.................................................................................479
vii
Taøi lieäu tham khaûo
Saùch giaùo khoa
[1] Bjarne Stroustrup,
What is
“Object-Oriented Programming” ?
AT&T Bell Lab., 1991 (revised version), p1-21
[2] Menachem Bazian,
Fundamentals of Object-Oriented Programming
,
Microsoft Corp., 1995.
[3] Herbert Schildt,
Teach Yourself C++, 3rd Edition,
McGraw-Hill,
1997.
[4] H. M. Deitel & P. J. Deitel
C++ How to Program, 2
nd
edition,
Prentice Hall, 1998
[5] E. Balagurusamy,
Object-Oriented Programming with C++,
Tata McGraw-Hill, 1997.
Saùch tham khaûo
[6] Herbert Schildt,
C++ Nuts & Bolt : for Experienced Programmers
,
McGraw-Hill,
1997.
[7] Herbert Schildt,
C/C++ Programmer's Reference
,
McGraw-Hill,
1997.
viii
[8] Bjarne Stroustrup,
The C++ Programming Language, (3
rd
Edition)
Addison-Wesley,
1997
[9] Bjarne Stroustrup,
Why C++ is not just an Object-Oriented Programming Language,
AT&T Bell Lab., Murray Hill, New Jersay, 1995 , 13 pages
[10] Bjarne Stroustrup,
An Overview of the C++ Programming Language
The Handbook of Object Technology, CRC Press LLC,
Boca Raton, 1999, 23 pages
[11] Bjarne Stroustrup,
Learning Standard C++ as a New Language
,
AT&T Bell Lab., 1999, 11 pages
[12] Jeri R. Hanly,
Essential C++ for Engineers and Scientists
,
Addison-Wesley,
1997
[13] Mark A. Terrible,
Practical C++
,
McGraw-Hill,
1994.
[14] Gordon Dodrill,
C++ Tutorial
,
Coronado Enterprises, 1994.
[15] IEEE Computer,
“Open Channel” Interview with Bjarne Stroustrup
,
IEEE,
1998.
[16] C. Thomas Wu,
An Introduction to Object-Oriented Programming with JAVA
,
McGraw-Hill,
1999.
[17] Borland International, Inc.
Borland C++, version 4.5, 1994.
Chöông 1
Toång quan veà
laäp trình höôùng ñoái töôïng
Vaøi neùt veà söï phaùt trieån cuûa caùc ngoân ngöõ laäp trình
Caùc khaùi nieäm cô baûn cuûa laäp trình höôùng ñoái töôïng
•
Lôùp vaø Ñoái töôïng (Class & Object)
•
Thoâng baùo (Message)
•
Tính ñoùng goùi (Encapsulation)
•
Tính keá thöøa (Inheritance)
•
Tính ña hình (Polymorphism)
Toång quan veà ngoân ngöõ laäp trình höôùng ñoái töôïng C++
•
Xuaát/Nhaäp (Console I/O)
•
Chuù thích (Comment)
•
Khaùi nieäm veà quaù taûi haøm (Function Overloading)
•
Caùc töø khoaù (Keywords)
Chöông 1 Toång quan veà Laäp trình höôùng ñoái töôïng
2
Chöông 1 Toång quan veà Laäp trình höôùng ñoái töôïng
3
I/ Vaøi neùt veà söï phaùt trieån cuûa caùc ngoân ngöõ laäp trình
Ngoân ngöõ laäp trình phaùt trieån qua hai lyù do :
(1) ñeå thích öùng vôùi söï phaùt trieån cuûa moâi tröôøng (caùc heä maùy tính, caùc maïng).
(2) boå sung toát hôn cho caùc phöông phaùp laäp trình.
•
Vaøo thaäp nieân 1940, chieác maùy tính ñieän töû ñaàu tieân ENIAC I (Electronic
Numerical Integrator and Calculator
) ñöôïc cheá taïo taïi ÑH Pennsylvania, USA,
bôûi nhoùm John W. Mauchly vaø J. Presper Eckert. Caùc chöông trình (program)
luùc ñoù ñöôïc laäp ra baèng caùc quaù trình ñoùng môû caùc coâng taéc treân moät baûng ñaët
tröôùc maùy tính. Ngoân ngöõ maùy (Machine language) vôùi nhöõng chuoåi nhò phaân
0,1,... coù ñoä daøi qui öôùc chæ thích hôïp vôùi caùc chöông trình nhoû nhaát.
•
Sau ñoù John von Neumann (ÑH Princeton, USA) ñaõ ñeà xuaát khaùi nieäm chöông
trình löu tröõ
trong boä nhôù maùy tính, yù töôûng naøy khoâng nhöõng caûi tieán toác ñoä tính
toaùn cuûa maùy tính luùc ñoù maø coøn gôïi ra nhöõng phöông phaùp linh hoaït ñeå vieát caùc
chöông trình trong töông lai. Hôïp ngöõ (Assembly language) ñöôïc taïo ra cho pheùp
vieát caùc chöông trình daøi hôn.
•
Cuoái thaäp nieân 1950 vaø ñaàu thaäp nieân 1960, caùc ngoân ngöõ caáp cao ñaõ ra ñôøi nhö
FORTRAN (FORmula TRANslator) duøng cho caùc tính toaùn veà toaùn hoïc vaø
COBOL (COmmon Business Oriented Language) duøng trong lónh vöïc thöông
maïi. Ngoân ngöõ BASIC (Beginners All-purpose Symbolic Instructional Code)
ñöôïc phaùt trieån laàn ñaàu tieân treân caùc maùy vi tính (micro-computer) nhaèm giuùp
caùc sinh vieân deã hoïc vaø tieáp caän vôùi caùc chöông trình maùy tính.
Caùc ngoân ngöõ laäp trình coù caáu truùc nhö ALGOL vaø PASCAL ra ñôøi giuùp loaïi boû
caùc nhöôïc ñieåm nhö roái loaïn maõ khoù quaûn lyù khi soá leänh trong chöông trình daøi
haøng ngaøn doøng.
•
Ñaàu thaäp nieân 1970 ngoân ngöõ C (do Denis Ritchie) ñöôïc ra ñôøi taïi AT&T Bell
Labs, USA. Ngoân ngöõ C toång hôïp caùc söùc maïnh cuûa caùc ngoân ngöõ laäp trình caáu
truùc khaùc, deå hieåu, deå hoïc vaø trôû neân phoå bieán vôùi moïi ngöôøi. Thaùng 12/1989,
ngoân ngöõ C ñöôïc ANSI (American National Standards Insitute) chuaån hoaù vaø
thoâng qua.
Chöông 1 Toång quan veà Laäp trình höôùng ñoái töôïng
4
•
Laäp trình coù caáu truùc (hay coøn goïi laø laäp trình thuû tuïc)
döïa vaøo caùc caáu truùc ñieàu
khieån (for, while, do, if, ...) ñaõ ñöôïc ñònh nghiaõ, caùc khoái maõ leänh, ít duøng leänh
GOTO, caùc chöông trình con hoã trôï pheùp ñeä qui vaø caùc bieán cuïc boä.
Main program
Function 1
Function 2
Function 3
Function
4
Function
5
Function 6
Function 7
Function 8
Hình 1.1
Caùc chöông trình höôùng-thuû tuïc (laäp trình caáu truùc)
Moät chöông trình lôùn ñöôïc chia thaønh nhieàu chöông trình con cho nhieàu nhoùm laäp
trình khaùc nhau cuøng laøm vieäc, vôùi soá doøng leänh ñeán vaøi chuïc ngaøn doøng, giuùp deã
daøng baûo trì vaø phaùt trieån phaàn meàm.
Global
Data
Global
Data
Function-1
Function-2
Function-3
Local Data
Local Data
Local Data
Hình 1.2
Quan heä giöõa döõ lieäu vaø haøm trong laäp trình höôùng-thuû tuïc
•
Ñaàu thaäp nieân 1980, ngoân ngöõ C++ (döïa treân ngoân ngöõ C, Bjarne Stroustrup
giôùi thieäu
) vaø ngoân ngöõ Smalltalk (Xerox PARK) ñöôïc phaùt trieån nhaèm hoå trôï
cho phöông phaùp laäp trình höôùng ñoái töôïng (Object Oriented Programming),
phöông phaùp naøy ñaõ ñöôïc ñeà xuaát töø cuoái thaäp nieân 1960 vôùi ngoân ngöõ Simula.
C++ ñöôïc chuaån hoaù vaøo thaùng 11/1997 vaø moät chuaån ANSI/ISO ñaõ coâng boá.
Chöông 1 Toång quan veà Laäp trình höôùng ñoái töôïng
5
Laäp trình höôùng ñoái töôïng söû duïng C++ taïo neân söï bieán ñoåi saâu saéc, giuùp laäp
trình vieân coù theå quaûn lyù nhöõng chöông trình lôùn vaø phöùc taïp (hôn 100.000 doøng
leänh).
•
Thaäp nieân 1990, vôùi söï phaùt trieån maïnh meõ cuûa maïng World Wide Web, moät
cuoäc caùch maïng môùi trong kyõ thuaät laäp trình ñaõ xaûy ra. Ngoân ngöõ JAVA do
James Gosling, Patrick Naughton, Christ Warth, vaø Mike Sheridan phaùt trieån taïi
haõng Sun Microsystem. Teân chính thöùc ñöôïc coâng boá vaøo naêm 1995.
•
JAVA laø ngoân ngöõ laäp trình höôùng ñoái töôïng khoâng phuï thuoäc vaøo thieát bò (caùc
boä vi xöû lyù, heä ñieàu haønh, maïng, ...). JAVA ñöôïc thieát keá khoâng phaûi ñeå thay
theá C++, maø ñeå giaûi quyeát nhöõng vaán ñeà ñang ñaët ra cho neàn coâng ngheä tin hoïc.
•
Phöông phaùp laäp trình höôùng ñoái töôïng
cho pheùp phaân chia moät baøi toaùn thaønh
caùc nhoùm nhoû coù quan heä vôùi nhau. Moãi nhoùm laø moät ñoái töôïng chöùa caùc leänh vaø
döõ lieäu rieâng cuûa noù coù quan heä vôùi ñoái töôïng ñoù
.
Nhôø ñoù, tính phöùc taïp cuûa chöông trình ñöôïc giaûm xuoáng, ngöôøi laäp trình coù theå
quaûn lyù nhöõng chöông trình raát lôùn, chaúng haïn heä ñieàu haønh Windows vaø nhöõng
chöông trình öùng duïng treân ñoù laø nhöõng minh chöùng cho phöông phaùp naøy.
Object A
Object B
Data
Data
Functions
Functions
Object
C
Functions
Data
Hình 1.3
Toå chöùc cuûa döõ lieäu vaø caùc phöông thöùc trong laäp trình höôùng-ñoái töôïng
Caùc ñaëc tính quan troïng trong laäp trình höôùng ñoái töôïng :
Chöông 1 Toång quan veà Laäp trình höôùng ñoái töôïng
6
•
Tính ñoùng goùi (Encapsulation)
•
Tính keá thöøa (Inheritance)
•
Tính ña hình (Polymorphism)
II/ Caùc khaùi nieäm cô baûn cuûa laäp trình höôùng ñoái töôïng
1/ Lôùp (Class) vaø Ñoái töôïng (Object)
Caùc ñoái töôïng laø caùc thöïc theå (entities) cô sôû khi chaïy chöông trình (run-time) trong
moät heä thoáng höôùng ñoái töôïng
.
Chuùng coù theå bieåu dieãn moät con ngöôøi, moät vò trí, moät taøi khoaûn ngaân haøng, moät
baûng döõ lieäu hoaëc baát kyø moät ñeà muïc (item) naøo maø chöông trình caàn duøng ñeå thöïc
hieän caùc taùc vuï (tasks).
Object : SINHVIEN
SINHVIEN
DATA
Teân
Nhaäp()
Ngaøy sinh
Ñieåm
....
TrungBình()
FUNCTIONS
Nhaäp()
TrungBình()
HieånThò()
HieånThò()
(a)
(b)
Hình 1.4 Hai caùch bieåu dieãn moät ñoái töôïng
Beân trong moät chöông trình coù theå vieát caùc doøng leänh (instructions) ñeå taïo ra caùc ñoái
töôïng. Ñeå maùy tính coù theå taïo ra ñoái töôïng, chuùng ta caàn phaûi cung caáp moät ñònh
nghiaõ, goïi laø lôùp.
Lôùp laø moät daïng khuoân (mould , template) qua ñoù chöông trình maùy tính duøng ñeå taïo
ra caùc ñoái töôïng.
Moät ñoái töôïng ñöôïc goïi laø moät theå hieän (instance) cuûa moät lôùp. Moät ñoái töôïng laø moät
theå hieän chính xaùc
cuûa moät lôùp.
Khi ñònh nghiaõ moät lôùp, coøn ñöôïc xem laø taïo ra moät kieåu döõ lieäu môùi töø ngöôøi duøng.
Chöông 1 Toång quan veà Laäp trình höôùng ñoái töôïng
7
Khi khai baùo moät ñoái töôïng, coù nghiaõ laø taïo ra moät bieán coù kieåu döõ lieäu laø moät lôùp.
Caùc thaønh vieân (members) cuûa moät lôùp bao goàm döõ lieäu (data) vaø caùc haøm hay
phöông thöùc (function, method)
Nguyeân
SINHVIEN
Hanh
Class
Instances
Objects
Hình 1.5
Lôùp SINHVIEN vaø 2 ñoái töôïng Nguyeân & Hanh
2/ Thoâng baùo (Message)
Ñeå yeâu caàu moät ñoái töôïng thöïc thi moät taùc vuï, caàn gôûi moät thoâng baùo ñeán noù.
Chaúng haïn, chuùng ta gôûi moät thoâng baùo new ñeán lôùp SINHVIEN ñeå taïo ra moät theå
hieän (moät ñoái töôïng SINHVIEN), sau ñoù gôûi moät thoâng baùo Nhaäp() ñeán ñoái töôïng
cuûa lôùp SINHVIEN ñeå nhaäp caùc döõ lieäu veà sinh vieân.
3/ Tính ñoùng goùi (Encapsulation)
Vieäc toå chöùc döõ lieäu (data) vaø caùc haøm (function) hay phöông thöùc (method) trong
moät ñôn vò duy nhaát (goïi laø lôùp) ñöôïc xem laø tính chaát ñoùng goùi.
Ñoùng goùi döõ lieäu
(Data Encapsulation) laø moät trong nhöõng ñaëc tính noåi baät cuûa moät
lôùp. Döõ lieäu khoâng theå truy xuaát ñöôïc ôû beân ngoaøi lôùp vaø chæ nhöõng phöông thöùc beân
trong lôùp ñoù môùi coù theå truy xuaát ñöôïc chuùng.
Trong moät ñoái töôïng, döõ lieäu vaø haøm hoaëc caû hai coù theå laø rieâng cuûa ñoái töôïng ñoù
hoaëc chung.
SINHVIEN
SINHVIEN
Chöông 1 Toång quan veà Laäp trình höôùng ñoái töôïng
8
Döõ lieäu vaø haøm rieâng laø thuoäc veà ñoái töôïng ñoù vaø chæ ñöôïc truy caäp bôûi caùc thaønh
phaàn beân trong cuûa ñoái töôïng.
Vôùi döõ lieäu vaø haøm chung, caùc boä phaän khaùc cuûa chöông trình coù theå truy caäp ñeán
chuùng.
Nhöõng chöùc naêng naøy cung caáp moät giao tieáp giöõa döõ lieäu cuûa ñoái töôïng vaø chöông
trình. Söï caùch ly naøy cuûa döõ lieäu töø vieäc truy xuaát tröïc tieáp bôûi chöông trình ñöôïc goïi
laø söï che daáu döõ lieäu (data hiding)
4/ Tính keá thöøa (Inheritance)
Tính keá thöøa laø quaù trình moät ñoái töôïng coù theå coù ñöôïc caùc tính chaát cuûa moät ñoái
töôïng khaùc
. Nghiaõ laø, moät ñoái töôïng coù theå keá thöøa caùc tính chaát toång quaùt ñeå boå
sung theâm caùc ñaëc ñieåm cuûa noù.
Tính keá thöøa hoå trôï khaùi nieäm phaân loaïi theo thöù baäc (hierarchical classification) ,
ñoùng vai troø quan troïng trong laäp trình höôùng ñoái töôïng.
Hình 1.6
Heä thoáng thöù baäc keá thöøa (ñôn giaûn) trong Hoïc vieän
Lôùp cô sôû (base class)
: “Hoïc Vieän Coâng ngheä Böu Chính –Vieãn Thoâng”
Lôùp daãn xuaát (derived class) : “Khoái Sinh vieân” ,
“Khoái
Giaùo
vieân”
,
“Khoái
Nhaân
vieân”
5/ Tính ña hình (Polymorphism)
Hoïc Vieän Coâng ngheä Böu Chính –Vieãn Thoâng
Khoái Sinh vieân
Khoái Giaùo vieân
Khoái Nhaân vieân
Chöông 1 Toång quan veà Laäp trình höôùng ñoái töôïng
9
Tính ña hình laø tính chaát cho pheùp moät teân (ñoái töôïng, haøm, toaùn töû) ñöôïc duøng cho
hai hay nhieàu muïc ñích khaùc nhau coù quan heä veà phöông dieän kyõ thuaät
.
Tính ña hình cho pheùp thöïc hieän quaù taûi haøm (function overloading) hay quaù taûi toaùn
töû
(operator overloading)
Tính ña hình theå hieän yù töôûng "moät giao dieän cho nhieàu phöông thöùc".
III/ Toång quan veà ngoân ngöõ laäp trình höôùng ñoái töôïng C++
Do C++ ñöôïc xaây döïng töø ngoân ngöõ C vôùi lôùp, neân moïi phaàn töû cuûa C ñeàu ñöôïc chöùa
trong C++ .
Caùc haøm caên baûn cuûa C++ ñeàu chöùa trong thö vieän iostream.h
1/ Xuaát/Nhaäp trong C++ (Console I/O)
Töø khoaù cout, cin laø caùc stream ñöôïc ñònh nghiaõ tröôùc trong iostream.h, töï ñoäng lieân
keát vôùi console khi chöông trình C++ baét ñaàu chaïy.
cout
töông ñöông vôùi stdout, vaø cin töông ñöông vôùi stdin trong ngoân ngöõ C.
Cuù phaùp
cout <<
expression ;
// xuaát noäi dung cuûa bieåu thöùc ra maøn hình
cin >>
variable ;
// nhaäp moät giaù trò töø baøn phím vaøo bieán variable
vôùi <<
toaùn töû xuaát
>>
toaùn töû nhaäp
expression
bieåu thöùc C++ baát kyø
variable
bieán
Ví duï 1.1
Chöông 1 Toång quan veà Laäp trình höôùng ñoái töôïng
10
#include <iostream.h>
int main()
{
int i = 10, j = 20;
double d = 99.101;
cout << "Here are some values: ";
cout << i;
cout << ' ';
cout << j;
cout << ' ';
cout << d;
return 0;
}
Ví duï 1.2
Xuaát nhieàu hôn moät giaù trò trong moät bieåu thöùc nhaäp/xuaát ñôn
#include <iostream.h>
int main()
{
int i, j;
double d;
i = 10;
j = 20;
d = 99.101;
cout << "Here are some values: ";
cout << i << ' ' << j << ' ' << d;
return 0;
}
Ví duï 1.3
Khi nhaäp, caùc muïc rieâng leû phaûi caùch nhau khoaûng traéng.
Vôùi chuoåi, toaùn töû nhaäp seõ ngöøng khi gaëp kyù töï khoaûng traéng ñaàu tieân.
#include <iostream.h>
Chöông 1 Toång quan veà Laäp trình höôùng ñoái töôïng
11
int main()
{
int i; float f; char s[80];
cout << "Enter an integer, float, and string: ";
cin >> i >> f >> s;
cout << "Here's your data: ";
cout << i << ' ' << f << ' ' << s;
return 0;
}
Ví duï 1.4
Vôùi toaùn töû nhaäp >> , moïi döõ lieäu nhaäp ñöôïc ñöa vaøo boä ñeäm (buffer)
cho ñeán khi nhaán phím ENTER.
#include <iostream.h>
int main()
{
char ch;
cout << "Enter keys, x to stop.\n";
do {
cout << " : ";
cin >> ch;
} while (ch != 'x');
return 0;
}
2/ Chuù thích (comment) trong C++
•
Chuù thích moät doøng leänh
// ...
Ví duï 1.5
Xaùc ñònh moät soá nguyeân laø soá chaün hay leû
Chöông 1 Toång quan veà Laäp trình höôùng ñoái töôïng
12
#include <iostream.h>
int main()
{
int num; // this is a C++, single-line comment
// read the number
cout << "Enter number to be tested: ";
cin >> num;
// see if even or odd
if((num%2)==0) cout << "Number is even\n";
else cout << "Number is odd\n";
return 0;
}
•
Chuù thích nhieàu doøng leänh
/* ... */
Ví duï 1.6
/* This is a multiline comment
inside of which // is nested a single-line comment.
Here is the end of the multiline comment.
*/
3/ Khaùi nieäm veà quaù taûi haøm (Function Overloading)
Hai hoaëc nhieàu haøm duøng chung moät teân. Coù 3 loaïi :
•
Cuøng soá ñoái soá
•
Khaùc soá ñoái soá
•
Khaùc soá ñoái soá vaø khaùc kieåu döõ lieäu
Muïc ñích :
•
giuùp giaûm bôùt tính phöùc taïp cuûa chöông trình baèng caùch cho pheùp caùc pheùp toaùn
coù lieân heä ñöôïc tham chieáu cuøng moät teân.
Chöông 1 Toång quan veà Laäp trình höôùng ñoái töôïng
13
•
ñaït ñöôïc tính ña daïng thôøi gian bieân dòch.
Ví duï 1.7
Cuøng soá ñoái soá.
Trình bieân dòch seõ choïn phieân baûn thích hôïp cuûa haøm ñeå goïi.
#include <iostream.h>
// Overload abs() three ways
int abs(int n) ;
long abs(long n) ;
double abs(double n) ;
int main()
{
cout << "Absolute value of -10: " << abs(-10) << "\n\n";
cout << "Absolute value of -10L: " << abs(-10L) << "\n\n";
cout << "Absolute value of -10.01: " << abs(-10.01) << "\n\n";
return 0;
}
// abs() for ints
int abs(int n)
{
cout << "In integer abs()\n";
return n<0 ? -n : n;
}
// abs() for longs
long abs(long n)
{
cout << "In long abs()\n";
return n<0 ? -n : n;
}
// abs() for doubles
double abs(double n)
Chöông 1 Toång quan veà Laäp trình höôùng ñoái töôïng
14
{
cout << "In double abs()\n";
return n<0 ? -n : n;
}
Ví duï 1.8
Khaùc soá ñoái soá vaø khaùc kieåu döõ lieäu
#include <iostream.h>
void date(char *date);
// date as a string
void date(int month, int day, int year);
// date as numbers
int main()
{
date("8/23/99");
date(8, 23, 99);
return 0;
}
// Date as string.
void date(char *date)
{
cout << "Date: " << date << "\n";
}
// Date as integers.
void date(int month, int day, int year)
{
cout << "Date: " << month << "/";
cout << day << "/" << year << "\n";
}
Ví duï 1.9
Hai haøm chæ khaùc nhau ôû kieåu döõ lieäu traû veà laøm cho trình bieân dòch
khoâng theå löïa choïn kieåu ñuùng ñeå goïi.
Chöông 1 Toång quan veà Laäp trình höôùng ñoái töôïng
15
// This is incorrect and will not compile.
int f1(int a);
double f1(int a);
int main()
{
f1(10);
// which function does the compiler call???
return 0;
}
.
.
.
4/ Caùc töø khoaù (keywords) trong C++
Ngoaøi caùc töø khoaùduøng trong ngoân ngöõ C, ANSI C++ söû duïng caùc töø khoaù thöôøng
duøng nhö sau :
asm
delete
new
protected
throw
...
bool
false
operator
public
true
...
catch
friend
overload
template
try
...
class
inline
private this
virtual
...
YÙ nghiaõ cuûa chuùng seõ ñöôïc laàn löôït giaûi thích vaø minh hoaï trong caùc chöông sau cuûa
baøi giaûng.
Chöông 2
Lôùp, ñoái töôïng vaø tính ñoùng goùi
•
Lôùp
•
Haøm taïo, haøm huûy
•
Tham soá cuûa haøm taïo
•
Noäi tuyeán töï ñoäng
•
Gaùn ñoái töôïng
•
Truyeàn caùc ñoái töôïng sang haøm
•
Traû ñoái töôïng töø haøm
•
Haøm friend
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
17
17
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
18
18
I/ Lôùp (class)
•
Cuù phaùp khai baùo lôùp
class
class_name {
private :
// khai baùo caùc bieán ;
// khai baùo caùc haøm;
public :
// khai baùo caùc bieán ;
// khai baùo caùc haøm;
}
objects_list ;
class_name teân cuûa lôùp do ngöôøi duøng ñònh nghiaõ.
objects_list danh saùch caùc ñoái töôïng, coù theå tuøy choïn.
Caùc bieán, caùc haøm khai baùo beân trong moät lôùp goïi laø caùc thaønh vieân cuûa lôùp ñoù.
Töø khoaù
YÙ nghiaõ
class
khai baùo moät lôùp
private :
qui ñònh caùc bieán, caùc haøm laø caùc thaønh vieân rieâng cuûa lôùp, beân
ngoaøi lôùp khoâng theå truy caäp ñöôïc.
public :
qui ñònh caùc bieán, caùc haøm laø caùc thaønh vieân chung cuûa lôùp, coù
theå truy caäp chuùng töø caùc thaønh vieân khaùc cuûa lôùp vaø bôûi caùc
thaønh phaàn khaùc cuûa chöông trình coù chöùa lôùp ñoù.
•
Cuù phaùp ñònh nghiaõ haøm thaønh vieân
data_type class_name :: func_name (arg_list)
{
// body of function
}
data_type kieåu döõ lieäu cuûa phöông thöùc traû veà
class_name teân lôùp chöùa haøm
::
toaùn töû phaân giaûi phaïm vi (scope resolution operator)
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
19
19
func_name teân haøm
arg_list
danh saùch caùc ñoái soá
Ví duï 1.1
Khai baùo lôùp coù teân "myclass"
class
myclass {
// private to myclass
int a;
public:
void set_a(int num);
int get_a();
};
void myclass::set_a(int num)
// ñònh nghiaõ haøm void set_a(int num)
{
a = num;
}
int myclass::get_a()
// ñònh nghiaõ haøm int get_a()
{
return a;
}
int main()
{
myclass ob1, ob2;
// khai baùo 2 ñoái töôïng coù teân ob1, ob2
ob1.set_a(10);
// thieát laäp giaù trò 10 cho baûn sao cuaû bieán a cuûa ob1
ob2.set_a(99);
// thieát laäp giaù trò 99 cho baûn sao cuaû bieán a cuûa ob2
cout << ob1.get_a() << "\n";
cout << ob2.get_a() << "\n";
return 0;
}
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
20
20
Ví duï 1.2
Loãi bieân dòch khi truy caäp ñeán bieán rieâng a töø beân ngoaøi lôùp myclass
int main()
{
myclass ob1, ob2;
ob1.a = 10;
// ERROR! cannot access private member
ob2.a = 99;
// by non-member functions.
return 0;
}
Ví duï 1.3
Khi a laø bieán chung, coù theå truy caäp a töø beân ngoaøi lôùp myclass
#include <iostream.h>
class myclass {
public:
// now a is public
int a;
// and there is no need for set_a() or get_a()
};
int main()
{
myclass ob1, ob2;
// here, a is accessed directly
ob1.a = 10;
ob2.a = 99;
cout << ob1.a << "\n";
cout << ob2.a << "\n";
return 0;
}
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
21
21
Ví duï 1.4
Taïo lôùp stack duøng ñeå chöùa caùc kyù töï
#include <iostream.h>
#define SIZE 10
// Declare a stack class for characters
class stack {
char stck[SIZE]; // holds the stack
int tos;
// index of top-of-stack
public:
void init();
// initialize stack
void push(char ch);
// push character on stack
char pop();
// pop character from stack
};
// Initialize the stack
void stack::init()
{
tos = 0;
}
// Push a character.
void stack::push(char ch)
{
if(tos == SIZE) {
cout << "Stack is full";
return;
}
stck[tos] = ch;
tos++;
}
// Pop a character.
char stack::pop()
{
if(tos == 0) {
cout << "Stack is empty";
return 0; // return null on empty stack
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
22
22
}
tos--;
return stck[tos];
}
int main()
{
stack s1, s2; // create two stacks
int i;
// initialize the stacks
s1.init();
s2.init();
s1.push('a');
s2.push('x');
s1.push('b');
s2.push('y');
s1.push('c');
s2.push('z');
for(i=0; i<3; i++) cout << "Pop s1: " << s1.pop() << "\n";
for(i=0; i<3; i++) cout << "Pop s2: " << s2.pop() << "\n";
return 0;
}
@ Keát quaû xuaát döõ lieäu cuûa chöông trình ?
•
Löu yù
Khai baùo lôùp laø moät tröøu töôïng logic ñeå ñònh nghiaõ moät kieåu döõ lieäu môùi.
Khai baùo moät ñoái töôïng döïa vaøo lôùp, taïo ra moät thöïc theå vaät lyù (coù ñiaï chæ trong boä
nhôù) coù kieåu döõ lieäu ñoù.
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
23
23
Moãi ñoái töôïng cuûa moät lôùp coù baûn sao rieâng cuûa caùc bieán ñöôïc khai baùo trong lôùp.
Baøi taäp I
1. Haõy taïo lôùp card ñeå giöõ caùc muïc nhaäp catalog theû thö vieän, chöaù töïa ñeà saùch (kieåu
chuoãi), teân taùc giaû (kieåu chuoãi) vaø soá baûn (kieåu nguyeân). Duøng haøm thaønh vieân
chung store() ñeå löu tröõ thoâng tin veà saùch vaø haøm thaønh vieân chung show() ñeå hieån
thò thoâng tin. Vieát chöông trình thöïc hieän yeâu caàu treân.
2. Taïo lôùp haøng ñôïi (queue) ñeå giöõ haøng caùc soá nguyeân. Taïo moät kích thöôùc haøng
daøi 100 soá nguyeân. Vieát chöông trình thöïc hieän yeâu caàu treân.
II/ Haøm taïo & haøm huûy
1/ Khaùi nieäm
Haøm taïo
(constructor) coù cuøng teân vôùi lôùp, laø haøm thaønh phaàn cuûa moät lôùp,
khoâng coù kieåu traû veà.
Muïc ñích cuûa haøm taïo nhaèm taïo ra caùc khôûi ñaàu cho moät ñoái töôïng.
Haøm taïo ñöôïc goïi töï ñoäng moãi khi ñoái töôïng cuûa lôùp ñoù ñöôïc taïo ra.
2/ Khai baùo
class class_name {
// khai baùo caùc bieán vaø haøm ;
public :
// khai baùo caùc bieán vaø haøm ;
class_name()
;
// khai baùo haøm taïo
} objects_list ;
Ví duï 2.1
Lôùp myclass coù haøm taïo myclass() vaø haøm show()
#include <iostream.h>
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
24
24
class myclass {
int a;
public:
myclass() ;
// constructor
void show();
};
myclass::myclass() // ñònh nghiaõ haøm taïo
{
cout << "In constructor\n";
a = 10;
}
void myclass::show()
{
cout << a;
}
int main()
{
myclass ob; // haøm taïo myclass() ñöôïc goïi töï ñoäng khi ñoái töôïng ob ñöôïc taïo ra
ob.show();
return 0;
}
Ñoái vôùi caùc ñoái töôïng chung, moät haøm taïo cuûa ñoái töôïng ñöôïc goïi moät laàn khi
chöông trình baét ñaàu thi haønh laàn ñaàu.
Ñoái vôùi caùc ñoái töôïng rieâng, haøm taïo cuûa ñoái töôïng ñöôïc goïi moãi khi leänh khai baùo
ñöôïc thi haønh.
3/ Khaùi nieäm haøm huûy (destructor)
Haøm huûy
coù cuøng teân vôùi lôùp, coù keøm theo daáu ~ ñöùng tröôùc, laø haøm thaønh phaàn cuûa
moät lôùp, khoâng coù kieåu traû veà.
Muïc ñích cuûa haøm huûy nhaèm thi haønh moät soá taùc ñoäng khi ñoái töôïng bò huûy boû,
chaúng haïn moät ñoái töôïng yeâu caàu caáp phaùt boä nhôù khi ñoái töôïng ñöôïc taïo ra vaø giaûi
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
25
25
phoùng boä nhôù khi ñoái töôïng bò huûy boû.
Haøm huûy ñöôïc goïi töï ñoäng moãi khi ñoái töôïng cuûa lôùp ñoù bò huûy boû.
4/ Khai baùo
class class_name {
// khai baùo caùc bieán vaø haøm ;
public :
// khai baùo caùc bieán vaø haøm ;
class_name();
// khai baùo haøm taïo
~class_name()
;
// khai baùo haøm huûy
} objects_list ;
Ví duï 2.2
Lôùp myclass coù haøm taïo myclass() vaø haøm huûy ~myclass()
#include <iostream.h>
class myclass {
int a;
public:
myclass();
// constructor
~myclass();
// destructor
void show();
};
myclass::myclass()
{
cout << "In constructor\n";
a = 10;
}
myclass::~myclass()
{
cout << "Destructing...\n";
}
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
26
26
void myclass::show()
{
cout << a << "\n";
}
int main()
{
myclass ob;
ob.show();
return 0;
}
Ñoái vôùi caùc ñoái töôïng chung, haøm huûy cuûa ñoái töôïng ñöôïc goïi khi chöông trình keát
thuùc.
Ñoái vôùi caùc ñoái töôïng rieâng, haøm huûy cuûa ñoái töôïng ñöôïc goïi khi chuùng ra khoûi phaïm
vi.
•
Löu yù
: Khoâng theå bieát ñöôïc ñòa chæ cuûa haøm taïo hoaëc haøm huûy.
Ví duï 2.3
Duøng haøm taïo stack() ñeå töï ñoäng khôûi ñaàu ngaên xeáp khi ñoái töôïng ñöôïc
taïo
#include <iostream.h>
#define SIZE 10
// Declare a stack class for characters.
class stack {
char stck[SIZE]; // holds the stack
int tos;
// index of top-of-stack
public:
stack();
// constructor
void push(char ch);
// push character on stack
char pop();
// pop character from stack
};
// Initialize the stack.
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
27
27
stack::stack()
{
cout << "Constructing a stack\n";
tos = 0;
}
// Push a character.
void stack::push(char ch)
{
if(tos==SIZE) {
cout << "Stack is full\n";
return;
}
stck[tos] = ch;
tos++;
}
// Pop a character.
char stack::pop()
{
if(tos==0) {
cout << "Stack is empty\n";
return 0;
// return null on empty stack
}
tos--;
return stck[tos];
}
int main()
{
// Create two stacks that are automatically initialized.
stack s1, s2;
int i;
s1.push('a');
s2.push('x');
s1.push('b');
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
28
28
s2.push('y');
s1.push('c');
s2.push('z');
for(i=0; i<3; i++) cout << "Pop s1: " << s1.pop() << "\n";
for(i=0; i<3; i++) cout << "Pop s2: " << s2.pop() << "\n";
return 0;
}
Ví duï 2.4
Duøng haøm taïo strtype() vaø haøm huûy ~strtype() ñeå töï ñoäng caáp phaùt
boä nhôù cho chuoåi *p vaø giaûi phoùng boä nhôù khi ñoái töôïng bò huûy.
#include <iostream.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#define SIZE 255
class strtype {
char *p;
int len;
public:
strtype(); // constructor
~strtype(); //destructor
void set(char *ptr);
void show();
};
// Initialize a string object.
strtype::strtype()
{
p = (char *) malloc(SIZE);
if(!p) {
cout << "Allocation error\n";
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
29
29
exit(1);
}
*p = '\0';
len = 0;
}
// Free memory when destroying string object.
strtype::~strtype()
{
cout << "Freeing p\n";
free(p);
}
void strtype::set(char *ptr)
{
if(strlen(ptr) >= SIZE) {
cout << "String too big\n";
return;
}
strcpy(p, ptr);
len = strlen(p);
}
void strtype::show()
{
cout << p << " - length: " << len;
cout << "\n";
}
int main()
{
strtype s1, s2;
s1.set("This is a test.");
s2.set("I like C++.");
s1.show();
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
30
30
s2.show();
return 0;
}
Ví duï 2.5
Duøng ñoái töôïng cuûa lôùp timer ñeå xaùc ñònh khoaûng thôøi gian
khi moät ñoái töôïng kieåu timer ñöôïc taïo vaø cho ñeán khi bò huûy.
#include <iostream.h>
#include <ctime.h>
class timer {
clock_t start;
public:
timer(); // constructor
~timer(); // destructor
};
timer::timer()
{
start = clock();
}
timer::~timer()
{
clock_t end;
end = clock();
cout << "Elapsed time: " << (end-start) / CLOCKS_PER_SEC << "\n";
}
int main()
{
timer ob;
char c;
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
31
31
// delay ...
cout << "Press a key followed by ENTER: ";
cin >> c;
return 0;
}
Chöông trình naøy duøng haøm thö vieän chuaån clock() ñeå traû veà soá chu kyø ñoàng hoà xaûy
ra töø khi chöông trình baét ñaàu chaïy. Chia giaù trò naøy cho haèng soá CLK-TCK ñeå
chuyeån thaønh giaù trò giaây. (CLK-TCK ñònh nghiaõ soá tic-taéc cuûa ñoàng hoà trong moät
giaây)
Baøi taäp II
1. Thöïc hieän laïi lôùp queue trong baøi taäp I/ 2. chöông 2 ñeå thay haøm khôûi ñaàu baèng
haøm taïo.
2. Taïo lôùp stopwatch ñeå so vôùi ñoàng hoà baám giôø trong vieäc xaùc ñònh thôøi gian troâi
qua, ñöôïc tính baèng giaây. Caùc yeâu caàu :
- Lôùp stopwatch coù 2 bieán rieâng start vaø end löu soá giaây
- Vieát haøm taïo ñeå ñaït thôøi gian troâi qua luùc ñaàu veà zero.
- Hai haøm thaønh vieân start() vaø stop() ñeå laàn löôït môû vaø taét cheá ñoä ñònh giôø.
- Haøm thaønh vieân show() ñeå hieån thò thôøi gian troâi qua.
- Vieát haøm huûy ñeå töï ñoäng hieån thò thôøi gian troâi qua khi ñoái töôïng stopwatch bò huûy.
3. Söûa loãi trong ñoaïn chöông trình sau :
class sample {
double a, b, c;
public
:
double
sample()
;
}
III/ Tham soá cuûa haøm taïo
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
32
32
1/ Khaùi nieäm
Haøm taïo coù theå coù caùc tham soá, chæ caàn boå sung caùc tham soá thích hôïp trong khai baùo
lôùp vaø trong ñònh nghóa haøm taïo.
Khi khai baùo moät ñoái töôïng, caàn chæ roõ caùc tham soá naøy laøm ñoái soá.
Ví duï 3.1
Haøm taïo myclass(int x) coù moät tham soá
#include <iostream.h>
class myclass {
int a;
public:
myclass(int x); // constructor
void show();
};
myclass::myclass(int x)
{
cout << "In constructor\n";
a = x;
}
void myclass::show()
{
cout << a << "\n";
}
int main()
{
myclass ob(4);
ob.show();
return 0;
}
Giaù trò 4 trong khai baùo ñoái töôïng ob(4), laø ñoái soá ñöôïc truyeàn cho tham soá x cuûa
haøm taïo myclass(int x), duøng ñeå khôûi taïo bieán a.
Caùch vieát khaùc (daøi hôn)
myclass ob = myclass (4) ;
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
33
33
•
Löu yù haøm huûy khoâng coù tham soá. Do khoâng coù cô cheá naøo ñeå truyeàn ñoái soá cho
moät ñoái töôïng bò huûy.
Ví duï 3.2
Coù theå truyeàn nhieàu tham soá cho haøm taïo
#include <iostream.h>
class myclass {
int a, b;
public:
myclass(int x, int y);
// constructor
void show();
};
myclass::myclass(int x, int y)
{
cout << "In constructor\n";
a = x;
b = y;
}
void myclass::show()
{
cout << a << ' ' << b << "\n";
}
int main()
{
myclass ob(4, 7);
ob.show();
return 0;
}
Ví duï 3.3
Duøng haøm taïo ñöôïc tham soá hoùa ñeå truyeàn "teân" cho stack.
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
34
34
#include <iostream.h>
#define SIZE 10
// Declare a stack class for characters.
class stack {
char stck[SIZE];
// holds the stack
int tos;
// index of top-of-stack
char who;
// identifies stack
public:
stack(char c);
// constructor
void push(char ch);
// push character on stack
char pop();
// pop character from stack
};
// Initialize the stack.
stack::stack(char c)
{
tos = 0;
who = c;
cout << "Constructing stack " << who << "\n";
}
// Push a character.
void stack::push(char ch)
{
if(tos == SIZE) {
cout << "Stack " << who << " is full\n";
return;
}
stck[tos] = ch;
tos++;
}
// Pop a character.
char stack::pop()
{
if(tos == 0) {
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
35
35
cout << "Stack " << who << " is empty\n";
return 0; // return null on empty stack
}
tos--;
return stck[tos];
}
int main()
{
// Create two stacks that are automatically initialized.
stack s1('A'), s2('B');
int i;
s1.push('a');
s2.push('x');
s1.push('b');
s2.push('y');
s1.push('c');
s2.push('z');
// This will generate some error messages.
for(i=0; i<5; i++) cout << "Pop s1: " << s1.pop() << "\n";
for(i=0; i<5; i++) cout << "Pop s2: " << s2.pop() << "\n";
return 0;
}
@ Muïc ñích : duøng ñeå nhaän ra teân stack naøo ñöôïc tham chieáu khi coù loãi xaûy ra.
Ñieàu naøy raát coù ích trong quaù trình gôõ roái (debug).
Ví duï 3.4
Ñoái soá cuûa haøm taïo laø moät chuoåi.
#include <iostream.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
36
36
class strtype {
char *p;
int len;
public:
strtype(char *ptr);
~strtype();
void show();
};
strtype::strtype(char *ptr)
{
len = strlen(ptr);
p = (char *) malloc(len+1);
if(!p) {
cout << "Allocation error\n";
exit(1);
}
strcpy(p, ptr);
}
strtype::~strtype()
{
cout << "Freeing p\n";
free(p);
}
void strtype::show()
{
cout << p << " - length: " << len;
cout << "\n";
}
int main()
{
strtype s1("This is a test.") , s2("I like C++.") ;
s1.show();
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
37
37
s2.show();
return 0;
}
Ví duï 3.6
Coù theå truyeàn cho haøm taïo cuûa ñoái töôïng moät bieåu thöùc hoaëc caùc bieán.
#include <iostream.h>
class myclass {
int i, j;
public:
myclass(int a, int b);
void show();
};
myclass::myclass(int a, int b)
{
i = a;
j = b;
}
void myclass::show()
{
cout << i << ' ' << j << "\n";
}
int main()
{
int x, y;
cout << "Enter two integers: ";
cin >> x >> y;
// use variables to construct ob
myclass ob(x, y);
ob.show();
return 0;}
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
38
38
Baøi taäp III
1. Vieát chöông trình thay ñoåi lôùp stack ñeå cho noù caáp phaùt boä nhôù ñoäng cho ngaên xeáp
chöùa caùc kyù töï. Kích thöôùc ngaên xeáp ñöôïc chæ roõ baèng moät tham soá vôùi haøm taïo.
Haøm huûy giaûi phoùng boä nhôù ñoäng.
2. Haõy taïo lôùp t_and_d ñeå truyeàn ngaøy vaø giôø heä thoáng hieän haønh nhö moät tham soá
cho haøm taïo cuûa noù khi ñöôïc taïo ra. Lôùp goàm coù haøm thaønh vieân hieån thò ngaøy giôø
naøy leân maøn hình. Duøng caùc haøm ngaøy vaø giôø chuaån trong thö vieän chuaån ñeå tìm vaø
hieän thò ngaøy.
3. Vieát chöông trình taïo lôùp box coù haøm taïo ñöôïc truyeàn 3 giaù trò double, dieãn taû ñoä
daøi caùc caïnh cuûa hoäp. Haõy cho lôùp box tính theå tích cuûa hình laäp phöông vaø löu tröõ
keát quûa trong bieán double. Taïo haøm thaønh vieân vol() ñeå hieån thò theå tích cuûa moãi ñoái
töôïng box.
IV/ Noäi tuyeán töï ñoäng (in-line)
1/ Khaùi nieäm
Khi ñònh nghiaõ haøm thaønh phaàn laø ñuû ngaén thì coù theå ñaët ñònh nghiaõ trong khai baùo
haøm trong lôùp ñoù. Haøm naøy seõ ñöôïc goïi laø haøm noäi tuyeán (in-line func.) vaø khoâng
caàn duøng töø khoaù inline ñöùng tröôùc haøm ñoù.
Ví duï 4.1
#include <iostream.h>
class samp {
int i, j;
public:
samp(int a, int b);
// divisible() is defined here and automatically in-lined
int divisible() { return !(i%j) ; }
};
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
39
39
samp::samp(int a, int b)
{
i = a;
j = b;
}
int main()
{
samp ob1(10, 2), ob2(10, 3);
// this is true
if(ob1.divisible()) cout << "10 divisible by 2\n";
// this is false
if(ob2.divisible()) cout << "10 divisible by 3\n";
return 0;
}
Ví duï 4.2
Duøng haøm noäi tuyeán ñeå ñònh nghiaõ caùc haøm taïo vaø haøm huûy
#include <iostream.h>
class samp {
int i, j;
public:
samp(int a, int b) { i = a; j = b; }
// inline constructor
int divisible() { return !(i%j); }
};
Ví duï 4.3
Moät haøm ngaén ôû beân trong moät khai baùo lôùp
cho duø ñaëc ñieåm noäi tuyeán töï ñoäng laø khoâng coù giaù trò.
class myclass {
int i;
public:
myclass(int n) { i = n; }
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
40
40
void show() { cout << i; }
};
Baøi taäp IV
1. Vieát chöông trình chuyeån ñoåi lôùp stack trong ví duï 2.3 chöông 2, ñeå lôùp naøy söû
duïng caùc haøm noäi tuyeán töï ñoäng ôû nhöõng nôi thích hôïp.
2. Vieát chöông trình chuyeån ñoåi lôùp strtype trong ví duï 2.4 chöông 2, ñeå lôùp naøy söû
duïng caùc haøm noäi tuyeán töï ñoäng.
V/ Gaùn ñoái töôïng
1/ Khaùi nieäm
Moät ñoái töôïng ñöôïc gaùn cho moät ñoái töôïng khaùc ñeå caû hai ñoái töôïng coù cuøng kieåu,
khi ñoù söï sao cheùp töøng bit cuûa caùc thaønh vieân döõ lieäu ñöôïc thöïc hieän.
Ví duï 5.1
// An example of object assignment.
#include <iostream.h>
class myclass {
int a, b;
public:
void set(int i, int j) { a = i; b = j; }
void show() { cout << a << ' ' << b << "\n"; }
};
int main()
{
myclass o1, o2;
o1.set(10, 4);
// assign o1 to o2
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
41
41
o2 = o1;
o1.show();
o2.show();
return 0;
}
Neáu boå sung caùc doøng leänh sau ñaây vaøo tröôùc doøng return 0; , keát quaû seõ ra sao ?
o1.set(3, 2);
o1.show();
o2.show();
2/ Caùc tính chaát
a/ Leänh gaùn ñoái töôïng chæ aùp duïng cho caùc ñoái töôïng coù cuøng kieåu (veà maët vaät lyù) vaø
cuøng teân kieåu
.
Ví duï 5.2
// This program has an error.
#include <iostream.h>
class myclass {
int a, b;
public:
void set(int i, int j) { a = i; b = j; }
void show() { cout << a << ' ' << b << "\n"; }
};
/* This class is similar to myclass but uses a different class name and thus appears
as
a different type to the compiler */
class yourclass {
int a, b;
public:
void set(int i, int j) { a = i; b = j; }
void show() { cout << a << ' ' << b << "\n"; }
};
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
42
42
int main()
{
myclass o1;
yourclass o2;
o1.set(10, 4);
o2 = o1;
// ERROR, objects not of same type name
o1.show();
o2.show();
return 0;
}
b/ Pheùp gaùn ñoái töôïng coøn aùp duïng cho caùc döõ lieäu phöùc taïp nhö maûng, ...
Ví duï 5.3
#include <iostream.h>
#define SIZE 10
// Declare a stack class for characters.
class stack {
char stck[SIZE]; // holds the stack
int tos;
// index of top-of-stack
public:
stack();
// constructor
void push(char ch);
// push character on stack
char pop();
// pop character from stack
};
// Initialize the stack.
stack::stack()
{
cout << "Constructing a stack\n";
tos = 0;
}
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
43
43
// Push a character.
void stack::push(char ch)
{
if(tos==SIZE) {
cout << "Stack is full\n";
return;
}
stck[tos] = ch;
tos++;
}
// Pop a character.
char stack::pop()
{
if(tos==0) {
cout << "Stack is empty\n";
return 0; // return null on empty stack
}
tos--;
return stck[tos];
}
int main()
{
// Create two stacks that are automatically initialized.
stack s1, s2;
int i;
s1.push('a');
s1.push('b');
s1.push('c');
// clone s1
s2 = s1; // now s1 and s2 are identical
for(i=0; i<3; i++) cout << "Pop s1: " << s1.pop() << "\n";
for(i=0; i<3; i++) cout << "Pop s2: " << s2.pop() << "\n";
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
44
44
return 0;
}
c/ Ñoái vôùi caùc ñoái töôïng coù söû duïng chuoåi, khi thöïc hieän pheùp gaùn ñoái töôïng phaûi
chaéc chaén raèng khoâng huûy boû caùc thoâng tin caàn thieát trong ñoái töôïng ñoù.
Ví duï 5.4
// This program contains an error.
#include <iostream.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
class strtype {
char *p;
int len;
public:
strtype(char *ptr);
~strtype();
void show();
};
strtype::strtype(char *ptr)
{
len = strlen(ptr);
p = (char *) malloc(len+1);
if(!p) {
cout << "Allocation error\n";
exit(1);
}
strcpy(p, ptr);
}
strtype::~strtype()
{
cout << "Freeing p\n";
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
45
45
free(p);
}
void strtype::show()
{
cout << p << " - length: " << len;
cout << "\n";
}
int main()
{
strtype s1("This is a test."), s2("I like C++.");
s1.show();
s2.show();
// assign s1 to s2 - - this generates an error
s2 = s1;
s1.show();
s2.show();
return 0;
}
Nguyeân nhaân naøo gaây ra loãi ?
Baøi taäp V
1. Tìm loãi sai trong ñoaïn chöông trình sau
#include <iostream>
class cl1 {
int i, j;
public:
cl1(int a, int b) { i = a; j = b; }
// ...
};
class cl2 {
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
46
46
int i, j;
public:
cl2(int a, int b) { i = a; j = b; }
// ...
};
int main()
{
cl1 x(10, 20);
cl2 y(0, 0);
x = y;
// ...
}
2. Vieát chöông trình döïa vaøo lôùp queue trong baøi taäp II/ 1. chöông II chöùng toû moät
haøng ñôïi coù theå ñöôïc gaùn cho moät haøng ñôïi khaùc.
3. Neáu lôùp queue trong caâu 2. caáp phaùt boä nhôù ñoäng ñeå giöõ haøng ñôïi, taïi sao trong
tröôøng hôïp naøy, moät haøng ñôïi khoâng theå ñöôïc gaùn cho haøng ñôïi khaùc.
VI/ Truyeàn caùc ñoái töôïng sang haøm
1/ Vieäc truyeàn caùc ñoái töôïng cho haøm gioáng nhö truyeàn caùc ñoái soá thoâng thöôøng.
Tham soá cuûa haøm coù kieåu döõ lieäu laø kieåu lôùp, vaø ñoái soá truyeàn cho haøm chính laø ñoái
töôïng
.
Gioáng nhö caùc kieåu döõ lieäu khaùc, theo ngaàm ñònh, taát caû caùc ñoái töôïng ñöôïc truyeàn
bôûi giaù trò cho moät haøm.
Ví duï 6.1
Truyeàn moät ñoái töôïng cho haøm.
#include <iostream.h>
class samp {
int i;
public:
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
47
47
samp(int n) { i = n; }
int get_i() { return i; }
};
// Return square of o.i.
int sqr_it(samp o)
{
return o.get_i() * o.get_i();
}
int main()
{
samp a(10), b(2);
cout << sqr_it(a) << "\n";
cout << sqr_it(b) << "\n";
return 0;
}
2/ Do ñoái töôïng ñöôïc truyeàn bôûi giaù trò cho moät haøm, coù nghóa laø vieäc sao cheùp töøng
bit cuûa ñoái soá ñöôïc thöïc hieän vaø chính sao cheùp naøy ñöôïc söû duïng bôûi haøm. Do ñoù,
nhöõng thay ñoåi cho ñoái töôïng beân trong haøm khoâng coù aûnh höôûng ñeán söï goïi ñoái
töôïng.
Ví duï 6.2
#include <iostream.h>
class samp {
int i;
public:
samp(int n) { i = n; }
void set_i(int n) { i = n; }
int get_i() { return i; }
};
// Set o.i to its square. This has no effect on the object used to call sqr_it(),
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
48
48
however.
void sqr_it(samp o)
{
o.set_i( o.get_i() * o.get_i() ) ;
cout << "Copy of a has i value of " << o.get_i();
cout << "\n";
}
int main()
{
samp a(10);
sqr_it(a) ;
// a passed by value, displays 100
cout << "But, a.i is unchanged in main: ";
cout << a.get_i(); // displays 10
return 0;
}
3/ Khi truyeàn ñiaï chæ cuûa ñoái töôïng sang haøm (seõ khoâng taïo ra baûn sao ñoái töôïng),
noäi dung cuûa ñoái töôïng seõ bò thay ñoåi.
Ví duï 6.3
#include <iostream.h>
class samp {
int i;
public:
samp(int n) { i = n; }
void set_i(int n) { i = n; }
int get_i() { return i; }
};
/* Set o.i to its square. This affects the calling argument. */
void sqr_it(samp *o)
{
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
49
49
o->set_i(o->get_i() * o->get_i());
cout << "Copy of a has i value of " << o->get_i();
cout << "\n";
}
int main()
{
samp a(10);
sqr_it(&a);
// pass a's address to sqr_it(), displays 100
cout << "Now, a in main() has been changed: ";
cout << a.get_i(); // displays 100
return 0;
}
4/ Baûn sao cuûa ñoái töôïng
Khi truyeàn moät ñoái töôïng cho haøm, moät baûn sao cuûa ñoái töôïng ñöôïc thöïc hieän, coù
nghóa laø moät ñoái töôïng môùi xuaát hieän. Do ñoù khi haøm keát thuùc laøm vieäc, baûn sao cuûa
ñoái töôïng ñoù (ñoái soá cuûa haøm) seõ bò huûy.
Ñieàu naøy laøm naûy sinh hai vaán ñeà :
- Haøm taïo cuûa ñoái töôïng ñöôïc goïi khi baûn sao thöïc hieän ?
- Haøm huûy cuûa ñoái töôïng ñöôïc goïi khi baûn sao bò huûy ?
Khi baûn sao cuûa moät ñoái töôïng ñöôïc thöïc hieän ñeå duøng goïi haøm, thì haøm taïo khoâng
ñöôïc goïi
. Do haøm taïo thöôøng ñöôïc duøng ñeå khôûi ñaàu moät khiaù caïnh naøo ñoù cuûa ñoái
töôïng. Khi truyeàn moät ñoái töôïng cho moät haøm, baïn caàn ñeán traïng thaùi hieän haønh cuûa
ñoái töôïng chöù khoâng phaûi traïng thaùi ban ñaàu.
Khi haøm keát thuùc vaø baûn sao bò huûy, haøm huûy ñöôïc goïi.
Ví duï 6.4
#include <iostream.h>
class samp {
int i;
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
50
50
public:
samp(int n) {
i = n;
cout << "Constructing\n";
}
~samp() { cout << "Destructing\n"; }
int get_i() { return i; }
};
// Return square of o.i.
int sqr_it(samp o)
{
return o.get_i() * o.get_i();
}
int main()
{
samp a(10);
cout << sqr_it(a) << "\n";
return 0;
}
Noäi dung chöông trình thöïc hieän
Constructing
Destructing
100
Destructing
Giaûi thích ?
Haøm huûy cuûa baûn sao ñoái töôïng
ñöôïc goïi khi haøm keát thuùc coù theå laø nguyeân nhaân cuûa
nhieàu vaán ñeà.
Chaúng haïn, neáu ñoái töôïng coù haøm taïo caáp phaùt boä nhôù ñoäng hoaëc haøm huûy giaûi
phoùng boä nhôù ñoäng, thì baûn sao cuûa ñoái töôïng seõ giaûi phoùng boä nhôù ñoäng khi haøm
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
51
51
huûy cuûa noù ñöôïc goïi. Ñieàu naøy laøm cho ñoái töôïng goác bò hoûng vaø trôû thaønh voâ duïng.
Ví duï 6.5
// This program contains an error.
#include <iostream.h>
#include <stdlib.h>
class dyna {
int *p;
public:
dyna(int i);
~dyna() { free(p); cout << "freeing \n"; }
int get() { return *p; }
};
dyna::dyna(int i)
{
p = (int *) malloc(sizeof(int));
if(!p) {
cout << "Allocation failure\n";
exit(1);
}
*p = i;
}
// Return negative value of *ob.p
int neg(dyna ob)
{
return -ob.get();
}
int main()
{
dyna o(-10);
cout << o.get() << "\n"; // -10
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
52
52
cout << neg(o) << "\n"; // freeing
// 10
dyna o2(20);
cout << o2.get() << "\n"; // 20
cout << neg(o2) << "\n"; // freeing
// -20
cout << o.get() << "\n"; // 20 do *p ñöôïc caáp ñòa chæ vuøng nhôù ñoäng
cout << neg(o) << "\n"; // freeing
// -20
return 0;
// freeing o
//
freeing
o2
// Null pointer assignment
}
Giaûi thích nguyeân nhaân gaây loåi ?
•
Coù theå khaéc phuïc baèng caùch truyeàn ñiaï chæ cuûa ñoái töôïng cho haøm. Vì seõ khoâng
coù ñoái töôïng môùi ñöôïc taïo ra vaø khoâng coù haøm huûy cuûa baûn sao ñoái töôïng ñöôïc
goïi khi haøm traû veà.
Tuy nhieân, giaûi phaùp toát nhaát laø söû duïng haøm taïo baûn sao (copy constructor), cho
pheùp ñònh nghiaõ caùch thöùc taïo caùc baûn sao cuûa caùc ñoái töôïng (xem chöông sau).
Baøi taäp VI
1. Vieát chöông trình taïo lôùp stack trong ví duï 5.3 chöông 2, boå sung haøm
showstack() ñeå truyeàn moät ñoái töôïng kieåu stack. Cho haøm naøy hieån thò noäi dung cuûa
ngaên xeáp.
2. Tìm loãi sai trong chöông trình naøy
#include <iostream.h>
#include <stdlib.h>
class dyna {
int *p;
public:
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
53
53
dyna(int i);
~dyna() { free(p); cout << "freeing \n"; }
int get() { return *p; }
};
dyna::dyna(int i)
{
p = (int *) malloc(sizeof(int));
if(!p) {
cout << "Allocation failure\n";
exit(1);
}
*p = i;
}
// Return negative value of *ob.p
int neg(dyna ob)
{
return -ob.get();
}
int main()
{
dyna o(-10);
cout << o.get() << "\n";
cout << neg(o) << "\n";
dyna o2(20);
cout << o2.get() << "\n";
cout << neg(o2) << "\n";
cout << o.get() << "\n";
cout << neg(o) << "\n";
return 0;
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
54
54
}
VII/ Traû ñoái töôïng töø haøm
•
Ñoái töôïng traû veà töø haøm thoâng qua caâu leänh return. Khi ñoù moät ñoái töôïng taïm
ñöôïc töï ñoäng taïo ra ñeå giöõ giaù trò traû veà.
Chính ñoái töôïng naøy thöïc söï ñöôïc traû veà bôûi haøm. Sau khi giaù trò ñöôïc traû veà, ñoái
töôïng naøy bò huûy, söï huûy ñoái töôïng taïm coù theå gaây ra taùc duïng ngoaøi yù muoán.
Ví duï 7.1
// Returning an object
#include <iostream.h>
#include <string.h>
class samp {
char s[80];
public:
void show() { cout << s << "\n"; }
void set(char *str) { strcpy(s, str); }
};
// Return an object of type samp
samp input()
{
char s[80];
samp str;
cout << "Enter a string: ";
cin >> s;
str.set(s);
return str;
}
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
55
55
int main()
{
samp ob;
// assign returned object to ob
ob = input();
// Enter a string: Hello
↵
ob.show();
//
Hello
return 0;
}
Ví duï 7.2
Phaûi thaän troïng khi haøm traû veà ñoái töôïng, khi ñoái töôïng naøy coù chöùa
haøm huûy.
// An error generated by returning an object.
#include <iostream.h>
#include <string.h>
#include <stdlib.h>
class samp {
char *s;
public:
samp() { s = '\0'; }
~samp() { if(s) free(s); cout << "Freeing s\n"; }
void show() { cout << s << "\n"; }
void set(char *str);
};
// Load a string.
void samp::set(char *str)
{
s = (char *) malloc(strlen(str)+1);
if(!s) {
cout << "Allocation error\n";
exit(1);
}
strcpy(s, str);
}
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
56
56
// Return an object of type samp.
samp input()
{
char s[80];
samp str;
cout << "Enter a string: ";
cin >> s;
str.set(s);
return str;
}
int main()
{
samp ob;
// assign returned object to ob
ob = input(); // This causes an error!!!!
ob.show();
return 0;
}
Haõy giaûi thích keát quaû cuûa chöông trình ?
Enter a astring: Hello
Freeing
s
Freeing
s
Hello
Freeing
s
Null pointer assignment
Khi moät ñoái töôïng ñöôïc traû veà töø moät haøm, moät ñoái töôïng taïm ñöôïc duøng ñeå thöïc
hieän söï traû veà seõ laøm huûy boä nhôù (ñöôïc caáp phaùt cho chuoåi s) cuûa ñoái töôïng ñöôïc goïi.
Ñeå traùnh tình traïng naøy coù theå söû duïng haøm taïo baûn sao.
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
57
57
Baøi taäp VII
1. Vieát chöông trình taïo lôùp Who, cho haøm taïo cuûa Who nhaän moät ñoái soá kyù töï maø
ñoái soá naøy ñöôïc duøng ñeå nhaän daïng moät ñoái töôïng.
Haõy cho haøm taïo hieån thò moät thoâng baùo töông töï thoâng baùo sau ñaây khi taïo ra moät
ñoái töôïng :
Constructing who #x
Trong ñoù x laø kyù töï nhaän daïng.
Haõy taïo haøm make_who() ñeå traû veà ñoái töôïng Who. Haõy cho moãi ñoái töôïng moät teân
duy nhaát.
VIII/ Caùc haøm friend
•
Moät haøm friend khoâng phaûi laø haøm thaønh vieân cuûa lôùp nhöng coù theå truy caäp
caùc thaønh vieân rieâng
cuûa lôùp.
Moät haøm friend ñöôïc ñònh nghiaõ nhö moät haøm bình thöôøng. Neáu naèm beân trong
moät lôùp
, haøm friend seõ coù töø khoaù friend ñöùng tröôùc.
Haøm friend khoâng ñöôïc keá thöøa töø lôùp daãn xuaát (xem chöông 6).
•
Caùc lôïi ích khi duøng haøm friend :
+ söï quaù taûi toaùn töû (xem chöông 5).
+ taïo ra caùc kieåu haøm nhaäp/xuaát naøo ñoù (xem chöông 8).
+ taïo haøm ñeå truy caäp caùc thaønh vieân rieâng cuûa hai hay nhieàu lôùp khaùc nhau.
Ví duï 8.1
// A example of a friend function.
#include <iostream.h>
class myclass {
int n, d;
public:
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
58
58
myclass(int i, int j) { n = i; d = j; }
// declare a friend of myclass
friend int isfactor(myclass ob) ;
};
/* Here is friend function definition. It returns true if d is a factor of n. Notice that
the keyword friend is not used in the definition of isfactor(). */
int isfactor(myclass ob)
{
if(!(ob.n % ob.d)) return 1;
else return 0;
}
int main()
{
myclass ob1(10, 2), ob2(13, 3);
if( isfactor(ob1) ) cout << "2 is a factor of 10\n";
else cout << "2 is not a factor of 10\n";
if( isfactor(ob2) ) cout << "3 is a factor of 13\n";
else cout << "3 is not a factor of 13\n";
return 0;
}
•
Khoâng theå goïi haøm friend baèng caùch duøng teân ñoái töôïng vaø toaùn töû truy caäp
thaønh vieân (daáu chaám hoaëc muõi teân)
ob1.isfactor();
// wrong, isfactor() is not a member function
•
Khoâng gioáng nhö caùc haøm thaønh vieân cuûa lôùp, coù theå tham chieáu tröïc tieáp ñeán
caùc bieán (rieâng hoaëc chung) cuûa lôùp ñoù, moät haøm friend chæ coù theå truy caäp caùc
bieán naøy khi lieân keát vôùi moät ñoái töôïng ñöôïc khai baùo trong hoaëc ñöôïc truyeàn ñeán
cho haøm friend
.
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
59
59
•
Moät haøm friend coù theå laø caùc haøm friend cuûa hôn moät lôùp.
Ví duï 8.2
#include <iostream.h>
class truck; // a forward declaration
class car {
int passengers;
int speed;
public:
car(int p, int s) { passengers = p; speed = s; }
friend int sp_greater(car c, truck t);
};
class truck {
int weight;
int speed;
public:
truck(int w, int s) { weight = w, speed = s; }
friend int sp_greater(car c, truck t);
};
/* Return positive if car speed faster than truck.
Return 0
if speeds are the same.
Return negative if truck speed faster than car.
*/
int sp_greater(car c, truck t)
{
return c.speed - t.speed;
}
int main()
{
int t;
car c1(6, 55), c2(2, 120);
truck t1(10000, 55), t2(20000, 72);
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
60
60
cout << "Comparing c1 and t1:\n";
t = sp_greater(c1, t1);
if(t < 0)
cout << "Truck is faster.\n";
else if(t == 0)
cout << "Car and truck speed is the same.\n";
else cout << "Car is faster.\n";
cout << "\nComparing c2 and t2:\n";
t = sp_greater(c2, t2);
if(t < 0)
cout << "Truck is faster.\n";
else if(t == 0)
cout << "Car and truck speed is the same.\n";
else cout << "Car is faster.\n";
return 0;
}
Söï tham chieáu tôùi (forward reference) laø ñieàu caàn thieát cho trình bieân dòch, do haøm
sp_greater() nhaän caùc tham soá cuûa caû hai lôùp car vaø truck.
•
Moät haøm coù theå laø thaønh vieân cuûa moät lôùp vaø laø moät haøm friend cuûa lôùp khaùc .
Ví duï 8.3
#include <iostream.h>
class truck
; // a forward declaration
class car {
int passengers;
int speed;
public:
car(int p, int s) { passengers = p; speed = s; }
int sp_greater(truck t);
};
class truck {
int weight;
int speed;
public:
truck(int w, int s) { weight = w, speed = s; }
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
61
61
// note new use of the scope resolution operator
friend int car::sp_greater(truck t);
};
/* Return positive if car speed faster than truck.
Return 0
if speeds are the same.
Return negative if truck speed faster than car. */
int car::sp_greater(truck t)
{
// Since sp_greater() is member of car, only a truck object must be passed to it.
return speed - t.speed;
}
int main()
{
int t;
car c1(6, 55), c2(2, 120);
truck t1(10000, 55), t2(20000, 72);
cout << "Comparing c1 and t1:\n";
t = c1.sp_greater(t1); // evoke as member function of car
if(t<0)
cout << "Truck is faster.\n";
else if(t==0)
cout << "Car and truck speed is the same.\n";
else cout << "Car is faster.\n";
cout << "\nComparing c2 and t2:\n";
t = c2.sp_greater(t2); // evoke as member function of car
if(t<0)
cout << "Truck is faster.\n";
else if(t==0)
cout << "Car and truck speed is the same.\n";
else cout << "Car is faster.\n";
return 0;
}
Caâu leänh
t = c1.sp_greater(t1);
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
62
62
coù theå vieát ñaày ñuû (ít duøng)
t = c1.car::sp_greater(t1);
Baøi taäp VIII
1. Coù 2 lôùp pr1 vaø pr2 ñang duøng chung moät maùy in. Chöông trình caàn bieát khi naøo
thì maùy in ñöôïc duøng bôûi ñoái töôïng naøo thuoäc moät trong hai lôùp ñoù. Haõy taïo haøm
inuse() traû veà giaù trò ñuùng khi maùy in ñang ñöôïc duøng vaø giaù trò sai khi ngöôïc laïi.
Laøm cho haøm naøy trôû thaønh haøm friend cuûa caû hai lôùp pr1 vaø pr2.
class pr1 {
int printing;
// ...
public:
pr1() { printing = 0; }
void set_print(int status) { printing = status; }
// ...
};
class pr2 {
int printing;
// ...
public:
pr2() { printing = 0; }
void set_print(int status) { printing = status; }
// ...
};
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
63
63
Baøi taäp chöông 2
1. Ñeå moät ñoái töôïng ñöôïc gaùn vaøo moät ñoái töôïng khaùc, caàn coù ñieàu kieän gì ?
class samp {
double *p;
public:
samp(double d) {
p = (double *) malloc(sizeof(double));
if(!p) exit(1); // allocation error
*p = d;
}
~samp() { free(p); }
// ...
};
// ...
samp ob1(123.09), ob2(0.0);
// ...
ob2 = ob1;
Vaán ñeà gì sinh ra do pheùp gaùn ob1 vaøo ob2 ?
2. Cho lôùp planet, haõy taïo haøm light() nhaän moät ñoái töôïng kieåu planet laøm ñoái soá traû
veà moät soá giaây caàn thieát ñeå aùnh saùng ñi töø maët trôøi ñeán haønh tinh. (Giaû söû aùnh saùng
di chuyeån vôùi vaän toác 186.000 miles/second vaø dist_from_sun tính baèng miles)
class planet {
int moons;
double dist_from_sun; // in miles
double diameter;
double mass;
public:
//...
double get_miles() { return dist_from_sun; }
};
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
64
64
3. Duøng lôùp stack, haõy vieát haøm loadstack() ñeå traû veà moät ngaên xeáp ñaõ ñöôïc naïp vaøo
caùc maãu töï alphabet (a-z). Haõy gaùn ngaên xeáp naøy cho moät ñoái töôïng khaùc khi goïi
moät chöông trình phuï vaø chöùng toû raèng noù chöùa caùc maãu töï alphabet.
4. Haõy taïo lôùp line ñeå veõ moät ñöôøng treân maøn hình. Löu tröõ ñoä daøi cuûa ñöôøng trong
moät bieán nguyeân rieâng len. Haõy cho haøm taïo löu tröõ ñoä daøi vaø veõ ñöôøng baèng caùch
duøng daáu "*". Laäp haøm huûy cuûa line ñeå xoaù ñöôøng.
5. Haõy söûa ñoåi chöông trình sau ñaây ñeå cho moïi haøm thaønh vieân ñöôïc töï ñoäng noäi
truyeán.
class myclass {
int i, j;
public:
myclass(int x, int y);
void show();
};
myclass::myclass(int x, int y)
{
i = x;
j = y;
}
void myclass::show()
{
cout << i << " " << j << "\n";
}
int main()
{
myclass count(2, 3); count.show();
return 0;
}
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
65
65
6. Haõy taïo lôùp prompt, truyeàn haøm taïo cuûa lôùp naøy moät chuoåi, ví duï "Nhaäp vaøo moät
soá nguyeân : ". Cho haøm taïo hieån thò chuoåi vaø sau ñoù nhaän vaøo moät soá nguyeân. Löu
tröõ giaù trò naøy trong moät bieán rieâng cuûa lôùp goïi laø count. Khi ñoái töôïng coù kieåu
prompt bò huûy, cho chuoâng reng count laàn.
7. Vieát chöông trình taïo moät lôùp change thöïc hieän vieäc chuyeån ñoåi inch thaønh cm.
Lôùp change coù hai bieán rieâng löu tröõ soá inch vaø giaù trò töông ñöông cuûa noù baèng cm.
Haõy truyeàn cho haøm taïo soá inch vaø hieån thò soá cm. Bieát 1 inch = 2,54 cm
8. Cho lôùp sau, vieát chöông trình chöùng toû ñoái töôïng ob ñöôïc khai baùo ñeå truyeàn giaù
trò 100 cho bieán a vaø "z" cho bieán c.
class sample {
int a;
char c;
public :
sample(int x, char c) { a = x; c = ch;}
//
...
};
9. Döïa vaøo baøi taäp 3 chöông 2, vieát chöông trình thöïc hieän haøm quaù taûi loadstack()
nhaän moät soá nguyeân goïi laø upper, laøm ñoái soá. Trong phieân baûn quaù taûi, neáu upper =
1, haõy ñöa vaøo ngaên xeáp caùc kyù töï in hoa. Ngöôïc laïi, ñöa vaøo ngaên xeáp caùc kyù töï
thöôøng.
10. Duøng lôùp strtype trong ví duï 5.4 chöông 2, haõy boå sung moät haøm friend, coù teân
get_string(), nhaän con troû veà moät ñoái töôïng kieåu strtype laøm tham soá vaø traû veà con
troû cho moät chuoåi ñöôïc troû bôûi ñoái töôïng ñoù.
11. Cho lôùp sau, haõy taïo haøm make_sum() ñeå traû veà moät ñoái töôïng kieåu summation.
Haõy laøm cho haøm naøy nhaéc ngöôì duøng nhaäp moät soá vaø sau ñoù taïo moät ñoái töôïng
nhaän giaù trò naøy vaø traû noù veà cho thuû tuïc. Vieát chöông trình thöïc hieän yeâu caàu treân.
12. Trong baøi taäp 11 treân, haøm set_sum() ñaõ khoâng ñöôïc ñònh nghiaõ noäi tuyeán töï
ñoäng trong khai baùo lôùp summation. Haõy giaûi thích taïi sao ?
Chöông 2 Lôùp, Ñoái töôïng vaø tính ñoùng goùi
66
66
13. Cho lôùp sau ñaây, haõy boå sung moät haøm friend isneg() nhaän moät tham soá loaïi
myclass vaø traû veà giaù trò ñuùng neáu num laø aâm vaø giaù trò sai neáu ngöôïc laïi.
class myclass {
int
num;
public :
myclass(int x) { num = x;}
};
14. Moät haøm friend coù theå laø nhöõng haøm friend cuûa nhieàu hôn moät lôùp ñöôïc khoâng ?
Chöông 3
Maûng , Con troû vaø Tham chieáu
•
Maûng caùc ñoái töôïng
•
Con troû ñoái töôïng
•
Con troû this
•
Toaùn töû new vaø delete
•
Tham chieáu (reference)
•
Truyeàn tham chieáu cho ñoái töôïng
•
Traû veà caùc tham chieáu
•
Caùc tham chieáu ñoäc laäp vaø caùc haïn cheá
Chöông 3 Maûng, Con troû, Tham chieáu
68
68
Chöông 3 Maûng, Con troû, Tham chieáu
69
69
I/ Maûng caùc ñoái töôïng
Caùc ñoái töôïng chính laø caùc bieán , coù caùc khaû naêng vaø thuoäc tính nhö caùc bieán thoâng
thöôøng khaùc. Do ñoù, caùc ñoái töôïng coù theå toå chöùc thaønh maûng.
Cuù phaùp khai baùo moät maûng caùc ñoái töôïng hoaøn toaøn gioáng nhö ngoân ngöõ C.
Vieäc truy caäp maûng caùc ñoái töôïng cuõng gioáng nhö maûng cuûa caùc loaïi bieán khaùc.
Ví duï 1.1
Maûng caùc ñoái töôïng
#include <iostream.h>
class samp {
int a;
public:
void set_a(int n) { a = n; }
int get_a() { return a; }
};
int main()
{
samp ob[4]
; //
khai
baùo
maûng
ñoái
töôïng
int i;
for(i=0; i<4; i++) ob[i].set_a(i);
// truy caäp maûng ñoái töôïng
for(i=0; i<4; i++) cout << ob[i].get_a( );
return 0;
}
•
Neáu kieåu lôùp coù haøm taïo, thì maûng ñoái töôïng coù theå ñöôïc khôûi ñaàu.
Ví duï 1.2
// Initialize an array.
#include <iostream.h>
class samp {
int a;
public:
samp(int n) { a = n; }
Chöông 3 Maûng, Con troû, Tham chieáu
70
70
int get_a() { return a; }
};
int main()
{
samp ob[4] = { -1, -2, -3, -4 };
int i;
for(i=0; i<4; i++) cout << ob[i].get_a() << ' ';
return 0;
}
@ Moät caùch vieát khaùc (daøi hôn)
samp ob[4] = { samp(-1), samp(- 2), samp(-3), samp(- 4) };
@ Caùch khôûi ñaàu ôû treân chæ laøm vieäc vôùi caùc maûng coù haøm taïo chæ nhaän moät ñoái soá.
•
Khôûi ñaàu maûng ñoái töôïng nhieàu chieàu.
Ví duï 1.3
// Create a two-dimensional array of objects.
#include <iostream.h>
class samp {
int a;
public:
samp(int n) { a = n; }
int get_a() { return a; }
};
int main()
{
samp ob[4][2] = { 1, 2,
3, 4,
5, 6,
7, 8 };
int i;
Chöông 3 Maûng, Con troû, Tham chieáu
71
71
for(i=0; i<4; i++) {
cout << ob[i][0].get_a() << ' ';
cout << ob[i][1].get_a() << "\n";
}
return 0;
}
•
Khi khôûi ñaàu moät maûng ñoái töôïng coù haøm taïo nhaän nhieàu ñoái soá , caàn phaûi duøng
daïng khôûi ñaàu khaùc.
Víduï 1.4
#include <iostream.h>
class samp {
int a, b;
public:
samp(int n, int m) { a = n; b = m; }
int get_a() { return a; }
int get_b() { return b; }
};
int main()
{
samp ob[4][2] = { samp(1, 2), samp(3, 4),
samp(5, 6), samp(7, 8),
samp(9, 10), samp(11, 12),
samp(13, 14), samp(15, 16) }
;
int i;
for(i=0; i<4; i++) {
cout << ob[i][0].get_a() << ' ';
cout << ob[i][0].get_b() << "\n";
cout << ob[i][1].get_a() << ' ';
cout << ob[i][1].get_b() << "\n";
}
return 0;
}
Chöông 3 Maûng, Con troû, Tham chieáu
72
72
Baøi taäp I
1. Duøng khai baùo lôùp sau ñaây ñeå taïo maûng 10 phaàn töû vaø khôûi ñaàu phaàn töû ch vôùi caùc
giaù trò töø A ñeán J. Haõy chöùng toû maûng chöùa caùc giaù trò naøy.
#include <iostream.h>
class letters {
char ch;
public:
letters(char c) { ch = c; }
char get_ch() { return ch; }
};
2. Duøng khai baùo lôùp sau ñaây ñeå taïo maûng 10 phaàn töû vaø khôûi ñaàu num vôùi caùc giaù
trò töø 1 ñeán 10 vaø haõy khôûi ñaàu spr ñoái vôùi bình phöông cuûa num.
#include <iostream.h>
class squares {
int num, sqr;
public:
squares(int a, int b) { num = a; sqr = b; }
void show() {cout << num << ' ' << sqr << "\n"; }
};
II/ Con troû ñoái töôïng
Caùc ñoái töôïng coù theå ñöôïc truy caäp thoâng qua con troû, toaùn töû -> seõ ñöôïc duøng.
Khai baùo moät con troû ñoái töôïng
gioáng nhö khai baùo moät con troû höôùng veà kieåu bieán
baát kyø. Ví duï
samp *p;
Ñeå coù ñiaï chæ cuûa moät ñoái töôïng, duøng toaùn töû & ñaët tröôùc ñoái töôïng. Ví duï
p
=
&ob;
Chöông 3 Maûng, Con troû, Tham chieáu
73
73
Ví duï 2.1
#include <iostream.h>
class myclass {
int a;
public:
myclass(int x); // constructor
int get();
};
myclass::myclass(int x)
{
a = x;
}
int myclass::get()
{
return a;
}
int main()
{
myclass ob(120); // create object
myclass *p;
// create pointer to object
p = &ob;
// put address of ob into p
cout << "Value using object: " << ob.get() << "\n" ;
cout << "Value using pointer: " << p->get();
return 0;
}
@ Vieäc taïo ra moät con troû ñoái töôïng khoâng taïo ra moät ñoái töôïng, noù chæ taïo ra moät
con troû troû veà ñoái töôïng.
Chöông 3 Maûng, Con troû, Tham chieáu
74
74
•
Soá hoïc con troû :
+ Khi taêng con troû ñoái töôïng, noù seõ troû ñeán ñoái töôïng tieáp theo.
+ Khi giaûm con troû ñoái töôïng, noù seõ troû ñeán ñoái töôïng ñöùng tröôùc.
Ví duï 2.2
// Pointers to objects.
#include <iostream.h>
class samp {
int a, b;
public:
samp(int n, int m) { a = n; b = m; }
int get_a() { return a; }
int get_b() { return b; }
};
int main()
{
samp ob[4] = {
samp(1, 2),
samp(3, 4),
samp(5, 6),
samp(7, 8)
};
int i;
samp *p;
p = ob ;
// get starting address of array
for(i=0; i<4; i++) {
cout << p->get_a() << ' ';
cout << p->get_b() << "\n";
p++;
// advance to next object
}
return 0;
}
Chöông 3 Maûng, Con troû, Tham chieáu
75
75
Baøi taäp II
1. Haõy vieát laïi ví duï 2.2 chöông 3 ñeå cho noù hieån thò noäi dung cuûa maûng ob theo thöù
töï ngöôïc laïi.
2. Haõy vieát laïi ví duï 1.3 chöông 3 ñeå truy caäp maûng hai chieàu qua con troû.
III/ Con troû this
this
laø con troû ñöôïc truyeàn töï ñoäng cho baát kyø haøm thaønh vieân naøo khi ñöôïc goïi vaø
noù laø con troû tôùi ñoái töôïng taïo ra lôøi goïi haøm.
Ví duï, cho caâu leänh ob.f1() ;
// ob laø ñoái töôïng
Haøm f1() töï ñoäng ñöôïc truyeàn con troû ob laø ñoái töôïng taïo ra lôøi goïi haøm. Con troû naøy
ñöôïc xem laø this .
Chæ coù caùc haøm thaønh vieân ñöôïc truyeàn con troû this. Haøm friend khoâng coù con troû
this
.
Con troû this coù nhieàu söû duïng, keå caû vieäc giuùp quaù taûi caùc toaùn töû.
•
Khi moät haøm thaønh vieân tham chieáu moät haøm thaønh vieân khaùc cuûa lôùp, noù thöïc
hieän maø khoâng xaùc ñònh tham chieáu vôùi hoaëc moät lôùp hoaëc moät ñaëc taû ñoái töôïng.
Ví duï 3.1
// Demonstrate the this pointer.
#include <iostream.h>
#include <string.h>
class inventory {
char item[20];
double cost;
int on_hand;
public:
inventory(char *i, double c, int o)
Chöông 3 Maûng, Con troû, Tham chieáu
76
76
{
// tham chieáu tröïc tieáp caùc bieán item[], cost, on_hand
strcpy(item, i);
cost = c;
on_hand = o;
}
void show();
};
void inventory::show()
{
cout << item;
cout << ": $" << cost;
cout << " On hand: " << on_hand << "\n";
}
int main()
{
inventory ob("wrench", 4.95, 4);
ob.show();
return 0;
}
•
Khi moät haøm thaønh vieân ñöôïc goïi, noù töï ñoäng ñöôïc truyeàn con troû this troû veà ñoái
töôïng taïo ra lôøi goïi
. Chöông trình coù theå vieát laïi :
Ví duï 3.2
#include <iostream.h>
#include <string.h>
class inventory {
// Demonstrate the this pointer.
char item[20];
double cost;
int on_hand;
public:
inventory(char *i, double c, int o)
Chöông 3 Maûng, Con troû, Tham chieáu
77
77
{
strcpy(this->item, i); // access members
this->cost = c;
// through the this
this->on_hand = o;
// pointer
}
void show();
};
void inventory::show()
{
cout << this->item; // use this to access members
cout << ": $" << this->cost;
cout << " On hand: " << this->on_hand << "\n";
}
int main()
{
inventory ob("wrench", 4.95, 4);
ob.show();
return 0;
}
Baøi taäp III
Haõy chuyeån taát caû caùc tham chieáu thích hôïp ñoái vôùi caùc thaønh vieân cuûa lôùp thaønh
tham chieáu con troû this.
#include <iostream.h>
class myclass {
int a, b;
public:
myclass(int n, int m) { a = n; b = m; }
int add() { return a+b; }
void show();
};
void myclass::show()
Chöông 3 Maûng, Con troû, Tham chieáu
78
78
{
int t;
t = add(); // call member function
cout << t << "\n";
}
int main()
{
myclass ob(10, 14);
ob.show();
return 0;
}
IV/ Toaùn töû new vaø delete
1/ Toaùn töû new duøng ñeå caáp phaùt boä nhôù ñoäng vaø toaùn töû delete duøng giaûi phoùng boä
nhôù ñaõ caáp phaùt.
Cuù phaùp
p_var = new data_type;
delete
p_var;
data_type
chæ ñònh kieåu ñoái töôïng muoán caáp phaùt boä nhôù
p_var
con troû tôùi kieåu ñoù
Gioáng nhö haøm malloc(), neáu khoâng ñuû boä nhôù theo yeâu caàu caáp phaùt thì toaùn töû
new seõ traû veà con troû NULL. Toaùn töû delete ñöôïc goïi chæ vôùi moät con troû ñaõ ñöôïc
caáp phaùt tröôùc ñoù qua toaùn töû new. Neáu goïi delete vôùi moät con troû khoâng hôïp leä, heä
thoáng caáp phaùt seõ bò huûy, vaø coù theå laøm hoûng chöông trình.
Caùc öu ñieåm
+ toaùn töû new töï ñoäng caáp phaùt boä nhôù ñeå giöõ moät ñoái töôïng coù kieåu ñöôïc chæ roõ.
+ toaùn töû new töï ñoäng traû veà moät con troû coù kieåu ñöôïc chæ roõ.
+ toaùn töû new vaø delete coù theå ñöôïc quaù taûi.
+ coù theå khôûi ñaàu ñoái töôïng ñöôïc caáp phaùt ñoäng.
Chöông 3 Maûng, Con troû, Tham chieáu
79
79
+ khoâng caàn naïp thö vieän malloc.h hoaëc stdlib.h vaøo trong chöông trình.
•
Caáp phaùt boä nhôù ñoäng ñeå giöõa moät soá nguyeân
Ví duï 4.1
// A simple example of new and delete.
#include <iostream.h>
int main()
{
int *p;
p = new int ;
// allocate room for an integer
if(!p) {
cout << "Allocation error\n";
return 1;
}
*p = 1000;
cout << "Here is integer at p: " << *p << "\n";
delete p;
// release memory
return 0;
}
•
Caáp phaùt ñoäng moät ñoái töôïng
Ví duï 4.2
// Allocating dynamic objects.
#include <iostream.h>
class samp {
int i, j;
public:
void set_ij(int a, int b) { i=a; j=b; }
Chöông 3 Maûng, Con troû, Tham chieáu
80
80
int get_product() { return i*j; }
};
int main()
{
samp *p;
p = new samp ; // allocate object
if(!p) {
cout << "Allocation error\n";
return 1;
}
p->set_ij(4, 5);
cout << "Product is: " << p->get_product() << "\n";
delete p
;
// release memory
return 0;
}
Baøi taäp IVa
1. Haõy vieát chöông trình söû duïng new ñeå caáp phaùt ñoäng moät float, moät long vaø moät
char. Cho caùc bieán ñoäng naøy nhöõng giaù trò vaø hieån thò. Sau ñoù, haõy duøng delete giaûi
phoùng taát caû boä nhôù.
2. Haõy taïo moät lôùp coù chöùa teân vaø soá ñieän thoaïi cuûa moät ngöôøi. Duøng new ñeå caáp
phaùt ñoäng moät ñoái töôïng cuûa lôùp naøy, löu teân vaø soá ñieän thoaïi vaøo ñoái töôïng ñoù roài
hieån thò.
2/ Caùc ñaëc ñieåm cuûa new vaø delete
+ caùc ñoái töôïng ñöôïc caáp phaùt ñoäng moät giaù trò ñaàu
p_var = new data_type(initial_value)
;
Chöông 3 Maûng, Con troû, Tham chieáu
81
81
+ caùc maûng ñöôïc caáp phaùt ñoäng coù theå ñöôïc taïo ra
p_var = new data_type[size]
;
p_var troû tôùi ñaàu maûng coù phaàn töû size coù kieåu ñöôïc chæ roõ.
Vì lyù do kyõ thuaät, khoâng theå khôûi ñaàu moät maûng ñaõ ñöôïc caáp phaùt ñoäng.
+ ñeå huûy boû maûng ñaõ ñöôïc caáp phaùt ñoäng
delete [] p_var
;
p_var seõ ñöôïc giaûi phoùng moät laàn.
•
caáp phaùt boä nhôù cho moät soá nguyeân vaø khôûi ñaàu boä nhôù ñoù
Ví duï 4.3
// An example of initializing a dynamic variable.
#include <iostream.h>
int main()
{
int *p;
p = new int(9) ; // give initial value of 9
if(!p) {
cout << "Allocation error\n";
return 1;
}
cout << "Here is integer at p: " << *p << "\n";
delete p; // release memory
return 0;
}
•
truyeàn caùc giaù trò ñaàu cho moät ñoái töôïng ñöôïc caáp phaùt ñoäng
Chöông 3 Maûng, Con troû, Tham chieáu
82
82
Ví duï 4.4
// Allocating dynamic objects.
#include <iostream.h>
class samp {
int i, j;
public:
samp(int a, int b) { i=a; j=b; }
int get_product() { return i*j; }
};
int main()
{
samp *p;
p = new samp(6, 5);
// allocate object with initialization
if(!p) {
cout << "Allocation error\n";
return 1;
}
cout << "Product is: " << p->get_product() << "\n";
delete p;
return 0;
}
•
Caáp phaùt moät maûng soá nguyeân
Ví duï 4.5
// A simple example of new and delete.
#include <iostream.h>
int main()
{
int *p;
Chöông 3 Maûng, Con troû, Tham chieáu
83
83
p = new int [5]; // allocate room for 5 integers
// always make sure that allocation succeeded
if(!p) {
cout << "Allocation error\n";
return 1;
}
int i;
for(i=0; i<5; i++) p[i] = i;
for(i=0; i<5; i++) {
cout << "Here is integer at p[" << i << "]: ";
cout << p[i] << "\n";
}
delete [] p;
// release memory
return 0;
}
•
Taïo moät maûng ñoäng caùc ñoái töôïng
Ví duï 4.6
// Allocating dynamic objects.
#include <iostream.h>
class samp {
int i, j;
public:
void set_ij(int a, int b) { i=a; j=b; }
int get_product() { return i*j; }
};
int main()
Chöông 3 Maûng, Con troû, Tham chieáu
84
84
{
samp *p;
int i;
p = new samp [10];
// allocate object array
if(!p) {
cout << "Allocation error\n";
return 1;
}
for(i=0; i<10; i++)
p[i].set_ij(i, i);
for(i=0; i<10; i++) {
cout << "Product [" << i << "] is: ";
cout << p[i].get_product() << "\n";
}
delete [] p
;
return 0;
}
•
Khi con troû ñoái töôïng p ñöôïc giaûi phoùng, haøm huûy cuûa moãi phaàn töû ñöôïc goïi
Ví duï 4.7
// Allocating dynamic objects.
#include <iostream.h>
class samp {
int i, j;
public:
void set_ij(int a, int b) { i=a; j=b; }
~samp() { cout << "Destroying...\n"; }
int get_product() { return i*j; }
};
int main()
Chöông 3 Maûng, Con troû, Tham chieáu
85
85
{
samp *p;
int i;
p = new samp [10];
// allocate object array
if(!p) {
cout << "Allocation error\n";
return 1;
}
for(i=0; i<10; i++)
p[i].set_ij(i, i);
for(i=0; i<10; i++) {
cout << "Product [" << i << "] is: ";
cout << p[i].get_product() << "\n";
}
delete [] p
;
return 0;
}
@ Keát quaû cuûa chöông trình coù gì khaùc so vôùi ví duï 4.6 ?
Baøi taäp IVb
1. Haõy chuyeån ñoåi ñoaïn chöông trình sau ñeå duøng toaùn töû new
char *p;
p = (char *) malloc(100);
// ...
strcpy(p, "This is a test");
2/ Söû duïng toaùn töû new, caáp phaùt moät double vaø cho gaí trò ñaàu laø -3.1416
V/ Tham chieáu (reference)
Chöông 3 Maûng, Con troû, Tham chieáu
86
86
1/ Moät tham chieáu laø moät con troû aån taùc ñoäng nhö moät teân khaùc ñoái vôùi moät bieán.
Khai baùo : data_type &var
Caùch söû duïng :
+ Moät tham chieáu coù theå ñöôïc truyeàn cho haøm (goïi laø tham soá tham chieáu) .
+ Moät tham chieáu coù theå ñöôïc traû veà bôûi haøm.
+ Moät tham chieáu ñoäc laäp coù theå ñöôïc taïo ra.
•
Hoaït ñoäng cuûa tham soá tham chieáu (reference parameter)
Ví duï 5.1
#include <iostream.h>
void f(int *n);
// use a pointer parameter
int main()
{
int i = 0;
f(&i);
cout << "Here is i's new value: " << i << '\n';
return 0;
}
void f(int *n)
{
*n = 100; // put 100 into the argument pointed to by n
}
Haøm f() ñöôïc goïi laø ñòa chæ cuûa i trong main(). Do ñoù sau khi haøm f() traû veà, i coù giaù
trò 100.
Chöông trình naøy chöùng toû caùch con troû ñöôïc duøng nhö moät tham soá ñeå taïo ra moät cô
cheá truyeàn tham soá goïi baèng tham chieáu
.
•
Quaù trình treân coù theå thöïc hieän töï ñoäng baèng caùch duøng tham soá tham chieáu
Chöông 3 Maûng, Con troû, Tham chieáu
87
87
Ví duï 5.2
#include <iostream.h>
void f(int &n) ;
// declare a reference parameter
int main()
{
int i = 0;
f(i);
cout << "Here is i's new value: " << i << '\n';
// giaù trò cuûa i = ?
return 0;
}
// f() now uses a reference parameter
void f(int &n)
{
// notice that no * is needed in the following statement
n = 100; // put 100 into the argument used to call f()
}
n laø moät bieán tham chieáu
f() ñöôïc khai baùo nhö moät tham soá tham chieáu, ñiaï chæ ñoái vôùi soá ñöôïc truyeàn töï
ñoäng cho f().
2/ Ñaëc tính
•
Khi söû duïng tham soá tham chieáu , trình bieân dòch seõ töï ñoäng truyeàn ñòa chæ cuûa
bieán ñöôïc duøng nhö ñoái soá. Khoâng caàn taïo ra ñiaï chæ cuûa ñoái soá baèng caùch ñaët
tröôùc noù kyù töï &.
•
Beân trong haøm, trình bieân dòch töï ñoäng duøng bieán ñöôïc troû tôùi bôûi tham soá tham
chieáu. Khoâng caàân duøng kyù töï *. Do ñoù, moät tham soá tham chieáu hoaøn toaøn thöïc
hieän töï ñoäng cô cheá truyeàn ñoái soá baèng caùch goïi tham chieáu.
•
Khoâng theå thay ñoåi nhöõng gì maø moät tham chieáu troû tôùi.
3/ Öu ñieåm cuûa tham soá tham chieáu
Chöông 3 Maûng, Con troû, Tham chieáu
88
88
+ Töø quan ñieåm thöïc haønh, khoâng caàn nhôù truyeàn ñiaï chæ cuûa moät ñoái soá .
+ Tham soá tham chieáu taïo ra moät giao dieän ñeïp hôn so vôùi caùch duøng cô cheá con troû.
+ Khi moät ñoái töôïng ñöôïc truyeàn cho moät haøm nhö moät tham chieáu thì khoâng coù baûn
sao ñöôïc thöïc hieän.
•
Duøng caùc tham chieáu ñeå trao ñoåi 2 ñoái soá nguyeân
Ví duï 5.3
#include <iostream.h>
void swapargs(int &x, int &y);
int main()
{
int i, j;
i = 10;
j = 19;
cout << "i: " << i << ", ";
cout << "j: " << j << "\n";
swapargs(i, j);
cout << "After swapping: ";
cout << "i: " << i << ", ";
cout << "j: " << j << "\n";
return 0;
}
void swapargs(int &x, int &y)
{
int t;
t = x; x = y;
y = t;
}
Neáu duøng con troû thì haøm swapargs() ñöôïc vieát laïi nhö sau :
void swapargs(int *x, int *y)
Chöông 3 Maûng, Con troû, Tham chieáu
89
89
{
int t;
t = *x;
*x = *y;
*y = t;
}
•
Haøm round() laøm troøn moät giaù trò double. Giaù trò troøn ñöôïc truyeàn bôûi tham
chieáu.
Ví duï 5.4
#include <iostream.h>
#include <math.h>
void round(double &num);
int main()
{
double i = 100.4;
cout << i << " rounded is ";
round(i);
cout << i << "\n";
i = 10.9;
cout << i << " rounded is ";
round(i);
cout << i << "\n";
return 0;
}
void round(double &num)
{
double frac;
double val;
Chöông 3 Maûng, Con troû, Tham chieáu
90
90
// decompose num into whole and fractional parts
frac = modf(num, &val);
if(frac < 0.5) num = val;
else num = val+1.0;
}
Baøi taäp V
1. Haõy vieát haøm neg() ñeå ñaûo ngöôïc daáu cuûa caùc tham soá nguyeân. Theo hai caùch :
+ duøng tham soá con troû
+ duøng tham soá tham chieáu
2. Tìm loãi sai trong chöông trình sau :
// This program has an error.
#include <iostream.h>
void triple(double &num);
int main()
{
double d = 7.0;
triple(&d);
cout << d;
return 0;
}
// Triple num's value.
void triple(double &num)
{
num = 3 * num;
}
VI/ Truyeàn tham chieáu cho ñoái töôïng
Chöông 3 Maûng, Con troû, Tham chieáu
91
91
Trong chöông 2, khi moät ñoái töôïng ñöôïc truyeàn cho moät haøm baèng caùch duøng cô cheá
truyeàn tham soá goïi giaù trò, moät baûn sao ñoái töôïng ñöôïc taïo ra. Khi haøm traû veà, haøm
huûy cuûa baûn sao ñoái töôïng ñöôïc goïi, ñieàu naøy coù theå sinh ra nhöõng vaán ñeà nghieâm
troïng, chaúng haïn haøm huûy giaûi phoùng boä nhôù ñoäng.
Khi truyeàn ñoái soá baèng tham chieáu, khoâng coù baûn sao ñoái töôïng ñöôïc taïo ra, do ñoù
haøm huûy cuûa noù khoâng ñöôïc goïi khi caùc haøm traû veà.
Tuy nhieân, nhöõng thay ñoåi ñoái vôùi ñoái töôïng ôû beân trong haøm coù aûnh höôûng ñeán ñoái
töôïng ñöôïc duøng nhö ñoái soá.
Khi moät ñoái töôïng ñöôïc truyeàn bôûi tham chieáu thì toaùn töû truy caäp thaønh vieân vaãn laø
toaùn töû ñieåm (.) chöù khoâng phaûi toaùn töû muõi teân (->) .
•
Truyeàn ñoái töôïng baèng giaù trò cho haøm ñöôïc goïi f()
Ví duï 6.1
#include <iostream.h>
class myclass {
int who;
public:
myclass(int n) {
who = n;
cout << "Constructing " << who << "\n";
}
~myclass() { cout << "Destructing " << who << "\n"; }
int id() { return who; }
};
// o is passed by value.
void f(myclass o)
{
cout << "Received " << o.id() << "\n";
}
int main()
Chöông 3 Maûng, Con troû, Tham chieáu
92
92
{
myclass x(1);
f(x);
return 0;
}
Keát quaû cuûa chöông trình
Constructing
1
Received
1
Destructing
1
Destructing
1
Giaûi thích keát quaû ?
•
Truyeàn ñoái töôïng baèng tham chieáu cho haøm ñöôïc goïi f()
Ví duï 6.2
#include <iostream.h>
class myclass {
int who;
public:
myclass(int n) {
who = n;
cout << "Constructing " << who << "\n";
}
~myclass() { cout << "Destructing " << who << "\n"; }
int id() { return who; }
};
// Now, o is passed by reference.
void f(myclass &o)
{
// note that . operator is still used!!!
cout << "Received " << o.id() << "\n";
Chöông 3 Maûng, Con troû, Tham chieáu
93
93
}
int main()
{
myclass x(1);
f(x);
return 0;
}
Keát quaû cuûa chöông trình
Constructing
1
Received
1
Destructing
1
Giaûi thích keát quaû ?
Baøi taäp VI
1. Tìm loãi sai trong chöông trình sau. Söûa chöông trình theo caùc duøng tham soá tham
chieáu.
// This program has an error.
#include <iostream.h>
#include <string.h>
#include <stdlib.h>
class strtype {
char *p;
public:
strtype(char *s);
~strtype() { delete [] p; }
char *get() { return p; }
};
strtype::strtype(char *s)
Chöông 3 Maûng, Con troû, Tham chieáu
94
94
{
int l;
l = strlen(s)+1;
p = new char [l];
if(!p) {
cout << "Allocation error\n";
exit(1);
}
strcpy(p, s);
}
void show(strtype x)
{
char *s;
s = x.get();
cout << s << "\n";
}
int main()
{
strtype a("Hello"), b("There");
show(a);
show(b);
return 0;
}
VII/ Traû veà caùc tham chieáu
Chöông 3 Maûng, Con troû, Tham chieáu
95
95
Moät haøm coù theå traû veà moät tham chieáu. Ñieàu naøy coù ích khi quaù taûi moät soá loaïi toaùn
töû naøo ñoù.
Moät haøm cuõng coù theå ñöôïc söû duïng ôû beân traùi cuûa caâu leänh gaùn.
•
Haøm traû veà moät tham chieáu.
Ví duï 7.1
// A simple example of a function returning a reference.
#include <iostream.h>
int &f(); // return a reference
int x;
int main()
{
f() = 100; // assign 100 to reference returned by f()
cout << x << "\n";
return 0;
}
// Return an int reference.
int &f()
{
return x; // returns a reference to x
}
Beân trong haøm f(), caâu leänh return x khoâng traû veà giaù trò cuûa bieán toaøn cuïc, nhöng
noù töï ñoäng traû veà ñiaï chæ cuûa x döôùi daïng tham chieáu.
•
Haøm traû veà moät tham chieáu, phaûi caån thaän khi ñoái töôïng tham chieáu khoâng ra
ngoaøi phaïm vi.
Chöông 3 Maûng, Con troû, Tham chieáu
96
96
Ví duï 7.2
// Return an int reference.
int &f()
{
int x;
// x is now a local variable
return x; // returns a reference to x
}
Do x laø bieán cuïc boä, seõ ra khoûi phaïm vi khi f() traû veà, nghiaõ laø tham chieáu ñöôïc traû
veà bôûi f() laø voâ duïng.
•
Moät öùng duïng cuûa haøm traû veà moät tham chieáu duøng kieåm tra giôùi haïn bieân cuûa
maûng.
Ví duï 7.3
// A simple bounded array example.
#include <iostream.h>
#include <stdlib.h>
class array {
int size;
char *p;
public:
array(int num);
~array() { delete [] p; }
char &put(int i);
char get(int i);
};
array::array(int num)
{
p = new char [num];
if(!p) {
cout << "Allocation error\n";
exit(1);
}
size = num;
Chöông 3 Maûng, Con troû, Tham chieáu
97
97
}
// Put something into the array.
char &array::put(int i)
{
if(i<0 || i>=size) {
cout << "Bounds error!!!\n";
exit(1);
}
return p[i]; // return reference to p[i]
}
// Get something from the array.
char array::get(int i)
{
if(i<0 || i>=size) {
cout << "Bounds error!!!\n";
exit(1);
}
return p[i]; // return character
}
int main()
{
array a(10);
a.put(3) = 'X';
a.put(2) = 'R';
cout << a.get(3) << a.get(2);
cout << "\n";
// now generate run-time boundary error
a.put(11) = '!';
return 0;
}
Chöông 3 Maûng, Con troû, Tham chieáu
98
98
Baøi taäp VII
1. Haõy vieát chöông trình taïo maûng an toaøn hai chieàu 2x3 caùc soá nguyeân.
2. Ñoaïn chöông trình sau coù ñuùng khoâng ? Taïi sao ?
int &f();
.
.
.
int *x;
x = f();
VIII/ Caùc tham chieáu ñoäc laäp vaø caùc haïn cheá
1/ Tham chieáu ñoäc laäp (independent reference) laø moät bieán tham chieáu coù taùc duïng
chæ laø moät teân khaùc cho moät bieán khaùc.
Tham chieáu ñoäc laäp phaûi ñöôïc khôûi ñaàu khi khai baùo, do caùc tham chieáu khoâng theå
ñöôïc gaùn nhöõng giaù trò môùi.
Caùc laäp trình vieân thöôøng ít söû duïng tham chieáu ñoäc laäp.
2/ Moät soá haïn cheá
+ khoâng theå tham chieáu ñeán moät tham chieáu khaùc.
+ khoâng theå coù ñiaï chæ cuûa tham chieáu.
+ khoâng theå taïo moät maûng caùc tham chieáu
+ khoâng theå tham chieáu moät tröôøng bit.
+ caùc tham chieáu phaûi ñöôïc khôûi ñaàu tröø khi chuùng laø caùc thaønh vieân cuûa lôùp, laø caùc
giaù trò traû veà hoaëc laø caùc tham soá cuûa haøm.
•
Chöông trình coù moät tham chieáu ñoäc laäp
Chöông 3 Maûng, Con troû, Tham chieáu
99
99
Ví duï 8.1
#include <iostream.h>
int main()
{
int x;
int &ref = x;
// create an independent reference
x = 10;
// these two statements
ref = 10;
// are functionally equivalent
ref = 100;
// this prints the number 100 twice
cout << x << ' ' << ref << "\n";
return 0;
}
•
Moät tham chieáu ñoäc laäp coù theå tham chieáu ñeán moät haèng.
Ví duï 8.2
const int &ref = 10
;
Baøi taäp chöông 3
Chöông 3 Maûng, Con troû, Tham chieáu
100
100
1. Cho lôùp sau, haõy taïo moät maûng hai chieàu 3x4 vaø cho moãi ñoái töôïng trong maûng
moät giaù trò ñaàu.
class a_type {
double a, b;
public:
a_type(double x, double y) {
a = x;
b = y;
}
void show() { cout << a << ' ' << b << "\n"; }
};
2. Haõy thay ñoåi lôøi giaûi ñoái vôùi baøi toaùn treân ñeå coù theå truy caäp maûng baèng caùch
duøng con troû.
3. Haõy taïo haøm recip() nhaän moät tham soá tham chieáu double. Haõy cho haøm naøy thay
ñoåi giaù trò cuûa tham soá ñoù. Haõy vieát moät chöông trình cho haøm naøy hoaït ñoäng.
4. Haõy söûa ñoåi chöông trình sau vôùi toaùn töû new vaø delete
#include <iostream.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
class strtype {
char *p;
int len;
public:
strtype(char *ptr);
~strtype();
void show();
};
strtype::strtype(char *ptr)
{
Chöông 3 Maûng, Con troû, Tham chieáu
101
101
len = strlen(ptr);
p = (char *) malloc(len+1);
if(!p) {
cout << "Allocation error\n";
exit(1);
}
strcpy(p, ptr);
}
strtype::~strtype()
{
cout << "Freeing p\n";
free(p);
}
void strtype::show()
{
cout << p << " - length: " << len;
cout << "\n";
}
int main()
{
strtype s1("This is a test."), s2("I like C++.");
s1.show();
s2.show();
return 0;
}
5. Haõy söûa ñoåi chöông trình treân ñeå duøng vôùi tham chieáu
Chöông 4
Quaù taûi haøm
•
Quaù taûi haøm taïo
•
Haøm taïo baûn sao
•
Haøm vôùi caùc ñoái soá maëc ñònh
•
Tính khoâng xaùc ñònh khi quaù taûi haøm
•
Ñiaï chæ cuûa haøm quaù taûi
Chöông 4 Quaù taûi haøm
104
104
Chöông 4 Quaù taûi haøm
105
105
I/ Quaù taûi haøm taïo (
constructor overloading )
Coù theå quaù taûi haøm taïo cuûa moät lôùp, nhöng khoâng quaù taûi haøm huûy.
Haøm taïo cuûa lôùp phaûi phuø hôïp vôùi caùch maø ñoái töôïng cuûa lôùp ñoù ñöôïc khai baùo. Neáu
khoâng loãi thôøi gian bieân dòch seõ xaûy ra.
Coù 3 lyù do caàn quaù taûi haøm taïo :
+ ñeå coù tính linh hoaït
+ ñeå hoå trôï maûng
+ ñeå taïo caùc haøm taïo baûn sao
Haïn cheá : neáu thöïc hieän quaù taûi nhieàu laàn coù theå taïo ra taùc duïng huûy hoaïi treân lôùp.
•
Quaù taûi haøm taïo vôùi khôûi ñaàu moät ñoái töôïng hoaëc khoâng khôûi ñaàu ñoái töôïng
Ví duï 1.1
#include <iostream.h>
class myclass {
int x;
public:
// overload constructor two ways
myclass() { x = 0; }
// no initializer
myclass(int n) { x = n; }
// initializer
int getx() { return x; }
};
int main()
{
myclass o1(10);
// declare with initial value
myclass o2;
// declare without initializer
cout << "o1: " << o1.getx() << '\n';
cout << "o2: " << o2.getx() << '\n';
return 0;
}
Chöông 4 Quaù taûi haøm
106
106
•
Quaù taûi haøm taïo ñeå cho caùc ñoái töôïng rieâng leõ laãn caùc maûng ñoái töôïng xaûy ra
trong chöông trình.
Ví duï 1.2
#include <iostream.h>
class myclass {
int x;
public:
// overload constructor two ways
myclass() { x = 0; }
// no initializer
myclass(int n) { x = n; }
// initializer
int getx() { return x; }
};
int main()
{
myclass o1[10];
// declare array without initializers
myclass o2[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // declare with initializers
int i;
for(i=0; i<10; i++) {
cout << "o1[" << i << "]: " << o1[i].getx();
cout << '\n';
cout << "o2[" << i << "]: " << o2[i].getx();
cout << '\n';
}
return 0;
}
•
Quaù taûi haøm taïo giuùp laäp trình vieân choïn phöông phaùp thuaän lôïi nhaát ñeå khôûi
ñaàu moät ñoái töôïng.
Chöông 4 Quaù taûi haøm
107
107
Ví duï 1.3
#include <iostream.h>
#include <stdio.h>
// included for sscanf()
class date {
int day, month, year;
public:
date(char *str);
date (int m, int d, int y) {
day = d;
month = m;
year = y;
}
void show() {
cout << month << '/' << day << '/';
cout << year << '\n';
}
};
date::date(char *str)
{
sscanf(str, "%d%*c%d%*c%d", &month, &day, &year);
}
int main()
{
// construct date object using string
date sdate("12/31/99");
// construct date object using integers
date idate(12, 31, 99);
sdate.show();
idate.show();
return 0;
}
Chöông 4 Quaù taûi haøm
108
108
•
Quaù taûi haøm taïo khi maûng ñoäng cuûa lôùp ñöôïc caáp phaùt. Ñieàu naøy giuùp giaûi
quyeát haïn cheá trong chöông 3, phaàn IV/2, moät maûng ñoäng khoâng theå ñöôïc khôûi
ñaàu, xem ví duï 4.6.
Ví duï 1.4
#include <iostream.h>
class myclass {
int x;
public:
// overload constructor two ways
myclass() { x = 0; }
// no initializer
myclass(int n) { x = n; }
// initializer
int getx() { return x; }
void setx(int n) { x = n; }
};
int main()
{
myclass *p;
myclass ob(10);
// initialize single variable
p = new myclass[10]; // can't use initializers here
if(!p) {
cout << "Allocation error\n";
return 1;
}
int i;
// initialize all elements to ob
for(i=0; i<10; i++)
p[i] = ob
;
for(i=0; i<10; i++) {
cout << "p[" << i << "]: " << p[i].getx();
cout << '\n';
}
Chöông 4 Quaù taûi haøm
109
109
return 0;
}
Baøi taäp I
1. Cho lôùp sau, haõy boå sung hai haøm taïo. Haøm taïo thöù nhaát khoâng nhaän tham soá,
haøm naøy duøng toaùn töû new caáp phaùt 255 bytes boä nhôù, khôûi ñaàu boä nhôù nhö moät
chuoãi roãng vaø cho len = 255. Haøm taïo thöù hai nhaän hai tham soá, tham soá thöù nhaát laø
chuoãi duøng ñeå khôûi ñaàu vaø tham soá kia laø soá byte ñeå caáp phaùt. Cho phieân baûn naøy
caáp phaùt löôïng boä nhôù ñaõ ñöôïc chæ roõ vaø cheùp chuoåi vaøo boä nhôù.
Thöïc hieän vieäc kieåm tra giôùi haïn bieân caàn thieát vaø chöùng toû caùc haøm taïo seõ hoaït
ñoäng qua moät chöông trình ngaén.
class strtype {
char *p;
int len;
public:
char *getstring() { return p; }
int getlength() { return len; }
};
2. Töø baøi taäp II, 2 chöông 2, boå sung haøm taïo khoâng nhaän tham soá vaø moät phieân baûn
ñöôïc quaù taûi ñeå nhaän giôø heä thoáng döôùi daïng ñöôïc traû veà bôûi haøm chuaån clock().
II/ Taïo vaø söû duïng haøm taïo baûn sao
(copy constructor)
1/ Khaùi nieäm
Haøm taïo baûn sao
laø kieåu ñaëc bieät cuûa haøm taïo ñöôïc quaù taûi.
Khi moät ñoái töôïng ñöôïc truyeàn cho moät haøm, baûn sao töøng bit moät cuûa ñoái töôïng ñoù
ñöôïc taïo ra vaø ñöôïc truyeàn cho tham soá cuûa haøm ñeå nhaän ñoái töôïng.
Chöông 4 Quaù taûi haøm
110
110
Tuy nhieân, coù nhöõng tröôøng hôïp trong ñoù baûn sao ñoàng nhaát laø nhö khoâng mong
muoán.
Chaúng haïn, neáu ñoái töôïng coù con troû tôùi boä nhôù ñöôïc caáp phaùt, thì baûn sao seõ troû tôùi
cuøng boä nhôù
nhö ñoái töôïng goác ñaõ laøm. Do ñoù, neáu baûn sao taïo ra söï thay ñoåi cho noäi
dung boä nhôù thì noù cuõng seõ ñöôïc thay ñoåi ñoái vôùi ñoái töôïng goác. Khi moät haøm keát
thuùc, baûn sao seõ bò huûy vaø haøm huûy cuûa noù ñöôïc goïi. Ñieàu naøy daãn ñeán nhöõng taùc
duïng khoâng mong muoán laøm aûnh höôûng ñeán ñoái töôïng goác.
Khi moät ñoái töôïng ñöôïc traû veà töø moät haøm tình traïng töông töï cuõng seõ xaûy ra. Trình
bieân dòch seõ taïo ra moät ñoái töôïng taïm ñeå giöõ baûn sao cuûa giaù trò do haøm traû veà. Ñoái
töôïng taïm naøy seõ ra khoûi phaïm vi moät khi giaù trò ñöôïc traû veà cho thuû tuïc goïi, khieán
haøm huûy cuûa ñoái töôïng taïm ñöôïc goïi. Neáu haøm huûy huûy boû thöù gì caàn cho thuû tuïc
goïi, chaúng haïn noù giaûi phoùng boä nhôù caáp phaùt ñoäng, thì raéc roái seõ xaûy ra.
Nhö vaäy, coát loõi cuûa vaán ñeà treân laø baûn sao töøng bit cuûa ñoái töôïng ñöôïc taïo ra vaø
thöïc hieän
. Ñeå ngaên chaën vaán ñeà naøy, laäp trình vieân caàn xaùc ñònh chính xaùc nhöõng gì
xaûy ra khi baûn sao cuûa moät ñoái töôïng ñöôïc thöïc hieän ñeå traùnh ñöôïc nhöõng taùc duïng
khoâng mong muoán.
Haøm taïo baûn sao seõ giaûi quyeát ñöôïc vaán ñeà treân. Khi ñònh nghóa haøm taïo baûn sao,
laäp trình vieân coù theå hoaøn toaøn kieåm soaùt chính xaùc nhöõng gì xaûy ra khi baûn sao cuûa
moät ñoái töôïng ñöôïc thöïc hieän.
•
Caàn phaân bieät hai tröôøng hôïp trong ñoù giaù trò cuûa moät ñoái töôïng ñöôïc truyeàn cho
ñoái töôïng khaùc :
+ Tröôøng hôïp thöù nhaát laø pheùp gaùn.
+ Tröôøng hôïp thöù hai laø söï khôûi ñaàu, coù theå xaûy ra theo 3 caùch :
- Khi moät ñoái töôïng ñöôïc duøng ñeå khôûi ñaàu moät ñoái töôïng khaùc trong
caâu leänh khai baùo.
- Khi moät ñoái töôïng ñöôïc truyeàn nhö tham soá cho haøm.
- Khi moät ñoái töôïng taïm ñöôïc taïo ra duøng ñeå laøm giaù trò traû veà bôûi moät haøm.
Haøm taïo baûn sao chæ aùp duïng cho söï khôûi ñaàu. Noù khoâng aùp duïng cho pheùp gaùn.
Haøm taïo baûn sao khoâng aûnh höôûng ñeán caùc pheùp gaùn.
Chöông 4 Quaù taûi haøm
111
111
2/ Cuù phaùp
•
Daïng toång quaùt cuûa haøm taïo baûn sao
classname(const classname &obj) {
// body of constructor
}
obj
laø moät tham chieáu tôùi moät ñoái töôïng ñöôïc duøng ñeå khôûi ñaàu moät ñoái töôïng
khaùc
•
Daïng môû roäng cuûa haøm taïo baûn sao (coù nhieàu ñoái soá)
classname(const classname &obj, int x = 0) {
// body of constructor
}
Ñoái soá thöù nhaát laø moät tham chieáu tôùi ñoái töôïng ñöôïc sao cheùp, vaø caùc ñoái töôïng
khaùc ñeàu maëc ñònh. Tính linh hoaït naøy cho pheùp taïo ra caùc haøm taïo baûn sao coù
nhöõng coâng duïng khaùc.
Ví duï
, lôùp ñöôïc goïi laø myclass vaø y laø ñoái töôïng cuûa myclass thì caùc leänh sau ñaây seõ
duøng ñeán haøm taïo baûn sao cuûa myclass :
myclass x = y;
// y explicitly initializing x
func1(y);
// y passed as a parameter
y = func2();
// y receiving a returned object
Trong hai tröôøng hôïp ñaàu, moät tham chieáu tôùi y seõ ñöôïc truyeàn cho haøm taïo baûn sao.
Tröôøng hôïp thöù ba, moät tham chieáu tôùi ñoái töôïng ñöôïc traû veà bôûi func2() seõ ñöôïc
truyeàn cho haøm taïo baûn sao.
•
Taïo moät maûng soá nguyeân "an toaøn" coù kieåm tra giôùi haïn bieân
Ví duï 2.1
Chöông 4 Quaù taûi haøm
112
112
/* This program creates a "safe" array class. Since space for the array is
dynamically allocated, a copy constructor is provided to allocate memory when
one array object is used to initialize another. */
#include <iostream.h>
#include <stdlib.h>
class array {
int *p;
int size;
public:
array(int sz) {
// constructor
p = new int[sz];
if(!p) exit(1);
size = sz;
cout << "Using 'normal' constructor\n";
}
~array() {delete [] p;}
// copy constructor
array(const array &a);
void put(int i, int j) {
if(i>=0 && i<size) p[i] = j;
}
int get(int i) {
return p[i];
}
};
/* Copy constructor.
In the following, memory is allocated specifically for the copy, and the address of
this memory is assigned to p. Therefore, p is not pointing to the same dynamically
allocated memory as the original object. */
array::array(const array &a)
{
Chöông 4 Quaù taûi haøm
113
113
int i;
size = a.size;
p = new int[a.size]; // allocate memory for copy
if(!p) exit(1);
for(i=0; i<a.size; i++) p[i] = a.p[i]; // copy contents
cout << "Using copy constructor\n";
}
int main()
{
array num(10); // this calls "normal" constructor
int i;
// put some values into the array
for(i=0; i<10; i++)
num.put(i, i);
// display num
for(i=9; i>=0; i--) cout << num.get(i);
cout << "\n";
// create another array and initialize with num
array x = num; // this invokes copy constructor
// display x
for(i=0; i<10; i++)
cout << x.get(i);
return 0;
}
@ Coù nhaän xeùt gì veà keát quaû khi chöông trình naøy khoâng söû duïng haøm taïo baûn sao ?
@ Nhöõng caâu leänh sau khoâng theå goïi ñöôïc haøm taïo baûn sao, taïi sao ?
array a(10);
array b(10);
b = a;
// does not call copy constructor
Chöông 4 Quaù taûi haøm
114
114
•
Haøm taïo baûn sao giuùp ngaên ngöøa moät soá vaán ñeà lieân quan ñeán vieäc truyeàn caùc
kieåu ñoái töôïng naøo ñoù cho haøm.
Ví duï 2.2
// This program has an error.
#include <iostream.h>
#include <string.h>
#include <stdlib.h>
class strtype {
char *p;
public:
strtype(char *s);
~strtype() { delete [] p; }
char *get() { return p; }
};
strtype::strtype(char *s)
{
int l;
l = strlen(s)+1;
p = new char [l];
if(!p) {
cout << "Allocation error\n";
exit(1);
}
strcpy(p, s);
}
void show(strtype x)
{
char *s;
s = x.get();
cout << s << "\n";
}
Chöông 4 Quaù taûi haøm
115
115
int main()
{
strtype a("Hello"), b("There");
show(a);
show(b);
return 0;
}
@ Haõy tìm nguyeân nhaân gaây ra loãi ?
Ví duï 2.3
Hieäu chænh chöông trình trong ví duï 2.2
/* This program uses a copy constructor to allow strtype objects to be passed to
functions. */
#include <iostream.h>
#include <string.h>
#include <stdlib.h>
class strtype {
char *p;
public:
strtype(char *s);
// constructor
strtype(const strtype &o);
// copy constructor
~strtype() { delete [] p; }
// destructor
char *get() { return p; }
};
// "Normal" constructor
strtype::strtype(char *s)
{
int l;
l = strlen(s)+1;
p = new char [l];
if(!p) {
cout << "Allocation error\n";
exit(1);
Chöông 4 Quaù taûi haøm
116
116
}
strcpy(p, s);
}
// Copy constructor
strtype::strtype(const strtype &o)
{
int l;
l = strlen(o.p)+1;
p = new char [l]; // allocate memory for new copy
if(!p) {
cout << "Allocation error\n";
exit(1);
}
strcpy(p, o.p);
// copy string into copy
}
void show(strtype x)
{
char *s;
s = x.get();
cout << s << "\n";
}
int main()
{
strtype a("Hello"), b("There");
show(a);
show(b);
return 0;
}
Chöông 4 Quaù taûi haøm
117
117
Baøi taäp II
1. Xeùt chöông trình sau, haõy giaûi thích taïi sao coù keát quaû naøy ?
Constructing
normally
Constructing normally
Constructing copy
#include <iostream.h>
class myclass {
public:
myclass();
myclass(const myclass &o);
myclass f();
};
myclass::myclass()
// Normal constructor
{
cout << "Constructing normally\n";
}
myclass::myclass(const myclass &o)
// Copy constructor
{
cout << "Constructing copy\n";
}
myclass myclass::f()
// Return an object.
{
myclass temp;
return temp;
}
int main()
{
myclass obj;
obj = obj.f();
return 0; }
Chöông 4 Quaù taûi haøm
118
118
2. Tìm loãi sai trong chöông trình vaø yeâu caàu chænh lyù ?
#include <iostream.h>
#include <stdlib.h>
class myclass {
int *p;
public:
myclass(int i);
~myclass() { delete p; }
friend int getval(myclass o);
};
myclass::myclass(int i)
{
p = new int;
if(!p) {
cout << "Allocation error\n";
exit(1);
}
*p = i;
}
int getval(myclass o)
{
return *o.p; // get value
}
int main()
{
myclass a(1), b(2);
cout << getval(a) << " " << getval(b) << "\n";
cout << getval(a) << " " << getval(b);
return 0;
}
Chöông 4 Quaù taûi haøm
119
119
III/ Söû duïng caùc ñoái soá maëc ñònh
(default argument)
•
Ñoái soá maëc ñònh
cho pheùp gaùn moät giaù trò maëc ñònh cho moät tham soá khi khoâng
coù ñoái soá töông öùng ñöôïc chæ roõ khi haøm ñöôïc goïi.
Ñoái soá maëc ñònh lieân quan ñeán söï quaù taûi haøm, söû duïng caùc ñoái soá maëc ñònh chuû
yeáu laø daïng ngaén cuûa quaù taûi haøm.
•
Ñeå gaùn moät ñoái soá maëc ñònh cho moät tham soá thì sau tham soá phaûi coù daáu baèng
vaø moät giaù trò muoán maëc ñònh neáu khoâng coù ñoái soá töông öùng khi haøm ñöôïc goïi.
Ví duï 3.1
// A simple first example of default arguments.
#include <iostream.h>
void f(int a = 0, int b = 0)
{
cout << "a: " << a << ", b: " << b;
cout << '\n';
}
int main()
{
f();
f(10);
f(10, 99);
return 0;
}
Haøm f() cho hai giaù trò maëc ñònh 0 ñoái vôùi caùc tham soá
void f(int a = 0, int b = 0);
Cuù phaùp naøy töông töï nhö khôûi ñaàu moät bieán.
Chöông 4 Quaù taûi haøm
120
120
Haøm f() coù theå goïi theo 3 caùch :
+ noù ñöôïc goïi vôí caû hai ñoái soá ñöôïc chæ roõ.
+ noù ñöôïc goïi chæ vôí ñoái soá thöù nhaát ñöôïc chæ roõ. Tröôøng hôïp naøy, b seõ maëc ñònh veà
0.
+ f() coù theå ñöôïc goïi laø khoâng coù ñoái soá , a vaø b maëc ñònh veà 0.
nghiaõ laø caùc caâu leänh sau ñeàu ñuùng :
f() ;
// a and b default to 0
f(10) ;
// a is 10, b defaults to 0
f(10, 99) ; // a is 10, b is 99
Löu yù, trong ví duï naøy, khoâng coù caùch ñeå maëc ñònh a vaø chæ roõ b .
•
Khi ñoái soá maëc ñònh ñaàu tieân ñöôïc chæ roõ, taát caû caùc tham soá theo sau cuõng phaûi
coù maëc ñònh. Ví duï moät phieân baûn khaùc cuûa f() sau ñaây seõ taïo ra loãi thôøi gian
bieân dòch :
void f(int a = 0, int b)
// wrong! b must have default, too
{
cout << "a: " << a << ", b: " << b;
cout << '\n';
}
•
Qui taéc
Khi taïo moät haøm coù moät hay nhieàu ñoái soá maëc ñònh thì nhöõng ñoái soá ñoù phaûi
chæ roõ moät laàn
hoaëc trong ñònh nghiaõ cuûa haøm hoaëc trong nguyeân maãu cuûa noù
chöù khoâng ñöôïc caû hai.
Qui taéc naøy aùp duïng ngay caû khi chæ nhaân ñoâi caùc ngaàm ñònh gioáng nhau.
•
Taát caû caùc tham soá maëc ñònh phaûi ôû beân phaûi cuûa caùc tham soá khoâng coù maëc
ñònh. Hôn nöõa, khi baét ñaàu ñònh nghóa caùc tham soá maëc ñònh, khoâng theå chæ ñònh
caùc tham soá khoâng coù maëc ñònh.
•
Vôùi caùc ñoái soá maëc ñònh, chuùng phaûi laø caùc haèng hoaëc laø caùc bieán toaøn cuïc.
Chöông 4 Quaù taûi haøm
121
121
Ví duï 3.2
Caùc ñoái soá maëc ñònh lieân quan ñeán söï quaù taûi haøm
// Compute area of a rectangle using overloaded functions.
#include <iostream.h>
// Return area of a non-square rectangle.
double rect_area(double length, double width)
{
return length * width;
}
// Return area of a square.
double rect_area(double length)
{
return length * length;
}
int main()
{
cout << "10 x 5.8 rectangle has area: ";
cout << rect_area(10.0, 5.8) << '\n';
cout << "10 x 10 square has area: ";
cout << rect_area(10.0) << '\n';
return 0;
}
Ví duï 3.3
Thöïc söï khoâng caàn coù hai haøm rect_area() khaùc nhau. Thay vaøo ñoù,
tham soá thöù hai coù theå ñöôïc maëc ñònh veà giaù trò naøo ñoù taùc ñoäng nhö coøi hieäu cho
haøm rect_area()
// Compute area of a rectangle using default arguments.
#include <iostream.h>
// Return area of a rectangle.
Chöông 4 Quaù taûi haøm
122
122
double rect_area(double length, double width = 0)
{
if(!width) width = length;
return length * width;
}
int main()
{
cout << "10 x 5.8 rectangle has area: ";
cout << rect_area(10.0, 5.8) << '\n';
cout << "10 x 10 square has area: ";
cout << rect_area(10.0) << '\n';
return 0;
}
@ Nhö vaäy, caùc ñoái soá ngaàm ñònh thöôøng ñöa ra caùch ñôn giaûn ñeå quaù taûi haøm.
•
Trong phaàn tröôùc, moät haøm taïo ñöôïc quaù taûi chiû cho pheùp taïo ra caùc ñoái töôïng
ñöôïc khôûi ñaàu vaãn khoâng ñöôïc khôûi ñaàu. Trong nhieàu tröôøng hôïp, coù theå traùnh
quaù taûi moät haøm taïo baèng caùch cho noù moät hay nhieàu ñoái soá ngaàm ñònh
.
Ví duï 3.4
#include <iostream.h>
class myclass {
int x;
public:
/* Use default argument instead of overloading myclass's constructor. */
myclass(int n = 0) { x = n; }
int getx() { return x; }
};
int main()
{
myclass o1(10); // declare with initial value
myclass o2;
// declare without initializer
Chöông 4 Quaù taûi haøm
123
123
cout << "o1: " << o1.getx() << '\n';
cout << "o2: " << o2.getx() << '\n';
return 0;
}
@ Nhö vaäy, baèng caùch cho bieán n giaù trò maëc ñònh zero, coù theå taïo ra caùc ñoái töôïng
coù caùc giaù trò ñaàu roõ raøng vaø caùc ñoái töôïng coù giaù trò maëc ñònh laø ñuû.
•
Ñoái soá maëc ñònh ñöôïc tìm thaáy khi moät tham soá ñöôïc duøng ñeå choïn moät tuøy
choïn.
Ví duï 3.5
#include <iostream.h>
#include <ctype.h>
const int ignore = 0;
const int upper = 1;
const int lower = 2;
void print(char *s, int how = -1) ;
int main()
{
print("Hello There\n", ignore);
print("Hello There\n", upper);
print("Hello There\n");
// continue in upper
print("Hello there\n", lower);
print("That's all\n");
// continue in lower
return 0;
}
/* Print a string in the specified case. Use last case specified if none is given. */
void print(char *s, int how)
{
static int oldcase = ignore;
Chöông 4 Quaù taûi haøm
124
124
// reuse old case if none specified
if(how < 0) how = oldcase;
while(*s) {
switch(how) {
case upper : cout << (char) toupper(*s);
break;
case lower : cout << (char) tolower(*s);
break;
default : cout << *s;
}
s++;
}
oldcase = how;
}
•
Thöïc söï, vieäc cung caáp ñoái soá maëc ñònh khi khoâng ñöôïc goïi seõ laøm hoûng
chöông trình vaø seõ höôùng daãn sai cho ngöôøi khaùc söû duïng haøm ñoù.
Vôùi söï quaù taûi haøm, moät laäp trình vieân thaønh thaïo seõ bieát ñöôïc khi naøo thì söû
duïng ñoái soá maëc ñònh vaø khi naøo khoâng.
Chöông 4 Quaù taûi haøm
125
125
Baøi taäp III
1. Tìm loãi sai trong nguyeân maãu haøm sau :
char *f(char *p, int x = 0 , char *q) ;
2. Tìm loãi sai trong nguyeân maãu duøng ñoái soá maëc ñònh sau :
int f(int count, int max = count) ;
3. Trong thö vieän chuaån C++ coù haøm strtol(), coù nguyeân maãu sau :
long strtol(const char *start, const **end, int base);
Haøm naøy chuyeån ñoåi chuoãi soá ñöôïc troû tôùi bôûi start thaønh soá nguyeân daøi.
Haõy taïo haøm mystrtol() hoaït ñoäng gioáng nhö strtol() vôùi ngoaïi leä laø base ñöôïc cho
moät ñoái soá maëc ñònh laø 10. Vieát chöông trình chöùng toû haøm mystrtol() hoaït ñoäng toát.
4. Haõy taïo haøm myclreol() ñeå xoaù doøng töø vò trí con troû hieän taïi ñeán cuoái doøng. Haøm
naøy coù moät tham soá chæ roõ vò trí cuûa kyù töï caàn xoaù. Neáu khoâng chæ roõ tham soá thì toaøn
boä doøng seõ töï ñoäng bò xoaù. Ngöôïc laïi, chæ xoaù nhöõng vò trí naøo ñöôïc chæ roõ bôûi tham
soá.
IV/ Söï quaù taûi vaø tính khoâng xaùc ñònh
(ambiguity)
Chöông 4 Quaù taûi haøm
126
126
Khi quaù taûi haøm, coù theå daãn ñeán tính khoâng xaùc ñònh trong chöông trình.
Tính khoâng xaùc ñònh
do quaù taûi gaây ra coù theå ñöôïc ñöa vaøo thoâng qua :
+ caùc chuyeån ñoåi kieåu
+ caùc tham soá tham chieáu
+ caùc ñoái soá maëc ñònh
+ hoaëc do chính caùc haøm ñöôïc quaù taûi
+ hoaëc do caùch goïi caùc haøm quaù taûi
Tính khoâng xaùc ñònh phaûi ñöôïc loaïi boû tröôùc khi chöông trình ñöôïc bieân dòch.
•
Tính khoâng xaùc ñònh gaây ra bôûi caùc quy taéc chuyeån ñoåi kieåu töï ñoäng trong C++
Ví duï 4.1
// This program contains an ambiguity error.
#include <iostream.h>
float f(float i)
{
return i / 2.0;
}
double f(double i)
{
return i / 3.0;
}
int main()
{
float x = 10.09;
double y = 10.09;
cout << f(x);
// unambiguous - use f(float)
cout << f(y);
// unambiguous - use f(double)
Chöông 4 Quaù taûi haøm
127
127
cout << f(10);
// ambiguous, convert 10 to double or float??
return 0;
}
@ Loãi bieân dòch coù daïng Error : Ambiguity between 'f(float)' and 'f(double)'
@ Ví duï treân minh hoïa tính khoâng xaùc ñònh coù theå xaûy ra khi moät haøm quaù taûi ñöôïc
goïi.
•
Khi haøm ñöôïc goïi vôùi kieåu ñoái soá sai, caùc quy taéc chuyeån ñoåi töï ñoäng cuûa C++
gaây ra tình traïng khoâng xaùc ñònh. Baûn thaân söï quaù taûi haøm ôû ví duï naøy töï noù
khoâng coù tính khoâng xaùc ñònh.
Ví duï 4.2
// This program is ambiguous.
#include <iostream.h>
void f(unsigned char c)
{
cout << c;
}
void f(char c)
{
cout << c;
}
int main()
{
f('c');
f(86);
// which f() is called???
return 0;
}
Chöông 4 Quaù taûi haøm
128
128
•
Tính khoâng xaùc ñònh xaûy ra do quaù taûi caùc haøm, trong ñoù coù söï khaùc bieät duy
nhaát laø moät haøm söû duïng moät tham soá tham chieáu vaø haøm kia söû duïng tham soá
maëc ñònh goïi baèng giaù trò.
Ví duï 4.3
// An ambiguous program.
#include <iostream.h>
int f(int a, int b)
{
return a+b;
}
// this is inherently ambiguous
int f(int a, int &b)
{
return a-b;
}
int main()
{
int x=1, y=2;
cout << f(x, y); // which version of f() is called???
return 0;
}
@ Loãi bieân dòch ôû haøm f(int a, int &b) coù daïng
Error : 'f(int, int &)' cannot be distinguished from 'f(int, int)'
Chöông 4 Quaù taûi haøm
129
129
•
Tính khoâng xaùc ñònh xaûy ra do quaù taûi haøm, trong ñoù coù moät hay nhieàu haøm
ñöôïc quaù taûi duøng moät ñoái soá maëc ñònh.
Ví duï 4.4
// Ambiguity based on default arguments plus overloading.
#include <iostream.h>
int f(int a)
{
return a*a;
}
int f(int a, int b = 0)
{
return a*b;
}
int main()
{
cout << f(10, 2); // calls f(int, int)
cout << f(10);
// ambiguous - call f(int) or f(int, int)???
return 0;
}
Chöông 4 Quaù taûi haøm
130
130
V/ Tìm ñiaï chæ cuûa moät haøm quaù taûi
Trong ngoân ngöõ C, ñeå bieát ñiaï chæ moät haøm, duøng con troû p troû ñeán haøm ñoù, chaúng
haïn
p = zap;
// vôùi haøm zap()
Trong ngoân ngöõ C++, vaán ñeà hôi phöùc taïp hôn bôûi vì haøm coù theå ñöôïc quaù taûi.
Cô cheá : duøng caùch khai baùo con troû xaùc ñònh ñiaï chæ cuûa haøm quaù taûi naøo seõ thu
ñöôïc.
Haøm coù söï phuø hôïp khai baùo laø haøm coù ñiaï chæ ñöôïc söû duïng.
Ví duï 5.1
/* Illustrate assigning function pointers to overloaded functions. */
#include <iostream.h>
// Output count number of spaces.
void space(int count)
{
for( ; count; count--)
cout << ' ';
}
// Output count number of chs.
void space(int count, char ch)
{
for( ; count; count--)
cout << ch;
}
int main()
{
// Create a pointer to void function with one int parameter.
void (*fp1)(int);
// Create a pointer to void function with one int parameter
Chöông 4 Quaù taûi haøm
131
131
// and one character parameter.
void (*fp2)(int, char);
fp1 = space;
// gets address of space(int)
fp2 = space;
// gets address of space(int, char)
fp1(22);
// output 22 spaces
cout << "|\n";
fp2(30, 'x');
// output 30 xs
cout << "|\n";
return 0;
}
@ Khai baùo con troû haøm phaûi phuø hôïp chính xaùc vôí moät vaø chæ moät haøm quaù taûi.
Neáu khoâng, tính khoâng xaùc ñònh seõ xaûy ra vaø gaây ra loãi thôøi gian bieân dòch.
Baøi taäp V
1. Cho hai haøm quaù taûi. Tìm ñiaï chæ cuûa moãi haøm
int dif(int a, int b)
{
return a-b;
}
float dif(float a, float b)
{
return a-b;
}
Chöông 4 Quaù taûi haøm
132
132
Baøi taäp chöông 4
1. Haõy quaù taûi haøm taïo date() trong ví duï 1.3, chöông 4 ñeå cho noù nhaän moät tham soá
kieåu time_t.
2. Tìm loãi sai trong chöông trình sau :
class samp {
int a;
public:
samp(int i) { a = i; }
// ...
}:
// ...
int main()
{
samp x, y(10);
// ...
}
3. Haõy taïo haøm reverse() nhaän hai tham soá. Tham soá thöù nhaát, goïi laø str, laø con troû
troû tôùi chuoãi maø chuoãi naøy ñöôïc ñaûo ngöôïc khi traû veà töø haøm. Tham soá thöù hai goïi laø
count vaø noù chæ roõ coù bao nhieâu kyù töï cuûa chuoãi ñeå ñaûo ngöôïc. Haõy cho count moät
giaù trò maëc ñònh ñeå baùo cho reverse() ñaûo ngöôïc toaøn boä chuoãi.
4. Tìm loãi sai trong ñoaïn chöông trình sau :
void compute(double *num, int divisor=1);
void compute(double *num);
// ...
compute(&x);
5. Haõy taïo haøm order() ñeå nhaän hai tham soá tham chieáu nguyeân. Neáu ñoái soá thöù nhaát
lôùn hôn ñoái soá thöù hai, haõy ñaûo ngöôïc hai ñoái soá. Ngöôïc laïi, khoâng taùc ñoäng naøo. Ví
duï
Chöông 4 Quaù taûi haøm
133
133
int x=1, y=0;
order(x, y);
6. Taïi sao hai haøm quaù taûi sau voán khoâng xaùc ñònh ?
int f(int a);
int f(int &a);
7. Cho lôùp sau, haõy boå sung caùc haøm taïo caàn thieát ñeå cho caû hai khai baùo trong
main() ñeàu ñuùng.
class samp {
int a;
public:
// add constructor functions
...
int get_a() { return a; }
};
int main()
{
samp ob(88);
// init ob's a to 88
samp obarray[10];
// noninitialized 10-element array
// ...
}
8. Thöïc hieän quaù taûi haøm taïo ñoái vôùi lôùp sau ñaây sao cho caùc ñoái töôïng khoâng ñöôïc
khôûi ñaàu cuõng ñöôïc taïo ra.
class myclass {
int x, y;
public :
myclass(int i, int j) {x= i; y =j;}
//
...
}
9. Qua baøi taäp 8, haõy chöùng toû coù theå khoâng quaù taûi myclass() baèng caùch duøng ñoái soá
maëc ñònh.
Chöông 4 Quaù taûi haøm
134
134
10. Cho lôùp sau ñaây, coù theå caáp phaùt ñoäng moät maûng caùc ñoái töôïng naøy khoâng ?
class test {
char *p;
int *q;
int count;
public:
test(char *x, int *y, int c) {
p = x; q = y; count = c;
}
// ...
};
Chöông 5
Quaù taûi toaùn töû
•
Quaù taûi toaùn töû ñoái vôùi lôùp
•
Quaù taûi toaùn töû nhò nguyeân
•
Quaù taûi toaùn töû quan heä & luaän lyù
•
Quaù taûi toaùn töû ñôn nguyeân
•
Haøm toaùn töû friend
•
Toaùn töû gaùn
Chöông 5 Quaù taûi toaùn töû
136
136
Chöông 5 Quaù taûi toaùn töû
137
137
I/ Quaù taûi toaùn töû
(operator overloading)
Quaù taûi toaùn töû
gioáng nhö quaù taûi haøm. Thöïc chaát quaù taûi toaùn töû chæ laø moät loaïi quaù
taûi haøm. Moät toaùn töû thöôøng ñöôïc quaù taûi ñoái vôùi moät lôùp.
Khi moät toaùn töû ñöôïc quaù taûi, toaùn töû ñoù khoâng maát yù nghóa goác cuûa noù. Theâm nöõa,
toaùn töû coøn coù theâm yù nghiaõ boå sung ñoái vôùi lôùp maø toaùn töû ñöôïc ñònh nghiaõ.
•
Ñeå quaù taûi moät toaùn töû, haõy taïo ra moät haøm toaùn töû (operator function). Thoâng
thöôøng, moät haøm toaùn töû laø moät thaønh vieân (member) hoaëc baïn (friend) cuûa lôùp
maø toaùn töû ñöôïc ñònh nghiaõ.
Cuù phaùp
return_type class_name::operator#(arg_list)
{
// operation to be performed
}
return_type kieåu traû veà cuûa moät haøm toaùn töû coù theå laø baát kyø,
thöôøng laø lôùp maø toaùn töû ñöôïc ñònh nghiaõ
class_name teân lôùp chöùa haøm toaùn töû
#
ñaïi dieän cho toaùn töû ñöôïc quaù taûi
arg_list
danh saùch caùc ñoái soá, thay ñoåi phuï thuoäc vaøo caùch maø haøm toaùn töû
ñöôïc thöïc hieän vaø kieåu toaùn töû ñöôïc quaù taûi
•
Hai haïn cheá khi quaù taûi toaùn töû :
+ thöù tuï öu tieân cuûa caùc toaùn töû khoâng thay ñoåi
+ soá toaùn haïng cuûa moät toaùn töû khoâng thay ñoåi
Haàu heát caùc toaùn töû trong C++ coù theå ñöôïc quaù taûi.
Moät soá toaùn töû khoâng theå quaù taûi nhö : :: , . , * , ?
Cuõng khoâng theå quaù taûi toaùn töû tieàn xöû lyù.
Hai toaùn töû ñöôïc quaù taûi ">>" vaø "<<" , duøng ñeå thöïc hieän caùc thao taùc nhaäp/xuaát
trong C++
•
Caùc haøm toaùn töû coù theå khoâng coù caùc ñoái soá ngaàm ñònh.
Chöông 5 Quaù taûi toaùn töû
138
138
II/ Quaù taûi toaùn töû nhò nguyeân
Khi moät haøm toaùn töû thaønh vieân quaù taûi toaùn töû nhò nguyeân, haøm seõ chæ coù moät tham
soá. Tham soá naøy seõ nhaän ñoái töôïng naèm beân phaûi toaùn töû. Ñoái töôïng beân traùi laø ñoái
töôïng taïo ra lôøi goïi. Goïi cho haøm toaùn töû vaø ñöôïc truyeàn bôûi con troû this .
Caùc haøm toaùn töû ñöôïc vieát theo nhieàu caùch khaùc nhau.
•
Quaù taûi toaùn töû "+" ñoái vôùi moät lôùp
Ví duï 2.1
// Overload the + relative to coord class.
#include <iostream.h>
class coord {
int x, y;
// coordinate values
public:
coord() { x=0; y=0; }
coord(int i, int j) { x=i; y=j; }
void get_xy(int &i, int &j) { i=x; j=y; }
coord operator+(coord ob2);
};
// Overload + relative to coord class.
coord coord::operator+(coord ob2)
{
coord temp;
temp.x = x + ob2.x;
temp.y = y + ob2.y;
return temp;
}
int main()
{
coord o1(10, 10), o2(5, 3), o3;
int x, y;
Chöông 5 Quaù taûi toaùn töû
139
139
o3 = o1 + o2;
// add two objects - this calls operator+()
o3.get_xy(x, y);
cout << "(o1+o2) X: " << x << ", Y: " << y << "\n";
return 0;
}
@ Khi traû veà moät ñoái töôïng, toaùn töû pheùp "+" cho pheùp moät chuoåi pheùp coäng, ví duï
o3 = o1 + o2 + o1 + o3;
@ Vì ñoái töôïng coord ñöôïc traû veà, caâu leänh sau ñaây cuõng hoaøn toaøn ñuùng
(o1 + o2).get_xy(x, y);
•
Quaù taûi toaùn töû "-" , "=" ñoái vôùi moät lôùp
Ví duï 2.2
// Overload the +, -, and = relative to coord class.
#include <iostream.h>
class coord {
int x, y; // coordinate values
public:
coord() { x=0; y=0; }
coord(int i, int j) { x=i; y=j; }
void get_xy(int &i, int &j) { i=x; j=y; }
coord operator+(coord ob2);
coord operator-(coord ob2);
coord operator=(coord ob2);
};
// Overload + relative to coord class.
coord coord::operator+(coord ob2)
{
coord temp;
temp.x = x + ob2.x;
Chöông 5 Quaù taûi toaùn töû
140
140
temp.y = y + ob2.y;
return temp;
}
// Overload - relative to coord class.
coord coord::operator-(coord ob2)
{
coord temp;
temp.x = x - ob2.x;
temp.y = y - ob2.y;
return temp;
}
// Overload = relative to coord.
coord coord::operator=(coord ob2)
{
x = ob2.x;
y = ob2.y;
return *this;
// return the object that is assigned
}
int main()
{
coord o1(10, 10), o2(5, 3), o3;
int x, y;
o3 = o1 + o2;
// add two objects - this calls operator+()
o3.get_xy(x, y);
cout << "(o1+o2) X: " << x << ", Y: " << y << "\n";
o3 = o1 - o2;
// subtract two objects
o3.get_xy(x, y);
cout << "(o1-o2) X: " << x << ", Y: " << y << "\n";
o3 = o1;
// assign an object
Chöông 5 Quaù taûi toaùn töû
141
141
o3.get_xy(x, y);
cout << "(o3=o1) X: " << x << ", Y: " << y << "\n";
return 0;
}
@ Vôùi haøm operator-() thöù töï cuûa caùc toaùn haïng laø quan troïng. Do A-B seõ khaùc B-A
.
Vì chính toaùn haïng beân traùi taïo ra lôøi goïi ñoái vôùi operator-() neân pheùp tröø phaûi
theo thöù töï :
x - ob2.x ;
@ Vôùi haøm toaùn töû gaùn
+ toaùn haïng beân traùi (nghiaõ laø ñoái töôïng ñöôïc gaùn cho moät giaù trò)
ñöôïc thay ñoåi bôûi pheùp toaùn.
+ haøm operator=() traû veà con troû this, nghiaõ laø haøm traû veà ñoái töôïng
seõ ñöôïc gaùn. Do ñoù caâu leänh sau cuõng hoaøn toaøn ñuùng :
o3 = o2 = o1;
•
Coù theå quaù taûi moät toaùn töû ñoái vôùi moät lôùp ñeå cho toaùn haïng beân phaûi laø moät ñoái
töôïng coù kieåu ñònh saün.
Toaùn töû "+" ñöôïc quaù taûi ñeå coäng moät giaù trò nguyeân vaø
ñoái töôïng coord.
Ví duï 2.3
// Overload + for ob + int as well as ob + ob.
#include <iostream.h>
class coord {
int x, y;
// coordinate values
public:
coord() { x=0; y=0; }
coord(int i, int j) { x=i; y=j; }
void get_xy(int &i, int &j) { i=x; j=y; }
coord operator+(coord ob2);
// ob + ob
coord operator+(int i);
// ob + int
};
// Overload + relative to coord class.
Chöông 5 Quaù taûi toaùn töû
142
142
coord coord::operator+(coord ob2)
{
coord temp;
temp.x = x + ob2.x;
temp.y = y + ob2.y;
return temp;
}
// Overload + for ob + int
coord coord::operator+(int i)
{
coord temp;
temp.x = x + i;
temp.y = y + i;
return temp;
}
int main()
{
coord o1(10, 10), o2(5, 3), o3;
int x, y;
o3 = o1 + o2;
// add two objects - this calls operator+(coord)
o3.get_xy(x, y);
cout << "(o1+o2) X: " << x << ", Y: " << y << "\n";
o3 = o1 + 100;
// add object + int - this call operator+(int)
o3.get_xy(x, y);
cout << "(o1+100) X: " << x << ", Y: " << y << "\n";
return 0;
}
Chöông 5 Quaù taûi toaùn töû
143
143
@ Caàn nhôù, khi quaù taûi moät haøm toaùn töû thaønh vieân ñeå cho moät ñoái töôïng coù theå
ñöôïc duøng trong moät pheùp toaùn coù kieåu ñònh saün, thì kieåu ñònh saün phaûi ôû beân phaûi
cuûa toaùn töû. Bôûi vì chính ñoái töôïng beân traùi taïo ra lôøi goïi cho haøm toaùn töû.
Ñieàu gì xaûy ra cho caâu leänh naøy ?
o3 = 100 + o1;
// int + ob
•
Coù theå duøng tham soá qui chieáu trong moät haøm toaùn töû
Ví duï 2.4
// Overload + relative to coord class using references.
coord coord::operator+(coord &ob2)
{
coord temp;
temp.x = x + ob2.x;
temp.y = y + ob2.y;
return temp;
}
@ Caùc lyù do phaûi duøng tham soá qui chieáu trong haøm toaùn töû :
+ Söï hieäu quaû. Do vieäc truyeàn ñiaï chæ cuûa moät ñoái töôïng thöôøng nhanh hôn vaø
caûi thieän naêng xuaát so vôùi truyeàn caùc ñoái töôïng nhö caùc tham soá cho haøm.
+ Traùnh nhöõng raéc roái gaây ra khi baûn sao moät toaùn haïng bò huûy. Tuy nhieân, coù theå
ñònh nghiaõ moät haøm huûy baûn sao ñeå ngaên ngöøa vaán ñeà naøy trong tröôøng hôïp toång
quaùt.
Baøi taäp II
1. Haõy taïo quaù taûi toaùn töû "*" vaø "/" ñoái vôùi lôùp coord. Vieát chöông trình.
Chöông 5 Quaù taûi toaùn töû
144
144
2. Taïi sao phaàn döôùi ñaây laø caùch söû duïng khoâng thích hôïp cuûa moät toaùn töû ñöôïc quaù
taûi.
coord coord::operator%(coord ob)
{
double i;
cout << "Enter a number: ";
cin >> i;
cout << "root of " << i << " is ";
cout << sqr(i);
}
3. Haõy thöû thay ñoåi caùc kieåu traû veà cuûa caùc haøm toaùn töû ñoái vôùi lôùp khaùc lôùp coord.
Xem kieåu gì coù keát quûa sai ?
III/ Quaù taûi caùc toaùn töû quan heä vaø luaän lyù
Khi quaù taûi caùc toaùn töû quan heä vaø luaän lyù ñeå chuùng hoaït ñoäng theo caùch truyeàn
thoáng, seõ khoâng caàn caùc haøm toaùn töû traû veà moät ñoái töôïng cuûa lôùp, thay vaøo ñoù caùc
haøm toaùn töû traû veà moät soá nguyeân ñeå chæ ñuùng hay sai.
•
Quaù taûi caùc toaùn töû "==" vaø "&&"
Ví duï 3.1
// Overload the == and && relative to coord class.
#include <iostream.h>
class coord {
int x, y;
// coordinate values
public:
coord() { x=0; y=0; }
coord(int i, int j) { x=i; y=j; }
void get_xy(int &i, int &j) { i=x; j=y; }
int operator==(coord ob2)
;
Chöông 5 Quaù taûi toaùn töû
145
145
int operator&&(coord ob2);
};
// Overload the == operator for coord.
int coord::operator==(coord ob2)
{
return x==ob2.x && y==ob2.y;
}
// Overload the && operator for coord.
int coord::operator&&(coord ob2)
{
return (x && ob2.x) && (y && ob2.y);
}
int main()
{
coord o1(10, 10), o2(5, 3), o3(10, 10), o4(0, 0);
if(o1==o2) cout << "o1 same as o2\n";
else cout << "o1 and o2 differ\n";
if(o1==o3) cout << "o1 same as o3\n";
else cout << "o1 and o3 differ\n";
if(o1&&o2)
cout << "o1 && o2 is true\n";
else cout << "o1 && o2 is false\n";
if(o1&&o4)
cout << "o1 && o4 is true\n";
else cout << "o1 && o4 is false\n";
return 0;
}
Baøi taäp III
1. Haõy taïo quaù taûi toaùn töû "<" vaø ">" ñoái vôùi lôùp coord. Vieát chöông trình.
Chöông 5 Quaù taûi toaùn töû
146
146
IV/ Quaù taûi toaùn töû ñôn nguyeân
Quaù taûi toaùn töû ñôn nguyeân töông töï nhö toaùn töû nhò nguyeân ngoaïi tröø chæ coù moät
toaùn haïng
.
Khi quaù taûi toaùn töû ñôn nguyeân baèng caùch duøng haøm thaønh vieân, thì haøm khoâng coù
tham soá
. Do chæ coù moät toaùn haïng, neân chính toaùn haïng naøy taïo ra lôøi goïi cho haøm
toaùn töû.
•
Quaù taûi toaùn töû taêng "++" ñoái vôùi lôùp
Ví duï 4.1
// Overload ++ relative to coord class.
#include <iostream.h>
class coord {
int x, y; // coordinate values
public:
coord() { x=0; y=0; }
coord(int i, int j) { x=i; y=j; }
void get_xy(int &i, int &j) { i=x; j=y; }
coord operator++() ;
};
// Overload ++ for coord class.
coord coord::operator++()
{
x++;
y++;
return *this;
}
Chöông 5 Quaù taûi toaùn töû
147
147
int main()
{
coord o1(10, 10);
int x, y;
++o1
;
// increment an object
o1.get_xy(x, y);
cout << "(++o1) X: " << x << ", Y: " << y << "\n";
return 0;
}
•
Vôùi ñaëc taû môùi cuûa C++ (chuaån ANSI C++), trình bieân dòch coù theå phaân bieät hai
caâu leänh naøy laø khaùc nhau
++o ;
// prefix - töông öùng vôùi caùch khai baùo ôû ví duï 4.1
o++
;
//
posfix
Daïng thöù hai ñöôïc khai baùo nhö sau
coord coord::operator++(int notused) ;
vôùi notused luoân luoân ñöôïc truyeàn giaù trò 0.
•
Vôùi daáu tröø "-", vöøa laø toaùn töû nhò nguyeân laãn ñôn nguyeân trong C++. Laøm caùch
naøo coù theå quaù taûi noù sao cho vaãn giöõ ñöôïc caû hai tính chaát naøy ñoái vôùi lôùp do
laäp trình vieân taïo ra ?
Giaûi phaùp : chæ caàn quaù taûi noù hai laàn, moät laàn nhö toaùn töû nhò nguyeân vaø moät laàn
nhö toaùn töû ñôn nguyeân.
Ví duï 4.2
// Overload the - relative to coord class.
#include <iostream.h>
class coord {
int x, y; // coordinate values
public:
coord() { x=0; y=0; }
Chöông 5 Quaù taûi toaùn töû
148
148
coord(int i, int j) { x=i; y=j; }
void get_xy(int &i, int &j) { i=x; j=y; }
coord operator-(coord ob2); // binary minus
coord operator-();
// unary minus
};
// Overload - relative to coord class.
coord coord::operator-(coord ob2)
{
coord temp;
temp.x = x - ob2.x;
temp.y = y - ob2.y;
return temp;
}
// Overload unary - for coord class.
coord coord::operator-()
{
x = -x;
y = -y;
return *this;
}
int main()
{
coord o1(10, 10), o2(5, 7);
int x, y;
o1 = o1 - o2;
// subtraction
o1.get_xy(x, y);
cout << "(o1-o2) X: " << x << ", Y: " << y << "\n";
Chöông 5 Quaù taûi toaùn töû
149
149
o1 = - o1;
// negation
o1.get_xy(x, y);
cout << "(-o1) X: " << x << ", Y: " << y << "\n";
return 0;
}
Baøi taäp IV
1. Haõy quaù taûi toaùn töû "--" ñoái vôùi lôùp coord. Vieát chöông trình cho caû hai daïng ñöùng
tröôùc vaø ñöùng sau.
2. Haõy quaù taûi toaùn töû "+" ñoái vôùi lôùp coord ñeå cho noù laø toaùn töû nhò nguyeân laãn toaùn
töû ñôn nguyeân. Vieát chöông trình cho caû hai daïng, khi ñöôïc duøng nhö toaùn töû ñôn
nguyeân haõy thöïc hieän moät giaù trò toaï ñoä aâm baát kyø thaønh döông.
V/ Haøm toaùn töû friend
Coù theå quaù taûi moät toaùn töû ñoái vôùi lôùp baèng caùch duøng haøm friend, neân nhôù haøm
friend khoâng coù con troû this.
Vôùi caùc toaùn töû nhò nguyeân, haøm toaùn töû friend ñöôïc truyeàn caû hai toaùn haïng.
Vôùi caùc toaùn töû ñôn nguyeân, haøm toaùn töû friend ñöôïc truyeàn moät toaùn haïng.
Khoâng theå duøng haøm friend ñeå quaù taûi toaùn töû gaùn.
•
Quaù taûi toaùn töû "+" baèng caùch duøng haøm friend
Chöông 5 Quaù taûi toaùn töû
150
150
Ví duï 5.1
// Overload the + relative to coord class using a friend.
#include <iostream.h>
class coord {
int x, y; // coordinate values
public:
coord() { x=0; y=0; }
coord(int i, int j) { x=i; y=j; }
void get_xy(int &i, int &j) { i=x; j=y; }
friend coord operator+(coord ob1, coord ob2)
;
};
// Overload + using a friend.
coord operator+(coord ob1, coord ob2)
{
coord temp;
temp.x = ob1.x + ob2.x;
temp.y = ob1.y + ob2.y;
return temp;
}
int main()
{
coord o1(10, 10), o2(5, 3), o3;
int x, y;
o3 = o1 + o2;
// add two objects - this calls operator+()
o3.get_xy(x, y);
cout << "(o1+o2) X: " << x << ", Y: " << y << "\n";
return 0;
}
Chöông 5 Quaù taûi toaùn töû
151
151
@ Toaùn haïng beân traùi ñöôïc truyeàn cho tham soá thöù nhaát, toaùn haïng beân phaûi ñöôïc
truyeàn cho tham soá thöù hai.
•
Quaù taûi moät toaùn töû baèng caùch duøng moät friend cung caáp ñaëc ñieåm quan troïng
maø moät haøm thaønh vieân khoâng theå coù ñöôïc. Vôùi haøm toaùn töû friend, coù theå ñeå
cho nhöõng ñoái töôïng ñöôïc söû duïng trong caùc pheùp toaùn coù caùc kieåu ñònh saün, ôû
ñoù kieåu ñònh saün naèm ôû beân traùi toaùn töû.
Trong ví duï 2.3, chöông 5, haøm toaùn töû thaønh vieân ñöôïc quaù taûi
coord coord::operator+(int i)
caâu leänh
ob1 = ob2 + 100; laø ñuùng
coøn caâu leänh
ob1 = 100 + ob2; laø sai
Vôùi haøm toaùn töû friend, coù theå ñònh nghiaõ haøm quaù taûi sao cho toaùn haïng beân
traùi laø moät ñoái töôïng vaø toaùn haïng beân phaûi laø kieåu ñònh saün. Sau ñoù, quaù taûi
toaùn töû naøy laàn nöõa vôùi toaùn haïng beân traùi laø kieåu ñònh saün vaø toaùn haïng beân
phaûi laø moät ñoái töôïng.
Ví duï 5.2
// Use friend operator functions to add flexibility.
#include <iostream.h>
class coord {
int x, y; // coordinate values
public:
coord() { x=0; y=0; }
coord(int i, int j) { x=i; y=j; }
void get_xy(int &i, int &j) { i=x; j=y; }
friend coord operator+(coord ob1, int i);
friend coord operator+(int i, coord ob1);
};
Chöông 5 Quaù taûi toaùn töû
152
152
// Overload for ob + int.
coord operator+(coord ob1, int i)
{
coord temp;
temp.x = ob1.x + i;
temp.y = ob1.y + i;
return temp;
}
// Overload for int + ob.
coord operator+(int i, coord ob1)
{
coord temp;
temp.x = ob1.x + i;
temp.y = ob1.y + i;
return temp;
}
int main()
{
coord o1(10, 10);
int x, y;
o1 = o1 + 10; // object + integer
o1.get_xy(x, y);
cout << "(o1+10) X: " << x << ", Y: " << y << "\n";
o1 = 99 + o1; // integer + object
o1.get_xy(x, y);
cout << "(99+o1) X: " << x << ", Y: " << y << "\n";
return 0;
}
Chöông 5 Quaù taûi toaùn töû
153
153
@ Do ñoù hai caâu leänh naøy luùc naøy hoaøn toaøn ñuùng
ob1 = ob2 + 100;
ob1 = 100 + ob2;
•
Baèng caùch truyeàn toaùn haïng cho friend nhö moät tham soá tham chieáu, nhöõng
thay ñoåi xaûy ra beân trong haøm friend coù aûnh höôûng ñeán ñoái töôïng taïo ra lôøi goïi.
Quaù taûi toaùn töû "++" baèng caùch duøng haøm friend.
Ví duï 5.3
// Overload the ++ using a friend.
#include <iostream.h>
class coord {
int x, y; // coordinate values
public:
coord() { x=0; y=0; }
coord(int i, int j) { x=i; y=j; }
void get_xy(int &i, int &j) { i=x; j=y; }
friend coord operator++(coord &ob);
};
// Overload ++ using a friend.
coord operator++(coord &ob) // use reference parameter
{
ob.x++;
ob.y++;
return ob; // return object generating the call
}
int main()
{
coord o1(10, 10);
int x, y;
++o1 ;
// o1 is passed by reference
Chöông 5 Quaù taûi toaùn töû
154
154
o1.get_xy(x, y);
cout << "(++o1) X: " << x << ", Y: " << y << "\n";
return 0;
}
@ Neáu duøng trình bieân dòch môùi (theo chuaån ANSI C++), coù theå phaân bieät giöõa caùc
daïng ñöùng tröôùc vaø ñöùng sau cuûa caùc toaùn töû taêng hay giaûm khi duøng haøm toaùn töû
friend. Chæ caàn boå sung tham soá nguyeân notused khi ñònh nghiaõ daïng ñöùng sau
(nghiaõ laø toaùn töû "++" ñöùng sau toaùn haïng) .
coord operator++(coord &ob);
// prefix
++O
coord operator++(coord &ob, int notused); // postfix
O++
Baøi taäp V
1. Haõy quaù taûi toaùn töû "-" vaø "/" ñoái vôùi lôùp coord duøng haøm friend. Vieát chöông
trình.
2. Quaù taûi lôùp coord ñeå söû duïng caùc ñoái töôïng coord trong caùc pheùp toaùn maø moät giaù
trò nguyeân ñöôïc nhaân vôùi moãi toaï ñoä, cho pheùp caùc pheùp toaùn duøng thöù töï cuûa noù :
ob * int
hoaëc int * ob
3. Söû duïng friend, haõy quaù taûi toaùn töû "--" ñoái vôùi lôùp coord. Vieát chöông trình cho caû
hai daïng ñöùng tröôùc vaø sau.
Chöông 5 Quaù taûi toaùn töû
155
155
VI/ Toaùn töû gaùn
Theo maëc ñònh, khi moät toaùn töû gaùn ñöôïc aùp duïng cho moät ñoái töôïng thì moät baûn sao
töøng bit ñöôïc ñaët vaøo trong ñoái töôïng beân traùi.
Tuy nhieân, coù nhöõng tröôøng hôïp maø baûn sao töøng bit chính xaùc laø khoâng caàn. Xem
moät soá ví duï trong chöông 2, nhöõng tröôøng hôïp khi moät ñoái töôïng söû duïng boä nhôù.
Trong nhöõng tröôøng hôïp naøy, caàn phaûi coù moät pheùp gaùn ñaëc bieät.
•
Quaù taûi toaùn töû "=" trong lôùp strtype
Ví duï 6.1
#include <iostream.h>
#include <string.h>
#include <stdlib.h>
class strtype {
char *p;
int len;
public:
strtype(char *s);
~strtype() {
cout << "Freeing " << (unsigned) p << '\n';
delete [] p;
}
char *get() { return p; }
strtype &operator=(strtype &ob);
};
strtype::strtype(char *s)
{
int l;
l = strlen(s)+1;
p = new char [l];
if(!p) {
cout << "Allocation error\n";
exit(1);
Chöông 5 Quaù taûi toaùn töû
156
156
}
len = l;
strcpy(p, s);
}
// Assign an object.
strtype &strtype::operator=(strtype &ob)
{
// see if more memory is needed
if(len < ob.len) {
// need to allocate more memory
delete [] p;
p = new char [ob.len];
if(!p) {
cout << "Allocation error\n";
exit(1);
}
}
len = ob.len;
strcpy(p, ob.p);
return *this;
}
int main()
{
strtype a("Hello"), b("There");
cout << a.get() << '\n';
cout << b.get() << '\n';
a = b;
// now p is not overwritten
cout << a.get() << '\n';
cout << b.get() << '\n';
return 0;
}
Chöông 5 Quaù taûi toaùn töû
157
157
@ Coù hai ñaëc ñieåm vôùi haøm operator=() trong ví duï naøy
+ noù coù moät tham soá tham chieáu
+ noù traû veà tham chieáu chöù khoâng phaûi moät ñoái töôïng
Baøi taäp VI
1. Cho khai baùo lôùp döôùi ñaây, haõy theâm vaøo caùc chi tieát ñeå taïo neân moät kieåu maûng
"an toaøn". Sau ñoù, haõy quaù taûi toaùn töû gaùn ñeå cho boä nhôù ñöôïc caáp phaùt cuûa maûng
khoâng bò huûy tình côø.
class dynarray {
int *p;
int size;
public:
dynarray(int s); // pass size of array in s
int &put(int i);
// return reference to element i
int get(int i);
// return value of element i
// create operator=() function
...
};
Chöông 5 Quaù taûi toaùn töû
158
158
Baøi taäp chöông 5
1. Quaù taûi caùc toaùn töû >> vaø << ñoái vôùi lôùp coord ñeå cho coù caùc kieåu pheùp toaùn sau
ñaây :
ob << integer ;
ob >> integer ;
Vieát chöông trình laøm cho caùc toaùn töû treân naâng caùc giaù trò x vaø y leân moät ñaïi löôïng
ñöôïc chiû roõ.
2. Cho lôùp
class three_d {
int x, y, z;
public:
three_d(int i, int j, int k)
{
x = i; y = j; z = k;
}
three_d() { x=0; y=0; z=0; }
void get(int &i, int &j, int &k)
{
i = x; j = y; k = z;
}
};
Haõy quaù taûi caùc toaùn töû +, -, ++ vaø -- ñoái vôùi lôùp naøy. Ñoái vôùi caùc toaùn töû taêng vaø
giaûm chiû quaù taûi theo daïng ñöùng tröôùc. Vieát chöông trình thöïc hieän caùc yeâu caàu sau :
- khai baùo caùc ñoái töôïng : three_d o1(6,8,10), o2(3,4,5), o3;
- thöïc hieän caùc pheùp toaùn :
o3 = o1 + o2;
o3
=
o1
-
o2;
++o1 ;
--o1;
- xuaát noäi dung x, y, z cuûa caùc ñoái töôïng treân.
3. Thöïc hieän laïi baøi taäp 2 döôùi daïng tham soá tham chieáu ñoái vôùi caùc haøm toaùn töû.
Duøng haøm friend ñoái vôùi caùc toaùn töû taêng vaø giaûm.
Chöông 5 Quaù taûi toaùn töû
159
159
4. Vieát chöông trình thöïc hieän quaù taûi toaùn töû + ñoái vôùi lôùp three_d ñeå cho noù nhaän
caùc kieåu pheùp toaùn sau : ob + double;
double + ob;
5. Vieát chöông trình thöïc hieän quaù taûi caùc toaùn töû ==, !=, vaø // ñoái vôùi lôùp three_d.
6. Vieát chöông trình taïo lôùp strtype ñeå cho pheùp caùc kieåu toaùn töû sau :
* gheùp chuoåi baèng caùch duøng toaùn töû +
* gaùn chuoåi baèng caùch duøng toaùn töû =
* so saùnh chuoåi baèng caùch duøng caùc toaùn töû > , < vaø ==
coù theå duøng chuoåi coù ñoä daøi coá ñònh. Trong ñoù :
- moät bieán chuoåi s[80] coù daïng private
- haøm taïo khoâng ñoái soá, thöïc hieän vieäc khôûi taïo chuoåi s laø NULL
- haøm taïo coù moät ñoái soá *p, thöïc hieän vieäc cheùp noäi dung chuoåi p cho s
- haøm char *get() traû veà giaù trò cuûa chuoåi s
7. Haõy boå sung caùc haøm toaùn töû caàn thieát vaøo chöông trình sau.
* Toaùn töû quaù taûi + coäng moãi phaàn töû cuûa toaùn haïng.
* Toaùn töû quaù taûi - tröø phaàn töû toaùn haïng beân traùi vôùi moãi phaàn töû cuûa toaùn haïng beân
phaûi.
* Toaùn töû quaù taûi == traû veà giaù trò ñuùng neáu moãi phaàn töû cuûa moãi toaùn haïng laø gioáng
nhau vaø traû veà giaù trò sai neáu ngöôïc laïi.
#include <iostream>
class array {
int nums[10];
public:
array();
void set(int n[10]);
void show();
array operator+(array ob2);
array operator-(array ob2);
int operator==(array ob2);
};
Chöông 5 Quaù taûi toaùn töû
160
160
array::array()
{
int i;
for(i=0; i<10; i++) nums[i] = 0;
}
void array::set(int *n)
{
int i;
for(i=0; i<10; i++) nums[i] = n[i];
}
void array::show()
{
int i;
for(i=0; i<10; i++)
cout << nums[i] << ' ';
cout << "\n";
}
// Fill in operator functions.
// ...
int main()
{
array o1, o2, o3;
int i[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
o1.set(i);
o2.set(i);
Chöông 5 Quaù taûi toaùn töû
161
161
o3 = o1 + o2;
o3.show();
o3 = o1 - o3;
o3.show();
if(o1==o2) cout << "o1 equals o2\n";
else cout << "o1 does not equal o2\n";
if(o1==o3) cout << "o1 equals o3\n";
else cout << "o1 does not equal o3\n";
return 0;
}
8. Thöïc hieän laïi baøi taäp 7 vôùi quaù taûi caùc toaùn töû baèng caùch duøng haøm friend.
Chöông 5 Quaù taûi toaùn töû
162
162
Chöông 6
Tính keá thöøa
•
Giôùi thieäu tính keá thöøa
•
Ñieàu khieån truy caäp lôùp cô sôû
•
Söû duïng caùc thaønh vieân ñöôïc baûo veä
•
Haøm taïo, haøm huûy vaø tính keá thöøa
•
Tính ña keá thöøa
•
Lôùp cô sôû aûo
Chöông 6 Tính keá thöøa
164
Chöông 6 Tính keá thöøa
165
I/ Giôùi thieäu tính keá thöøa (inheritance)
Tính keá thöøa
laø cô cheá nhôø ñoù moät lôùp coù theå keá thöøa caùc ñaëc ñieåm cuûa moät lôùp khaùc.
Tính keá thöøa hoå trôï khaùi nieäm phaân loaïi theo thöù baäc (hierachical classification) cuûa
lôùp, ngoaøi ra coøn hoå trôï tính ña hình (polymorphism).
•
Lôùp cô sôû
(base class) laø lôùp ñöôïc keá thöøa bôûi moät lôùp khaùc.
Lôùp daãn xuaát
(derive class) laø lôùp keá thöøa töø moät lôùp cô sôû.
Lôùp cô sôû
xaùc ñònh caùc tính chaát maø seõ trôû neân thoâng duïng cho caùc lôùp daãn xuaát.
Nghiaõ laø lôùp cô sôû hieån thò moâ taû toång quaùt nhaát moät taäp hôïp caùc ñaëc ñieåm.
Moät lôùp daãn xuaát keá thöøa caùc ñaëc ñieåm toång quaùt naøy vaø boå sung theâm caùc tính chaát
rieâng cuûa lôùp daãn xuaát.
Cuù phaùp khai baùo cho lôùp daãn xuaát
class
derived_class_name : access_specifier base_class_name {
// body of class
} ;
base_class_name
Teân lôùp cô sôû
derived_class_name
Teân lôùp daãn xuaát
access_specifier
chæ ñònh truy caäp bao goàm : public, private vaø protected
•
Töø khoaù public baùo cho trình bieân dòch bieát raèng lôùp cô sôû seõ ñöôïc keá thöøa sao
cho moïi thaønh vieân chung cuûa lôùp cô sôû cuõng seõ laø caùc thaønh vieân chung cuûa lôùp
daãn xuaát
. Tuy nhieân, moïi thaønh vieân rieâng cuûa lôùp cô sôû vaãn coøn rieâng ñoái vôùi noù
vaø khoâng ñöôïc truy caäp tröïc tieáp bôûi lôùp daãn xuaát.
Ví duï 1.1
// A simple example of inheritance.
#include <iostream.h.h>
B
D
Hình 6.1 Söï keá thöøa ñôn
Chöông 6 Tính keá thöøa
166
// Define base class.
class base {
int i;
public:
void set_i(int n);
int get_i();
};
// Define derived class.
class derived : public base {
int j;
public:
void set_j(int n);
int mul();
};
// Set value i in base.
void base::set_i(int n)
{
i = n;
}
// Return value of i in base.
int base::get_i() { return i; }
// Set value of j in derived.
void derived::set_j(int n)
{
j = n;
}
// Return value of base's i times derived's j.
int derived::mul()
{
// derived class can call base class public member functions
return j * get_i();
}
Chöông 6 Tính keá thöøa
167
int main()
{
derived ob;
ob.set_i(10); // load i in base
ob.set_j(4); // load j in derived
cout << ob.mul(); // displays 40
return 0;
}
•
Moät lôùp cô sôû laø khoâng thuoäc rieâng veà moät lôùp daãn xuaát. Lôùp cô sôû coù theå ñöôïc keá
thöøa bôûi nhieàu lôùp khaùc
.
Ví duï 1.2
Lôùp cô sôû chung Fruit coù 2 lôùp daãn xuaát Apple vaø Orange
// An example of class inheritance.
#include <iostream.h.h>
#include <string.h>
enum yn {no, yes};
enum color {red, yellow, green, orange};
void out(enum yn x);
char *c[] = {"red", "yellow", "green", "orange"};
// Generic fruit class.
class fruit {
// in this base, all elements are public
public:
enum yn annual;
enum yn perennial;
enum yn tree;
enum yn tropical;
enum color clr;
char name[40];
};
Chöông 6 Tính keá thöøa
168
// Derive Apple class.
class Apple : public fruit {
enum yn cooking;
enum yn crunchy;
enum yn eating;
public:
void seta(char *n, enum color c, enum yn ck, enum yn crchy, enum yn e);
void show();
};
// Derive orange class.
class Orange : public fruit {
enum yn juice;
enum yn sour;
enum yn eating;
public:
void seto(char *n, enum color c, enum yn j, enum yn sr, enum yn e);
void show();
};
void Apple::seta(char *n, enum color c, enum yn ck, enum yn crchy,
enum yn e)
{
strcpy(name, n);
annual = no;
perennial = yes;
tree = yes;
tropical = no;
clr = c;
cooking = ck;
crunchy = crchy;
eating = e;
}
void Orange::seto(char *n, enum color c, enum yn j, enum yn sr, enum yn e)
{
strcpy(name, n);
Chöông 6 Tính keá thöøa
169
annual = no;
perennial = yes;
tree = yes;
tropical = yes;
clr = c;
juice = j;
sour = sr;
eating = e;
}
void Apple::show()
{
cout << name << " apple is: " << "\n";
cout << "Annual: ";
out(annual);
cout << "Perennial: ";
out(perennial);
cout << "Tree: ";
out(tree);
cout << "Tropical: ";
out(tropical);
cout << "Color: " << c[clr] << "\n";
cout << "Good for cooking: "; out(cooking);
cout << "Crunchy: ";
out(crunchy);
cout << "Good for eating: "; out(eating);
cout << "\n";
}
void Orange::show()
{
cout << name << " orange is: " << "\n";
cout << "Annual: ";
out(annual);
cout << "Perennial: ";
out(perennial);
cout << "Tree: ";
out(tree);
cout << "Tropical: ";
out(tropical);
cout << "Color: " << c[clr] << "\n";
cout << "Good for juice: ";
out(juice);
cout << "Sour: ";
out(sour);
cout << "Good for eating: "; out(eating); cout << "\n";
}
Chöông 6 Tính keá thöøa
170
void out(enum yn x)
{
if(x==no) cout << "no\n";
else cout << "yes\n";
}
int main()
{
Apple a1, a2;
Orange o1, o2;
a1.seta("Red Delicious", red, no, yes, yes);
a2.seta("Jonathan", red, yes, no, yes);
o1.seto("Navel", orange, no, no, yes);
o2.seto("Valencia", orange, yes, yes, no);
a1.show();
a2.show();
o1.show();
o2.show();
return 0;
}
Baøi taäp I
1. Cho lôùp cô sôû sau
class area_cl {
public:
double height;
double width;
};
haõy taïo 2 lôùp daãn xuaát box vaø isosceles keá thöøa lôùp area_cl. Vôùi moãi lôùp haõy taïo
haøm area() laàn löôït traû veà dieän tích cuûa moät hoäp hay moät tam giaùc caân. Duøng caùc
haøm taïo ñöôïc tham soá hoaù ñeå khôûi ñaàu height vaø width.
Chöông 6 Tính keá thöøa
171
II/ Ñieàu khieån truy caäp lôùp cô sôû
Chæ ñònh truy caäp (access_specifier) xaùc ñònh caùch maø caùc phaàn töû cuûa lôùp cô sôû
ñöôïc keá thöøa bôûi lôùp daãn xuaát.
•
Töø khoaù private chæ ñònh caùc thaønh vieân chung lôùp cô sôû trôû thaønh caùc thaønh
vieân rieâng cuûa lôùp daãn xuaát,
nhöng nhöõng thaønh vieân naøy vaãn coøn ñöôïc truy caäp
bôûi caùc haøm thaønh vieân cuûa lôùp daãn xuaát.
Ví duï 2.1
#include <iostream.h>
class base {
int x;
public:
void setx(int n) { x = n; }
void showx() { cout << x << '\n'; }
};
// Inherit as public.
class derived : public base {
int y;
public:
void sety(int n) { y = n; }
void showy() { cout << y << '\n'; }
};
int main()
{
derived ob;
ob.setx(10);
// access member of base class
ob.sety(20);
// access member of derived class
ob.showx();
// access member of base class
ob.showy();
// access member of derived class
Chöông 6 Tính keá thöøa
172
return 0;
}
Ví duï 2.2
Lôùp daãn xuaát khoâng theå truy caäp ñeán caùc thaønh vieân rieâng cuûa lôùp cô
sôû
class base {
int x;
public:
void setx(int n) { x = n; }
void showx() { cout << x << '\n'; }
};
// Inherit as public - this has an error!
class derived : public base {
int y;
public:
void sety(int n) { y = n; }
/* Cannot access private member of base class.
x is a private member of base and not available within derived. */
void show_sum() { cout << x + y << '\n'; } // Error!
void showy() { cout << y << '\n'; }
};
Ví duï 2.3
Lôùp daãn xuaát keá thöøa lôùp cô sôû vôùi chæ ñònh private
// This program contains an error.
#include <iostream.h>
class base {
int x;
public:
void setx(int n) { x = n; }
void showx() { cout << x << '\n'; }
};
Chöông 6 Tính keá thöøa
173
// Inherit base as private.
class derived : private base {
int y;
public:
void sety(int n) { y = n; }
void showy() { cout << y << '\n'; }
};
int main()
{
derived ob;
ob.setx(10);
// ERROR - now private to derived class
ob.sety(20);
// access member of derived class - OK
ob.showx();
// ERROR - now private to derived class
ob.showy();
// access member of derived class - OK
return 0;
}
@ Löu yù
Trong haøm main vaãn coù theå truy caäp caùc thaønh vieân chung cuaû lôùp cô
sôû
base base_ob;
base_ob.setx(1); // is legal because base_ob is of type base
Ví duï 2.4
Lôùp daãn xuaát keá thöøa lôùp cô sôû vôùi chæ ñònh private, caùc thaønh vieân vaãn
coøn ñöôïc truy caäp beân trong lôùp daãn xuaát.
// This program is fixed.
#include <iostream.h>
class base {
int x;
public:
void setx(int n) { x = n; }
void showx() { cout << x << '\n'; }
};
Chöông 6 Tính keá thöøa
174
// Inherit base as private.
class derived : private base {
int y;
public:
// setx is accessible from within derived
void setxy(int n, int m) { setx(n);
y = m; }
// showx is accessible from within derived
void showxy() { showx();
cout << y << '\n'; }
};
int main()
{
derived ob;
ob.setxy(10, 20);
ob.showxy();
return 0;
}
Chöông 6 Tính keá thöøa
175
Baøi taäp II
1. Xeùt ñoaïn chöông trình sau
#include <iostream.h>
class mybase {
int a, b;
public:
int c;
void setab(int i, int j) { a = i; b = j; }
void getab(int &i, int &j) { i = a; j = b; }
};
class derived1 : public mybase {
// ...
};
class derived2 : private mybase {
// ...
};
int main()
{
derived1 o1;
derived2 o2;
int i, j;
// ...
}
Trong haøm main() caâu leänh naøo sau ñaây laø hôïp leä :
A. o1.getab(i,j) ;
B. o2.getab(i,j) ;
C. o1.c = 10 ;
D. o2.c = 10 ;
2. Ñieàu gì xaûy ra khi moät thaønh vieân rieâng ñöôïc keá thöøa nhö moät thaønh vieân chung ?
Ñieàu gì xaûy ra khi noù ñöôïc keá thöøa nhö moät thaønh vieân rieâng ?
Chöông 6 Tính keá thöøa
176
III/ Söû duïng caùc thaønh vieân ñöôïc baûo veä (protected members)
Vôùi caùc chæ ñònh truy caäp public vaø private, moät lôùp daãn xuaát khoâng truy caäp ñöôïc
caùc thaønh vieân rieâng cuûa lôùp cô sôû. Tuy nhieân, seõ coù nhöõng luùc muoán moät thaønh vieân
cuûa lôùp cô sôû vaãn laø rieâng nhöng vaãn cho pheùp lôùp daãn xuaát truy caäp tôùi noù.
•
Chæ ñònh truy caäp protected, töông ñöông vôùi chæ ñònh private vôùi moät ngoaïi leä
duy nhaát laø caùc thaønh vieân ñöôïc baûo veä (protected members) cuûa lôùp cô sôû coù theå
ñöôïc truy caäp ñoái vôùi caùc thaønh vieân cuûa moät lôùp daãn xuaát töø lôùp cô sôû ñoù.
Beân ngoaøi lôùp cô sôû hoaëc lôùp daãn xuaát, caùc thaønh vieân ñöôïc baûo veä khoâng theå
ñöôïc truy caäp.
Daïng toång quaùt cuûa khai baùo lôùp :
class
class_name {
//
private
members
protected :
//
protected
members
public :
// public members
};
Khi moät thaønh vieân ñöôïc baûo veä cuûa moät lôùp cô sôû ñöôïc keá thöøa bôûi lôùp daãn xuaát vôùi
chæ ñònh public, noù trôû thaønh thaønh vieân ñöôïc baûo veä cuûa lôùp daãn xuaát.
Neáu lôùp daãn xuaát ñöôïc keá thöøa vôùi chæ ñònh private, thì moät thaønh vieân ñöôïc baûo veä
cuûa lôùp cô sôû trôû thaønh thaønh vieân rieâng cuûa lôùp daãn xuaát.
Lôùp cô sôû coù theå ñöôïc keá thöøa vôùi chæ ñònh protected bôûi lôùp daãn xuaát, khi ñoù caùc
thaønh vieân chung vaø ñöôïc baûo veä cuûa lôùp cô sôû trôû thaønh caùc thaønh vieân ñöôïc baûo veä
cuûa lôùp daãn xuaát.
Coøn caùc thaønh vieân rieâng cuûa lôùp cô sôû vaãn coøn rieâng ñoái vôùi lôùp cô sôû vaø khoâng
ñöôïc truy caäp bôûi lôùp daãn xuaát.
Chöông 6 Tính keá thöøa
177
Ví duï 3.1
Truy caäp caùc thaønh vieân chung, rieâng vaø ñöôïc baûo veä cuûa lôùp cô sôû
#include <iostream.h>
class samp {
// private by default
int a;
protected: // still private relative to samp
int b;
public:
int c;
samp(int n, int m) { a = n; b = m; }
int geta() { return a; }
int getb() { return b; }
};
int main()
{
samp ob(10, 20);
// ob.b = 99;
Error! b is protected and thus private
ob.c = 30;
// OK, c is public
cout << ob.geta() << ' ';
cout << ob.getb() << ' ' << ob.c << '\n';
return 0;
}
Ví duï 3.2
Caùc thaønh vieân ñöôïc baûo veä ñöôïc keá thöøa nhö thaønh vieân chung
#include <iostream.h>
class base {
protected :
// private to base
int a, b;
// but still accessible by derived
public:
Chöông 6 Tính keá thöøa
178
void setab(int n, int m) { a = n; b = m; }
};
class derived : public base {
int c;
public:
void setc(int n) { c = n; }
// this function has access to a and b from base
void showabc() {
cout << a << ' ' << b << ' ' << c << '\n';
}
};
int main()
{
derived ob;
// a and b are not accessible here because they are private to both base and
derived.
ob.setab(1, 2);
ob.setc(3);
ob.showabc();
return 0;
}
Ví duï 3.3
Caùc thaønh vieân ñöôïc baûo veä ñöôïc keá thöøa bôûi chæ ñònh protected
// This program will not compile.
#include <iostream.h>
class base {
protected :
// private to base
int a, b;
// but still accessible by derived
public:
Chöông 6 Tính keá thöøa
179
void setab(int n, int m)
{ a = n;
b = m;
}
};
class derived : protected base { // inherit as protected
int c;
public:
void setc(int n) { c = n; }
// this function has access to a and b from base
void showabc() {
cout << a << ' ' << b << ' ' << c << '\n';
}
};
int main()
{
derived ob;
// ERROR: setab() is now a protected member of base.
ob.setab(1, 2);
// setab() is not accessible here.
ob.setc(3);
ob.showabc();
return 0;
}
Chöông 6 Tính keá thöøa
180
Baøi taäp III
1. Laäp baûng toång keát veà quyeàn truy caäp cuûa lôùp daãn xuaát vôùi söï keá thöøa ñôn
Thuoäc tính thaønh vieân
trong lôùp cô sôû
Chæ ñònh truy caäp cuûa lôùp
daãn xuaát
Quyeàn truy caäp cuûa lôùp
daãn xuaát
Public Public
Private
Protected
?
?
?
Private Public
Private
Protected
?
?
?
Protected Public
Private
Protected
?
?
?
2. Trong baøi taäp II/ 1. chöông 6, neáu a vaø b beân trong lôùp mybase ñöôïc thöïc hieän trôû
thaønh nhöõng thaønh vieân ñöôïc baûo veä thay vì caùc thaønh vieân rieâng (theo maëc ñònh) thì
keát quaû theá naøo ? Taïi sao ?
Chöông 6 Tính keá thöøa
181
IV/ Haøm taïo, haøm huûy vaø tính keá thöøa
Lôùp cô sôû, lôùp daãn xuaát hoaëc caû hai coù theå coù caùc haøm taïo vaø/hoaëc haøm huûy.
•
Khi caû lôùp cô sôû laãn lôùp daãn xuaát coù caùc haøm taïo vaø haøm huûy, caùc haøm taïo ñöôïc
thi haønh theo thöù töï daãn xuaát. Caùùc haøm huûy ñöôïc thi haønh theo thöù töï ngöôïc laïi.
Cuù phaùp truyeàn ñoái soá töø lôùp daãn xuaát ñeán lôùp cô sôû
:
derived_constructor(arg_list) : base(arg_list) {
// body of derived class constructor
}
Ví duï 4.1
#include <iostream.h>
class base {
public:
base() { cout << "Constructing base class \n"; }
~base() { cout << "Destructing base class \n"; }
};
class derived : public base {
public:
derived() { cout << "Constructing derived class \n"; }
~derived() { cout << "Destructing derived class \n"; }
};
int main()
{
derived o;
return 0;
}
Giaûi thích keát quaû cuûa chöông trình ?
Chöông 6 Tính keá thöøa
182
Constructing base class
Constructing derived class
Destructing derived class
Destructing base class
Ví duï 4.2
Truyeàn moät ñoái soá cho haøm taïo cuûa lôùp daãn xuaát
#include <iostream.h>
class base {
public:
base() { cout << "Constructing base class\n"; }
~base() { cout << "Destructing base class\n"; }
};
class derived : public base {
int j;
public:
derived(int n) {
cout << "Constructing derived class\n";
j = n;
}
~derived() { cout << "Destructing derived class\n"; }
void showj() { cout << j << '\n'; }
};
int main()
{
derived o(10);
// truyeàn theo caùch thoâng thöôøng
o.showj();
return 0;
}
Keát quaû cuûa chöông trình ?
Ví duï 4.3
Haøm taïo cuûa lôùp daãn xuaát laãn cuûa lôùp cô sôû nhaän moät ñoái soá,
Chöông 6 Tính keá thöøa
183
caû hai söû duïng ñoái soá gioáng nhau
#include <iostream.h>
class base {
int i;
public:
base(int n) {
cout << "Constructing base class\n";
i = n;
}
~base() { cout << "Destructing base class\n"; }
void showi() { cout << i << '\n'; }
};
class derived : public base {
int j;
public:
derived(int n) : base(n) {
// pass arg to base class
cout << "Constructing derived class\n";
j = n;
}
~derived() { cout << "Destructing derived class\n"; }
void showj() { cout << j << '\n'; }
};
int main()
{
derived o(10);
o.showi();
o.showj();
return 0;
}
Keát quaû cuûa chöông trình ?
Chöông 6 Tính keá thöøa
184
•
Trong haàu heát caùc tröôønghôïp, caùc haøm taïo ñoái vôùi lôùp cô sôû vaø lôùp daãn xuaát seõ
khoâng duøng ñoái soá gioáng nhau
.
Neáu truyeàn moät hay nhieàu ñoái soá cho moãi lôùp, caàn phaûi truyeàn cho haøm taïo cuûa lôùp
daãn xuaát taát caû caùc ñoái soá maø caû hai lôùp daãn xuaát vaø lôùp cô sôû caàn ñeán. Sau ñoù lôùp
daãn xuaát chæ truyeàn cho lôùp cô sôû nhöõng ñoái soá naøo maø lôùp cô sôû caàn ñeán.
Ví duï 4.4
#include <iostream.h>
class base {
int i;
public:
base(int n) {
cout << "Constructing base class\n";
i = n;
}
~base() { cout << "Destructing base class\n"; }
void showi() { cout << i << '\n'; }
};
class derived : public base {
int j;
public:
derived(int n, int m) : base(m) {
// pass arg to base class
cout << "Constructing derived class\n";
j = n;
}
~derived() { cout << "Destructing derived class\n"; }
void showj() { cout << j << '\n'; }
};
int main()
{
derived o(10, 20);
Chöông 6 Tính keá thöøa
185
o.showi();
o.showj();
return 0;
}
Keát quaû cuûa chöông trình ?
•
Ñoái vôùi haøm taïo cuûa lôùp daãn xuaát khoâng caàn phaûi nhaän moät soá ñeå truyeàn cho
lôùp cô sôû. Neáu lôùp daãn xuaát khoâng caàn ñoái soá, noù boû qua ñoái soá vaø chæ truyeàn
cho lôùp cô sôû.
Ví duï 4.5
class base {
int i;
public:
base(int n) {
cout << "Constructing base class\n";
i = n;
}
~base() { cout << "Destructing base class\n"; }
void showi() { cout << i << '\n'; }
};
class derived : public base {
int j;
public:
derived(int n) : base(n) {
// pass arg to base class
cout << "Constructing derived class\n";
j = 0; // n not used here
}
~derived() { cout << "Destructing derived class\n"; }
void showj() { cout << j << '\n'; }
};
Baøi taäp IV
Chöông 6 Tính keá thöøa
186
1. Cho ñoaïn chöông trình sau, haõy boå sung haøm taïo cho lôùp myderived. Cho
myderived truyeàn cho lôùp mybase moät con troû veà moät chuoãi khôûi ñaàu. Haõy cho haøm
taïo myderived() khôûi ñaàu len vôùi ñoä daøi chuoåi.
#include <iostream.h>
#include <string.h>
class mybase {
char str[80];
public:
mybase(char *s) { strcpy(str, s); }
char *get() { return str; }
};
class myderived : public mybase {
int len;
public:
// add myderived() here
int getlen() { return len; }
void show() { cout << get() << '\n'; }
};
int main()
{
myderived ob("hello");
ob.show();
cout << ob.getlen() << '\n';
return 0;
}
2. Laäp caùc haøm taïo car() vaø truck() trong ñoaïn chöông trình sau. Moãi haøm truyeàn caùc
ñoái soá thích hôïp cho lôùp vehicle. Ngoaøi ra, cho car() khôûi ñaàu passengers vaø truck()
khôûi ñaàu loadlimit nhö ñöôïc chæ roõ khi ñoái töôïng ñöôïc taïo ra. Khai baùo caùc ñoái töôïng
:
Chöông 6 Tính keá thöøa
187
car ob(passengers, wheels, range) ;
truck ob(loadlimit, wheels, range) ;
#include <iostream.h>
// A base class for various types of vehicles.
class vehicle {
int num_wheels;
int range;
public:
vehicle(int w, int r)
{
num_wheels = w; range = r;
}
void showv()
{
cout << "Wheels: " << num_wheels << '\n';
cout << "Range: " << range << '\n';
}
};
class car : public vehicle {
int passengers;
public:
// insert car() constructor here
void show()
{
showv();
cout << "Passengers: " << passengers << '\n';
}
};
class truck : public vehicle {
int loadlimit;
public:
// insert truck() constructor here
void show()
{
Chöông 6 Tính keá thöøa
188
showv();
cout << "loadlimit " << loadlimit << '\n';
}
};
int main()
{
car c(5, 4, 500);
truck t(30000, 12, 1200);
cout << "Car: \n";
c.show();
cout << "\nTruck:\n";
t.show();
return 0;
}
V/ Tính ña keá thöøa
Chöông 6 Tính keá thöøa
189
1/ Khaùi nieäm
•
Coù hai caùch ñeå moät lôùp daãn xuaát keá thöøa hôn moät lôùp .
Thöù nhaát
, lôùp daãn xuaát ñöôïc duøng nhö moät lôùp cô sôû cho moät lôùp daãn xuaát khaùc,
taïo ra thöù baäc lôùp nhieàu caáp. Khi ñoù caáp cô sôû goác ñöôïc goïi laø lôùp cô sôû giaùng
tieáp
cuûa lôùp cô sôû thöù hai (Hình 6.2) .
Hình 6.2 Keá thöøa ña möùc
Hình 6.3 Keá thöøa phaân caáp
(Multi
level
Inheritance)
(Hierarchical
Inheritance)
Thöù hai
, lôùp daãn xuaát coù theå keá thöøa tröïc tieáp hôn moät lôùp cô sôû. Tröôøng hôïp naøy, hai
hay nhieàu lôùp cô sôû ñöôïc keát hôïp ñeå taïo ra lôùp daãn xuaát (Hình 6.4) .
Hình 6.4 Ña keá thöøa
Hình 6.5 Keá thöøa lai
(Multiple
Inheritance)
(Hybrid
Inheritance)
2/ Tính chaát
•
Khi moät lôùp cô sôû ñöôïc duøng ñeå daãn ra moät lôùp maø lôùp naøy laïi ñöôïc duøng laøm
lôùp cô sôû cho moät lôùp daãn xuaát khaùc, thì caùc haøm taïo cuûa caùc lôùp ñöôïc goïi theo
thöù töï daãn xuaát
. Cuõng vaäy, taát caû caùc haøm huûy ñöôïc goïi theo thöù töï ngöôïc laïi.
•
Khi moät lôùp daãn xuaát keá thöøa tröïc tieáp hôn moät lôùp cô sôû, noù duøng caùch khai
baùo môû roäng nhö sau :
class
derived_class_name : access base1 , access base2, ..., access baseN {
// body of class
B
↓
D1
↓
D2
B1
B2
D
B
D1
D2 D3
D4
B
D1
D2
D
Chöông 6 Tính keá thöøa
190
}
base1 , base2, ... , baseN
teân caùc lôùp cô sôû
access
chæ ñònh truy caäp, coù theå khaùc nhau ñoái vôùi moãi lôùp
Khi nhieàu lôùp cô sôû ñöôïc keá thöøa, caùc haøm taïo ñöôïc thi haønh theo thöù töï töø traùi
qua phaûi
maø caùc lôùp cô sôû ñaõ ñöôïc chæ ñònh roõ. Caùc haøm huûy ñöôïc thi haønh
theo thöù töï ngöôïc laïi
.
•
Khi moät lôùp keá thöøa nhieàu lôùp cô sôû coù caùc haøm taïo caàn nhieàu ñoái soá, lôùp daãn
xuaát seõ truyeàn caùc ñoái soá caàn thieát cho caùc haøm taïo naøy baèng caùch duøng daïng
môû roäng cuûa haøm taïo cuûa lôùp daãn xuaát nhö sau :
derived_constructor(arg_list) : base1(arg_list) , base2(arg_list), ..., baseN(arg_list) {
// body of class
}
Khi moät lôùp daãn xuaát keá thöøa moät heä thoáng thöù baäc caùc lôùp, moãi lôùp daãn xuaát trong
chuoãi caùc lôùp naøy phaûi truyeàn cho lôùp cô sôû ñöùng tröôùc caùc tham soá maø lôùp daãn xuaát
naøy caàn.
Ví duï 5.1
// Multiple Inheritance
#include <iostream.h>
class B1 {
int a;
public:
B1(int x) { a = x; }
int geta() { return a; }
};
// Inherit direct base class.
class D1 : public B1 {
Chöông 6 Tính keá thöøa
191
int b;
public:
D1(int x, int y) : B1(y) // pass y to B1
{
b = x; }
int getb() { return b; }
};
// Inherit a derived class and an indirect base.
class D2 : public D1 {
int c;
public:
D2(int x, int y, int z) : D1(y, z) // pass args to D1
{
c = x;
}
// Because bases inherited as public, D2 has access to public elements
// of both B1 and D1
void show() {
cout << geta() << ' ' << getb() << ' ';
cout << c << '\n';
}
};
int main()
{
D2 ob(1, 2, 3);
ob.show();
// geta() and getb() are still public here
cout << ob.geta() << ' ' << ob.getb() << '\n';
return 0;
}
Keát quaû cuûa chöông trình ?
Ví duï 5.2
Lôùp daãn xuaát keá thöøa tröïc tieáp hai lôùp cô sôû
#include <iostream.h>
Chöông 6 Tính keá thöøa
192
// Create first base class.
class B1 {
int a;
public:
B1(int x) { a = x; }
int geta() { return a; }
};
// Create second base class.
class B2 {
int b;
public:
B2(int x) { b = x; }
int getb() { return b; }
};
// Directly inherit two base classes.
class D : public B1, public B2 {
int c;
public:
// here, z and y are passed directly to B1 and B2
D(int x, int y, int z) : B1(z) , B2(y) { c = x; }
// Because bases inherited as public, D has access to public elements
// of both B1 and B2.
void show() {
cout << geta() << ' ' << getb() << ' ';
cout << c << '\n';
}
};
int main()
{
D ob(1, 2, 3);
ob.show();
return 0;
}
Chöông 6 Tính keá thöøa
193
Keát quaû cuûa chöông trình ?
Ví duï 5.3
Minh hoïa thöù töï goïi caùc haøm taïo vaø haøm huûy khi lôùp daãn xuaát
keá thöøa tröïc tieáp nhieàu lôùp cô sôû.
#include <iostream.h>
class B1 {
public:
B1() { cout << "Constructing B1\n"; }
~B1() { cout << "Destructing B1\n"; }
};
class B2 {
int b;
public:
B2() { cout << "Constructing B2\n"; }
~B2() { cout << "Destructing B2\n"; }
};
// Inherit two base classes.
class D : public B1 , public B2 {
public:
D() { cout << "Constructing D\n"; }
~D() { cout << "Destructing D\n"; }
};
int main()
{
D ob;
return 0;
}
Giaûi thích keát quaû cuûa chöông trình ?
Constructing B1
Chöông 6 Tính keá thöøa
194
Constructing B2
Constructing D
Destructing D
Destructing B2
Destructing B1
Baøi taäp V
1. Cho ñoaïn chöông trình sau, haõy khaûo saùt keát quaû cuûa chöông trình ?
#include <iostream.h>
class A {
public:
A() { cout << "Constructing A\n"; }
~A() { cout << "Destructing A\n"; }
};
class B {
public:
B() { cout << "Constructing B\n"; }
~B() { cout << "Destructing B\n"; }
};
class C : public A, public B {
public:
C() { cout << "Constructing C\n"; }
~C() { cout << "Destructing C\n"; }
};
int main()
{
C ob;
return 0;
}
Chöông 6 Tính keá thöøa
195
2. Söû duïng heä thoáng thöù baäc lôùp sau ñaây, haõy laäp haøm taïo cua lôùp C ñeå cho noù khôûi
ñaàu k vaø truyeàn caùc ñoái soá cho A() vaø B()
#include <iostream.h>
class A {
int i;
public:
A(int a) { i = a; }
};
class B {
int j;
public:
B(int a) { j = a; }
};
class C : public A, public B {
int k;
public:
// Create C() so that it initializes k and passes arguments to both A() and B()
...
};
VI/ Lôùp cô sôû aûo (virtual base class)
Chöông 6 Tính keá thöøa
196
Khi nhieàu lôùp cô sôû ñöôïc keá thöøa tröïc tieáp bôûi moät lôùp daãn xuaát, toàn taïi moät vaán ñeà :
xuaát hieän nhieàu baûn sao cuûa lôùp cô sôû cuøng hieän dieän trong ñoái töôïng daãn xuaát.
Chaúng haïn, xeùt heä thoáng thöù baäc lôùp sau
Bôøi vì coù hai baûn sao cuûa B trong D3, neân moät tham chieáu ñeán moät thaønh vieân cuûa B
seõ tham chieáu veà B ñöôïc keá thöøa giaùn tieáp thoâng qua D1 hay tham chieáu veà B ñöôïc
keá thöøa giaùn tieáp thoâng qua D2 ?
Ñeå giaûi quyeát tính khoâng roõ raøng naøy, C++ coù moät cô cheá maø nhôø ñoù chæ coù moät baûn
sao cuûa B ôû trong D3. Ñaëc ñieåm naøy ñöôïc goïi laø lôùp cô sôû aûo.
Coù theå ngaên chaën ñöôïc hai baûn sao cuûa lôùp cô sôû cuøng hieän dieän trong ñoái töôïng daãn
xuaát baèng caùch cho lôùp cô sôû ñoù ñöôïc keá thöøa nhö virtual bôûi baát kyø caùc lôùp daãn
xuaát naøo.
•
Töø khoaù virtual ñöùng tröôùc chæ ñònh truy caäp lôùp cô sôû khi noù ñöôïc keá thöøa bôûi
moät lôùp daãn xuaát.
Ví duï 6.1
// This program uses a virtual base class.
#include <iostream.h>
class base {
public:
int i;
};
// Inherit base as virtual.
B
B
D1 D2
D3
Chöông 6 Tính keá thöøa
197
class derived1 : virtual public base {
public:
int j;
};
// Inherit base as virtual, here too.
class derived2 : virtual public base {
public:
int k;
};
// Here, derived3 inherits both derived1 and derived2.
// However, only one copy of base is present.
class derived3 : public derived1, public derived2 {
public:
int product() { return i * j * k; }
};
int main()
{
derived3 ob;
ob.i = 10; // unambiguous because only one copy present
ob.j = 3;
ob.k = 5;
cout << "Product is " << ob.product() << '\n';
return 0;
}
@ Neáu derived1 vaø derived2 khoâng keá thöøa base nhö moät lôùp aûo thì caâu leänh
ob.i = 10;
seõ khoâng roõ raøng vaø seõ taïo ra loãi thôøi gian bieân dòch.
•
Khi moät lôùp cô sôû ñöôïc keá thöøa nhö moät lôùp aûo bôûi moät lôùp daãn xuaát thì lôùp cô
sôû ñoù vaãn coøn toàn taïi trong lôùp daãn xuaát
.
Chöông 6 Tính keá thöøa
198
Qua ví duï 6.1 ñoaïn chöông trình sau vaãn hoaøn toaøn ñuùng
derived1 ob;
ob.i = 100;
•
Söï khaùc bieät duy nhaát giöõa lôùp cô sôû thöôøng vôùi lôùp cô sôû aûo xaûy ra khi moät ñoái
töôïng keá thöøa lôùp cô sôû hôn moät laàn
. Neáu caùc lôùp cô sôû aûo ñöôïc söû duïng thì chæ
coù moät lôùp cô sôû hieän dieän trong ñoái töôïng. Ngöôïc laïi, nhieàu baûn sao seõ ñöôïc tìm
thaáy.
Baøi taäp VI
1. Trong ví duï 6.1, boû töø khoaù virtual vaø thöû bieân dòch chöông trình. Khaûo saùt loåi ?
2. Haõy söûa loãi ñoaïn chöông trình sau
// A variation on the vehicle hierarchy. But this program contains an error. Fix it.
//
Hint : try compiling it as is and observe the error messages.
#include <iostream.h>
// A base class for various types of vehicles.
class vehicle {
int num_wheels;
int range;
public:
vehicle(int w, int r)
{
num_wheels = w; range = r;
}
void showv()
{
cout << "Wheels: " << num_wheels << '\n';
cout << "Range: " << range << '\n';
}
Chöông 6 Tính keá thöøa
199
};
enum motor {gas, electric, diesel};
class motorized : public vehicle {
enum motor mtr;
public:
motorized(enum motor m, int w, int r) : vehicle(w, r) {
mtr = m;
}
void showm() {
cout << "Motor: ";
switch(mtr) {
case gas : cout << "Gas\n";
break;
case electric : cout << "Electric\n";
break;
case diesel : cout << "Diesel\n";
break;
}
}
};
class road_use : public vehicle {
int passengers;
public:
road_use(int p, int w, int r) : vehicle(w, r)
{
passengers = p;
}
void showr()
{
cout << "Passengers: " << passengers << '\n';
}
};
enum steering { power, rack_pinion, manual };
Chöông 6 Tính keá thöøa
200
class car : public motorized, public road_use {
enum steering strng;
public:
car(enum steering s, enum motor m, int w, int r, int p) :
road_use(p, w, r), motorized(m, w, r), vehicle(w, r) {
strng = s;
}
void show() {
showv(); showr();
showm();
cout << "Steering: ";
switch(strng) {
case power : cout << "Power\n";
break;
case rack_pinion : cout << "Rack and Pinion\n";
break;
case manual : cout << "Manual\n";
break;
}
}
};
int main()
{
car c(power, gas, 4, 500, 5);
c.show();
return 0;
}
Baøi taäp chöông 6
Chöông 6 Tính keá thöøa
201
1. Haõy taïo lôùp cô sôû chung building ñeå löu tröõ soá taàng nhaø maø moät toaø nhaø coù soá
phoøng vaø soá toång dieän tích döôùi daïng protected. Haõy taïo lôùp daãn xuaát house keá thöøa
building vaø löu tröõ soá phoøng nguõ vaø phoøng taém. Cuõng vaäy, taïo lôùp daãn xuaát office keá
thöøa public lôùp building vaø löu tröõ soá bình cöùu hoaû vaø soá maùy ñieän thoaïi. Caû hai lôùp
daãn xuaát ñeà coù haøm taïo vaø haøm show. Vieát chöông trình thöïc hieän yeâu caàu treân ?
2. Cho ñoaïn chöông trình sau, haõy boå sung caùc chi tieát theo chæ daãn trong caùc lôøi chuù
giaûi
#include <iostream.h>
class planet {
protected:
double distance; // miles from the sun
int revolve;
// in days
public:
planet(double d, int r) { distance = d; revolve = r; }
};
class earth : public planet {
double circumference; // circumference of orbit
public:
// Create earth(double d, int r). Have it pass the distance and days of revolution
back
// to planet. Have it compute the circumference of the orbit.
// (Hint : circumference = 2r*3.1416.)
// Create a function called show() that displays the information.
};
int main()
{
earth ob(93000000, 365);
ob.show();
return 0;
}
3. Cho ñoaïn chöông trình sau, haõy boå sung ñeå chöông trình chaïy toát
Chöông 6 Tính keá thöøa
202
// Overload the +, -, and = relative to coord class. Then, use coord as a base for
quad.
#include <iostream.h>
class coord {
public:
int x, y;
// coordinate values
coord() { x=0; y=0; }
coord(int i, int j) { x=i; y=j; }
void get_xy(int &i, int &j) { i=x; j=y; }
coord operator+(coord ob2);
coord operator-(coord ob2);
coord operator=(coord ob2);
};
// Overload + relative to coord class.
coord coord::operator+(coord ob2)
{
coord temp;
cout << "Using coord operator+()\n";
temp.x = x + ob2.x;
temp.y = y + ob2.y;
return temp;
}
// Overload - relative to coord class.
coord coord::operator-(coord ob2)
{
coord temp;
cout << "Using coord operator-()\n";
temp.x = x - ob2.x;
temp.y = y - ob2.y;
return temp;
Chöông 6 Tính keá thöøa
203
}
// Overload = relative to coord.
coord coord::operator=(coord ob2)
{
cout << "Using coord operator=()\n";
x = ob2.x;
y = ob2.y;
return *this;
// return the object that is assigned to
}
class quad : public coord {
int quadrant;
public:
quad() { x = 0; y = 0; quadrant = 0; }
quad(int x, int y) : coord(x, y) {
if(x>=0 && y>=0)
quadrant = 1;
else if(x<0 && y>=0) quadrant = 2;
else if(x<0 && y<0)
quadrant = 3;
else quadrant = 4;
}
void showq() {
cout << "Point in Quadrant: " << quadrant << '\n';
}
quad operator=(coord ob2);
};
quad quad::operator=(coord ob2)
{
cout << "Using quad operator=()\n";
x = ob2.x;
y = ob2.y;
Chöông 6 Tính keá thöøa
204
if(x>=0 && y>=0) quadrant = 1;
else if(x<0 && y>=0) quadrant = 2;
else if(x<0 && y<0) quadrant = 3;
else quadrant = 4;
return *this;
}
int main()
{
quad o1(10, 10), o2(15, 3), o3;
int x, y;
o3 = o1 + o2;
// add two objects - this calls operator+()
o3.get_xy(x, y);
o3.showq();
cout << "(o1+o2) X: " << x << ", Y: " << y << "\n";
o3 = o1 - o2;
// subtract two objects
o3.get_xy(x, y);
o3.showq();
cout << "(o1-o2) X: " << x << ", Y: " << y << "\n";
o3 = o1;
// assign an object
o3.get_xy(x, y);
o3.showq();
cout << "(o3=o1) X: " << x << ", Y: " << y << "\n";
return 0;
}
4. Haõy söûa ñoåi chöông trình treân sao cho noù söû duïng caùc haøm toaùn töû friend ?
5. Haõy taïo moät phaân caáp lôùp ñeå löu tröõ thoâng tin veà maùy bay. Haõy baét ñaàu baèng moät
lôùp cô sôû teân laø airship chöùa thoâng tin veà soá löôïng haønh khaùch toái ña vaø troïng löôïng
haøng hoaù toái ña (ñôn vò tính laø pound) maø maùy bay coù theå chôû ñöôïc.
Chöông 6 Tính keá thöøa
205
Taïo hai lôùp daãn xuaát airplane vaø balloons. Lôùp airplane löu kieåu cuûa ñoäng cô (goàm
ñoäng cô caùnh quaït vaø ñoäng cô phaûn löïc), taàm xa (ñôn vò tính laø mile). Lôùp balloon
löu thoâng tin veà loaïi nhieân lieäu söû duïng chi khí caàu (goàm hai loaïi laø hydrogen vaø
helium), ñoä cao toái ña (ñôn vò tính laø feed). Vieát chöông trình minh hoaï hoaït ñoäng
cuûa chuùng.
Chöông 7
Heä thoáng Nhaäp/Xuaát C++
•
Cô sôû Nhaäp/Xuaát C++
•
Nhaäp/Xuaát coù ñònh daïng
•
Söû duïng width(), precision() vaø fill()
•
Söû duïng boä thao taùc Nhaäp/Xuaát
•
Taïo boä cheøn
•
Taïo boä chieát
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
208
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
209
I/ Cô sôû Nhaäp/Xuaát C++
Heä thoáng Nhaäp/Xuaát cuûa C++ cuõng ñieàu khieån caùc stream .
•
Stream
laø moät thieát bò logic coù chöùc naêng taïo ra hoaëc söû duïng thoâng tin. Nhôø heä
thoáng Nhaäp/Xuaát cuûa C++, moãi stream ñöôïc lieân keát vôùi thieát bò vaät lyù. Cho duø coù
nhieàu loaïi thieát bò vaät lyù khaùc nhau, nhöng caùc stream ñeàu ñöôïc xöû lyù nhö nhau.
Chính vì vaäy maø heä thoáng Nhaäp/Xuaát coù theå vaän haønh treân baát kyø loaïi thieát bò
naøo.
Khi moät chöông trình C++ ñöôïc thöïc thi seõ coù boán stream ñöôïc môû moät caùch töï
ñoäng.
Stream
YÙ nghiaõ
Thieát bò maëc ñònh
cin
thieát bò nhaäp chuaån
Baøn phím
cout
thieát bò xuaát chuaån
Maøn hình
cerr
thieát bò baùo loãi chuaån
Maøn hình
clog
Phieân baûn cuûa cerr
Maøn hình
Coù theå ñònh laïi cho caùc stream ñeå lieân keát gaén vôùi caùc thieát bò xuaát nhaäp khaùc.
•
Trong chöông I, C++ cung caáp caùc hoå trôï cho heä thoáng Nhaäp/Xuaát trong file
iostream.h Noäi dung cuûa file naøy laø caùc phaân caáp lôùp hoå trôï caùc thao taùc
Nhaäp/Xuaát. C++ coù hai phaân caáp lôùp Nhaäp/Xuaát, chuùng coù lieân heä vôùi nhau
nhöng chuùng khoâng gioáng nhau.
Phaân caáp lôùp Nhaäp/Xuaát thöù nhaát ñöôïc suy daãn töø lôùp Nhaäp/Xuaát möùc thaáp teân laø
streambuf
. Lôùp naøy cung caáp caùc thao taùc cô baûn cuûa Nhaäp/Xuaát caáp thaáp, cuõng nhö
caùc hoå trôï cô baûn cho toaøn boä heä thoáng Nhaäp/Xuaát cuûa C++
. Laäp trình vieân trình ñoä
cao neân söû duïng tröïc tieáp lôùp streambuf naøy.
Phaân caáp lôùp Nhaäp/Xuaát thöù hai coù teân ios , laø lôùp Nhaäp/Xuaát caáp cao. Noù cung caáp
caùc thao taùc veà ñònh daïng, kieåm loãi, chöùa nhieàu haøm vaø bieán duøng ñeå ñieàu khieån vaø
kieåm soaùt caùc thao taùc cô baûn cuûa caùc stream Nhaäp/Xuaát.
Lôùp ios laø lôùp cô sôû ñeå suy daãn ra caùc lôùp istream, ostream vaø iostream.h. Ba lôùp
daãn xuaát naøy ñöôïc söû duïng ñeå taïo ra caùc stream Nhaäp, Xuaát vaø Nhaäp/Xuaát.
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
210
II/ Nhaäp/Xuaát coù ñònh daïng
1/
Moãi stream cuûa C++ ñöôïc ñi keøm vôùi caùc côø ñònh daïng (format flags).
Caùc côø ñònh daïng naøy xaùc ñònh caùch thöùc theå hieän cuûa döõ lieäu, caùc côø ñöôïc maõ hoaù
döôùi daïng soá nguyeân kieåu long int. Caùc côø ñònh daïng ñöôïc ñaët teân vaø giaù trò trong lôùp
ios
qua baûng lieät keâ nhö sau :
// ios format flags
enum{
skipws
= 0x0001;
left
= 0x0002;
right
= 0x0004;
internal
= 0x0008;
dec
= 0x0010;
oct
= 0x0020;
hex
= 0x0040;
showbase = 0x0080;
showpoint = 0x0100;
uppercase = 0x0200;
showpos
= 0x0400;
scientific
= 0x0800;
fixed
= 0x1000;
unitbuf
= 0x2000;
stdio
= 0x4000;
};
Khi moät côø ñònh daïng naøo ñoù ñöôïc thieát laäp thì ñaëc tính cuûa côø ñoù trôû neân coù hieäu
löïc. Neáu côø ñònh daïng bò xoaù, heä thoáng seõ duøng giaù trò maëc ñònh cho ñaëc tính cuûa côø
ñoù.
2/ Moâ taû caùc côø ñònh daïng
•
Khi côø skipws ñöôïc thieát laäp, caùc kyù töï caùch (goàm caùc kyù töï khoaûng caùch, tab
vaø xuoáng doøng) ñöôïc boû ñi khi ñoïc moät stream. Neáu côø naøy bò xoaù, caùc kyù töï
caùch seõ khoâng bò boû ñi. Thöôøng aùp duïng cho moät soá kieåu file treân diaõ.
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
211
•
Khi côø left ñöôïc thieát laäp, keát xuaát seõ ñöôïc canh bieân traùi.
•
Khi côø right ñöôïc thieát laäp, keát xuaát seõ ñöôïc canh bieân phaûi.
•
Khi côø internal ñöôïc thieát laäp, daáu cuûa trò soá ñöôïc canh bieân traùi trong khi con
soá
ñöôïc canh bieân traùi. Neáu caû ba côø ñeàu bò xoaù, theo maëc ñònh, keát xuaát seõ ñöôïc
canh bieân phaûi.
•
Theo maëc ñònh, giaù trò nguyeân ñöôïc trình baøy döôùi daïng soá thaäp phaân. Tuy
nhieân. coù theå thay ñoåi cô soá cuûa keát xuaát. Thieát laäp côø oct seõ laøm cho keát xuaát
ñöôïc trình baøy döôùi daïng soá heä baùt phaân. Thieát laäp côø hex keát xuaát laø soá heä thaäp
luïc. Ñeå traû laïi kieåu soá thaäp phaân, caàn thieát laäp côø dec.
•
Khi ñaët côø showbase, cô soá cuûa giaù trò soá ñöôïc trình baøy.
•
Khi ñaët côø showpoint cho pheùp in daáu chaám thaäp phaân vaø caùc soá khoâng ñi sau
keøm theo caùc giaù trò kieåu daáu chaám ñoäng.
•
Theo maëc ñònh, khi moät con soá kieåu soá muõ ñöôïc in ra, chöõ "e" ñöôïc trình baøy ôû
kieåu chöõ thöôøng. Töông töï, khi in moät giaù trò soá ôû heä thaäp luïc, kyù töï " duøng chæ
heä thaäp luïc ñöôïc trình baøy ôû kieåu chöõ thöôøng. Khi côø upcase ñöôïc thieát laäp, caùc
kyù töï noùi treân seõ ñöôïc trình baøy baèng kieåu chöõ in hoa.
•
Khi ñaët côø showpos laøm cho xuaát hieän daáu coäng phiaù tröôùc caùc giaù trò soá döông.
•
Khi ñaët côø scientific laøm caùc giaù trò soá kieåu daáu chaám ñoäng ñöôïc trình baøy döôí
daïng muõ. Nhöng khi ñaët côø fixed, caùc giaù trò soá kieåu daáu chaám ñoäng ñöôïc trình
baøy döôí daïng thöôøng coù 6 soá leõ.
•
Khi ñaët côø unitbuf, heä thoáng Nhaäp/Xuaát cuûa C++ ñaåy stream xuaát ra heát sau
moãi thao taùc xuaát.
•
Khi ñaët côø stdio, thieát bò xuaát chuaån stdout vaø thieát bò nhaäp chuaån stdin seõ ñöôïc
ñaåy ra sau moãi thao taùc xuaát. Tuy nhieân côø naøy khoâng ñöôïc ñònh nghiaõ trong
chuaån truø ñònh ANSI C++, vaø coù theå khoâng aùp duïng trong moät soá trình bieân dòch.
3/ Caùc haøm lieân quan ñeán côø ñònh daïng
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
212
•
Haøm setf() duøng thieát laäp côø ñònh daïng. Haøm naøy thuoäc lôùp ios. Daïng toång quaùt
:
long
setf
(long flags) ;
Haøm traû veà giaù trò ñöôïc thieát laäp tröôùc ñoù cuûa côø vaø thieát laäp caùc côø coù teân trong
haøm. Ví duï thieát laäp côø showpos :
stream
.setf(ios::showpos) ;
stream
laø teân stream caàn ñeå thieát laäp côø showpos
Löu y
ù, trong C++, khoâng theå ñaët côø ñònh daïng ôû phaïm vi toaøn cuïc chung cho taát caû
caùc stream, moãi stream seõ mang moät thoâng tin traïng thaùi caùc ñònh daïng rieâng cuûa noù
vaø chuùng ñoäc laäp vôùi nhau.
Coù theå goïi haøm setf() ñeå laäp nhieàu côø cuøng luùc, baèng caùch duøng toaùn töû OR. Ví duï
cout
.setf(ios::showbase | ios::hex) ;
•
Haøm xoaù côø unsetf(), duøng ñeå xoaù moät hay nhieàu côø ñònh daïng. Daïng toång quaùt
:
long
unsetf
(long flags) ;
Haøm traû veà giaù trò tröôùc ñoù cuûa côø.
•
Haøm flags() cho bieát traïng thaùi cuûa côø ñònh daïng. Haøm naøy thuoäc lôùp ios. Daïng
thöôøng goïi :
long flags() ;
Daïng coù keøm ñoái soá long flags(long f) ;
cho pheùp thieát laäp taát caû caùc côø ñònh daïng cuûa stream döïa theo giaù trò cuûa ñoái soá khi
goïi haøm. Töøng bit cuûa giaù trò f seõ ñöôïc gaùn cho bieán löu trò côø ñònh daïng, vaø seõ xoaù
tình traïng côø ñònh daïng tröôùc ñoù. Haøm seõ traû veà giaù trò tình traïng caùc côø ñònh daïng
tröôùc ñoù.
Ví duï 2.1
Minh hoaï haøm setf()
#include <iostream.h>
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
213
int main()
{
// display using default settings
cout << 123.23 << " hello " << 100 << '\n';
cout << 10 << ' ' << -10 << '\n';
cout << 100.0 << "\n\n";
// now, change formats
cout.unsetf(ios::dec); // not required by all compilers
cout.setf(ios::hex | ios::scientific);
cout << 123.23 << " hello " << 100 << '\n';
cout.setf(ios::showpos);
cout << 10 << ' ' << -10 << '\n';
cout. setf(ios::showpoint | ios::fixed);
cout << 100.0;
return 0;
}
Keát quaû cuûa chöông trình
123.23 hello 100
10 -10
100
1.232300e+02 hello 64
a fffffff6
+100.000000
Ví duï 2.2
Minh hoaï haøm unsetf()
#include <iostream.h>
int main()
{
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
214
cout.unsetf(ios::dec);
cout.setf(ios::uppercase | ios::showbase | ios::hex);
cout << 88 << '\n';
cout.unsetf(ios::uppercase);
cout << 88 << '\n';
return 0;
}
Ví duï 2.3
Minh hoaï haøm flags()
#include <iostream.h>
void showflags();
int main()
{
// show default condition of format flags
showflags();
cout.setf(ios::oct | ios::showbase | ios::fixed);
showflags();
return 0;
}
// This function displays the status of the format flags.
void showflags()
{
long f;
f = cout.flags(); // get flag settings
Keát quaû cuûa chöông trình
0X58
0x58
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
215
if(f & ios::skipws) cout << "skipws on\n";
else cout << "skipws off\n";
if(f & ios::left) cout << "left on\n";
else cout << "left off\n";
if(f & ios::right) cout << "right on\n";
else cout << "right off\n";
if(f & ios::internal) cout << "internal on\n";
else cout << "internal off\n";
if(f & ios::dec) cout << "dec on\n";
else cout << "dec off\n";
if(f & ios::oct) cout << "oct on\n";
else cout << "oct off\n";
if(f & ios::hex) cout << "hex on\n";
else cout << "hex off\n";
if(f & ios::showbase) cout << "showbase on\n";
else cout << "showbase off\n";
if(f & ios::showpoint) cout << "showpiont on\n";
else cout << "showpoint off\n";
if(f & ios::showpos) cout << "showpos on\n";
else cout << "showpos off\n";
if(f & ios::uppercase) cout << "uppercase on\n";
else cout << "uppercase off\n";
if(f & ios::scientific) cout << "scientific on\n";
else cout << "scientific off\n";
if(f & ios::fixed) cout << "fixed on\n";
else cout << "fixed off\n";
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
216
if(f & ios::unitbuf) cout << "unitbuf on\n";
else cout << "unitbuf off\n";
if(f & ios::stdio) cout << "stdio on\n";
else cout << "stdio off\n";
cout << "\n";
}
Keát quaû cuûa chöông trình
skipws
is on
left
is off
right
is off
internal
is off
dec
is
off
oct
is off
hex
is off
showbase is off
showpoint is off
uppercase is
off
showpos
is off
scientific
is off
fixed
is off
unitbuf
is off
stdio
is off
skipws
is on
left
is off
right
is off
internal
is off
dec
is
off
oct
is on
hex
is off
showbase
is on
showpoint is off
uppercase is
off
showpos
is off
scientific
is off
fixed
is on
unitbuf
is off
stdio
is off
Ví duï 2.4
Minh hoaï haøm flags(), söû duïng maët naï côø (flag mask) duøng ñeå thieát laäp
caùc côø showpos, showbase, oct vaø right. Boán côø naøy mang giaù trò töông öùng laø
0x0400, 0x0080, 0x0020, 0x0004. Coäng boán giaù trò naøy ta coù giaù trò 0x04A4 .
#include <iostream.h>
void showflags() ;
int main()
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
208
{
// show default condition of format flags
showflags();
// showpos, showbase, oct, right are on, others off
long f = 0x04A4;
cout.flags(f); // set flags
showflags();
return 0;
}
Baøi taäp II
1. Haõy vieát chöông trình thieát laäp traïng thaùi caùc côø ñònh daïng, sao cho caùc giaù trò
nguyeân döông ñöôïc in ra coù mang daáu +. Haõy in ra cho bieát laø caùc côø ñònh daïng ñaõ
ñöôïc thieát laäp.
2. Haõy vieát chöông trình ñeå thieát laäp traïng thaùi caùc côø ñònh daïng cuûa stream cout sao
cho caùc giaù trò soá kieåu daáu chaám ñoäng ñöôïc trình baøy vôùi daáu chaám thaäp phaân. Ngoaøi
ra, caùc giaù trò soá kieåu daáu chaám ñoäng ñöôïc in ra döôùi daïng soá muõ, vôùi kyù töï "E" chæ
phaàn muõ ñöôïc trình baøy baèng kieåu chöõ in hoa.
3. Haõy vieát chöông trình thöïc hieän chöùc naêng löu laïi traïng thaùi hieän taïi cuûa caùc côø
ñònh daïng, tieáp ñeán thieát laäp hai côø showbase vaø hex, roài xuaát ra giaù trò 100, cuoái
cuøng laäp laïi traïng thaùi ban ñaàu cuûa caùc côø traïng thaùi.
III/ Söû duïng caùc haøm width(), precision() vaø fill()
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
209
Caùc haøm naøy thieát laäp caùc tham soá ñònh daïng goàm : ñoä roäng cuûa tröôøng, ñoä chính xaùc
vaø kyù töï laáp ñaày.
Haøm int width(int w) ; vôùi w laø ñoä roäng cuûa tröôøng
Haøm traû veà ñoä roäng cuûa tröôøng tröôùc ñoù.
Haøm int precision(int p); vôùi p laø chính xaùc caàn thieát laäp
Haøm traû veà giaù trò laø chính xaùc tröôùc ñoù.
Haøm char fill (char ch); vôùi ch laø kyù töï laáp ñaày môùi
Haøm traû veà kyù töï laáp ñaày tröôùc ñoù.
Ví duï 3.1
#include <iostream.h>
int main()
{
cout.width(10);
// set minimum field width
cout << "hello" << '\n'; // right justify by default
cout.fill('%');
// set fill character
cout.width(12);
// set width
cout << "hello" << '\n'; // right justify by default
cout.setf(ios::left);
// left justify
cout.width(9);
// set width
cout << "hello" << '\n'; // output left justified
cout.width(12);
// set width
cout.precision(10); // set 10 digits of precision
cout << 123.234567 << '\n';
cout.width(10);
// set width
cout.precision(3); // set 3 digits of precision
cout << 123.234567 << '\n';
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
210
return 0;
}
Keát quaû cuûa chöông trình
hello
%%%%%%%hello
hello%%%%
123.234567%%
123.234%%%
Ví duï 3.2
Caùc haøm ñònh daïng Nhaäp/Xuaát cuûa C++
// Create a table of square roots and squares.
#include <iostream.h>
#include <math.h>
int main()
{
double x;
cout.precision(4);
cout << "x sqrt(x) x^2\n\n";
for(x = 2.0; x <= 20.0; x++) {
cout.width(7);
cout << x << " ";
cout.width(7);
cout << sqrt(x) << " ";
cout.width(7);
cout << x*x << '\n';
}
return 0;
}
Baøi taäp III
Keát quaû cuûa chöông trình
x sqrt(x)
x^2
2
1.4142
4
3
1.7321
9
4
2
16
5
2.2361
25
...
...
...
20 4.4721 400
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
211
1. Haõy vieát chöông trình thieát in ra logarit cô soá töï nhieân vaø logarit cô soá thaäp phaân
cuûa caùc con soá töø 2 ñeán 100. Ñònh daïng baûng soá sao cho caùc con soá ñöôïc canh bieân
phaûi vôùi ñoä roäng tröôøng laø 10. Söû duïng ñoä chính xaùc laø 5.
2. Taïo moät haøm mang teân laø : void center(char *s) ;
Chöùc naêng cuûa haøm laø canh giöõa moät chuoãi kyù töï treân maøn hình. Ñeå thöïc hieän haøm
naøy, haõy söû duïng haøm width(). Giaû söû maøn hình coù ñoä roäng 80 coät (vaø ñeå cho ñôn
giaûn, giaû söû chuoãi kyù töï coù chieàu daøi < 80 kyù töï).
IV/ Söû duïng boä thao taùc Nhaäp/Xuaát (I/O Manipulator)
Boä thao taùc Nhaäp/Xuaát
laø caùc haøm ñaëc bieät söû duïng trong caùc meänh ñeà Nhaäp/Xuaát.
Caàn phaûi naïp file tieâu ñeà iomanip.h vaøo chöông trình. Caùc boä thao taùc Nhaäp/Xuaát
chuaån ñöôïc trình baøy trong baûng sau :
Boä thao taùc
Muïc ñích
Nhaäp/Xuaát
dec
Ñònh daïng döõ lieäu kieåu soá ôû daïng thaäp phaân
Xuaát
endl
Xuaát moät kyù töï xuoáng doøng vaø
ñaåy stream ra thieát bò vaät lyù
Xuaát
ends
Xuaát moät kyù töï roãng
Xuaát
flush
Ñaåy stream ra thieát bò vaät lyù
Xuaát
hex
Ñònh daïng döõ lieäu kieåu soá ôû daïng thaäp luïc phaân Xuaát
oct
Ñònh daïng döõ lieäu kieåu soá ôû daïng baùt phaân
Xuaát
resetiosflags(long f) Xoùa caùc côø xaùc ñònh trong f
Nhaäp/Xuaát
setbase(int base)
Ñaët cô soá thaønh base
Xuaát
setfill(int ch)
Ñaët ch laøm kyù töï laáp ñaày
Xuaát
setiosflags(long f)
Thieát laäp caùc côø xaùc ñònh trong f
Nhaäp/Xuaát
setprecision(int p)
Ñaët ñoä chính xaùc laø p
Xuaát
setw(int w)
Ñaët ñoä roäng cuûa tröôøng laø w
Xuaát
ws
Boû qua caùc kyù töï caùch (khoaûng caùch, tab, xuoáng
doøng)
Nhaäp
Caùc boä thao taùc coù theå xuaát hieän trong caùc meänh ñeà Nhaäp/Xuaát. Ví duï
cout << oct << 100 << hex << 100;
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
212
cout << setw(10) << 100;
Löu yù caùc boä thao taùc Nhaäp/Xuaát chæ coù aûnh höôûng ñeán stream coù teân trong bieåu
thöùc Nhaäp/Xuaát, caùc boä thao taùc naøy khoâng aûnh höôûng ñeán taát caû caùc stream ñang
môû.
•
Söû duïng boä thao taùc Nhaäp/Xuaát laø caùch thöù hai ñeå ñònh daïng thoâng tin trong heä
thoáng Nhaäp/Xuaát cuûa C++. Trong moät soá tröôøng hôïp, söû duïng boä thao taùc
Nhaäp/Xuaát deã daøng hôn laø duøng caùc côø vaø haøm ñònh daïng.
Öu ñieåm
so vôùi caùc haøm ñònh daïng khaùc cuûa ios laø
+ tính deã söû duïng
+ maõ chöông trình seõ ngaén goïn hôn.
Neáu muoán thieát laäp moät soá côø ñònh daïng baèng boä thao taùc, haõy duøng setiosflags(). Boä
thao taùc naøy coù chöùc naêng gioáng nhö haøm setf().
Neáu muoán xoaù moät soá côø ñònh daïng baèng boä thao taùc, haõy duøng resetiosflags(). Boä
thao taùc naøy coù chöùc naêng gioáng nhö haøm unsetf().
Ví duï 4.1
Söû duïng boä thao taùc Nhaäp/Xuaát
#include <iostream.h>
#include <iomanip.h>
int main()
{
cout << hex << 100 << endl;
//
64
cout << oct << 10 << endl; //
12
cout << setfill('X') << setw(10);
cout << 100 << " hi " << endl;
// XXXXXXX144 hi
return 0;
}
Ví duï 4.2
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
213
// This version uses I/O manipulators to display the table of squares and square
roots.
#include <iostream.h>
#include <iomanip.h>
#include <math.h>
int main()
{
double x;
cout << setprecision(4);
cout << " x sqrt(x) x^2\n\n";
for(x = 2.0; x <= 20.0; x++) {
cout << setw(7) << x << " ";
cout << setw(7) << sqrt(x) << " ";
cout << setw(7) << x*x << '\n';
}
return 0;
}
Baøi taäp IV
1. Thöïc hieän caùc baøi taäp 1 vaø 2 cuûa phaàn III chöông 7, trong ñoù haõy söû duïng caùc boä
thao taùc Nhaäp/Xuaát thay cho haøm ñònh daïng.
2. Vieát moät chöông trình nhoû xuaát giaù trò 100 ôû daïng soá thaäp luïc phaân coù keøm theo
kyù töï chæ heä thaäp luïc (0x). Haõy söû duïng boä thao taùc setiosflags().
V. Taïo boä cheøn vaøo (inserter)
Keát quaû chöông trình
x sqrt(x)
x^2
2
1.4142
4
3
1.7321
9
4
2
16
5 2.2361 25
...
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
214
Quaù taûi toaùn töû Nhaäp/Xuaát cho caùc lôùp töï taïo laø moät trong nhöõng lyù do quyeát ñònh söû
duïng meänh ñeà Nhaäp/Xuaát cuûa C++ thay cho vieäc söû duïng caùc haøm Nhaäp/Xuaát theo
kieåu C.
•
Theo C++, thao taùc xuaát coøn ñöôïc goïi laø cheøn (insert), toaùn töû << coøn goïi laø
toaùn töû cheøn.
Khi quaù taûi toaùn töû naøy, nghiaõ laø taïo moät haøm cheøn, hay coøn goïi laø
boä cheøn
(inserter) , do toaùn töû << thöïc hieän chöùc naêng cheøn thoâng tin vaøo trong
moät stream.
Cuù phaùp caùc boä cheøn
ostream
&operator << (ostream &stream, class_name ob)
{
// body of inserter
}
stream : tham soá thöù nhaát tham chieáu ñeán moät ñoái töôïng thuoäc kieåu ostream.
Stream stream phaûi laø moät stream xuaát
ob
: tham soá thöù hai laø ñoái töôïng caàn xuaát (noù coù theå laø moät tham chieáu)
Boä cheøn seõ traû veà moät tham chieáu ñeán stream stream kieåu ostream. Ñieàu naøy caàn
thieát khi söû duïng toaùn töû << trong caùc bieåu thöùc Nhaäp/Xuaát phöùc taïp, ví duï
cout << ob1 << ob2 << ob2;
Noäi dung cuûa boä cheøn
coù theå thöïc hieän baát kyø thuû tuïc naøo maø laäp trình vieân muoán.
Kinh nghieäm cho bieát, neân giôùi haïn chöùc naêng cuûa noù trong phaïm vi keát xuaát thoâng
tin ra moät stream.
•
Moät boä cheøn khoâng ñöôïc pheùp laø thaønh phaàn cuûa lôùp maø boä cheøn naøy thao taùc.
Lyù do, khi moät haøm toaùn töû kieåu baát kyø laø moät thaønh phaàn cuûa moät lôùp naøo ñoù, toaùn
haïng beân traùi voán ñöôïc tham chieáu khoâng töôøng minh baèng con troû, laïi laø moät ñoái
töôïng phaùt sinh ra vieäc goïi haøm toaùn töû. Coù nghiaõ laø, toaùn haïng beân traùi laø moät ñoái
töôïng cuûa chính lôùp ño
ù.
Ñoái vôùi boä cheøn, toaùn haïng beân traùi (cuûa <<) laø moät stream thay vì moät ñoái töôïng,
vaø toaùn haïng beân phaûi laø moät ñoái töôïng caàn ñöôïc keát xuaát.
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
215
@ C++ cho pheùp boä cheøn laø haøm friend cuûa lôùp maø noù thao taùc.
Ví duï 5.1
Lôùp coord chöùa boä cheøn laø haøm friend
// Use a friend inserter for objects of type coord.
#include <iostream.h>
class coord {
int x, y;
public:
coord() { x = 0; y = 0; }
coord(int i, int j) { x = i; y = j; }
friend ostream &operator<<(ostream &stream, coord ob);
};
ostream &operator<<(ostream &stream, coord ob)
{
stream << ob.x << ", " << ob.y << '\n'; // xaây döïng boä cheøn ôû möùc toång quaùt hoaù
return stream;
//
vôùi
stream laø moät stream baát ky
ø
}
int main()
{
coord a(1, 1), b(10, 23);
cout << a << b;
return 0;
}
@ Laäp trình vieân neân traùnh caùch xaây döïng boä cheøn bò haïn cheá bôûi vieäc keát xuaát
thoâng tin ra thieát bò xuaát chuaån gaén vôùi stream cout.
ostream &operator<<(ostream &stream, coord ob)
{
Keát quaû chöông trình
1, 1
10, 23
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
216
cout << ob.x << ", " << ob.y << '\n';
return stream;
}
Ví duï 5.2
Lôùp coord chöùa boä cheøn khoâng phaûi laø haøm friend .
// Create an inserter for objects of type coord, using a non-friend inserter.
#include <iostream.h>
class coord {
public:
int x, y; // must be public
coord() { x = 0; y = 0; }
coord(int i, int j) { x = i; y = j; }
};
// An inserter for the coord class.
ostream &operator<<(ostream &stream, coord ob)
{
stream << ob.x << ", " << ob.y << '\n';
return stream;
}
int main()
{
coord a(1, 1), b(10, 23);
cout << a << b;
return 0;
}
•
Moät boä cheøn khoâng chæ giôûi haïn ôû vieäc xuaát thoâng tin daïng vaên baûn. Noù coù theå
thöïc hieän caùc thao taùc
hay chuyeån ñoåi thoâng tin caàn thieát ñeå keát xuaát thoâng tin ra
thieát bò rieâng bieät
hay moät tình huoáng rieâng bieät naøo ñoù.
Ví duï 5.3
Boä cheøn xuaát thoâng tin ra maùy veõ (plotter)
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
217
// This program draws right triangles
#include <iostream.h>
class triangle {
int height, base;
public:
triangle(int h, int b) { height = h; base = b; }
friend ostream &operator<<(ostream &stream, triangle ob);
};
// Draw a triangle.
ostream
&operator<<(ostream &stream, triangle ob)
{
int i, j, h, k;
i = j = ob.base - 1;
for( h = ob.height - 1; h ; h--) {
for( k = i; k; k--)
stream << ' ';
stream << '-';
if( j != i) {
for( k = j - i - 1; k; k--) stream << ' ';
stream << '-';
}
i--;
stream << '\n';
}
for( k = 0; k < ob.base; k++) stream << '-';
stream << '\n';
return stream;
}
Keát quaû chöông trình laø
3 hình tam giaùc vuoâng ñoàng daïng vôùi
kích thöôùc khaùc nhau
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
218
int main()
{
triangle t1(5, 5), t2(10, 10), t3(12, 12);
cout << t1;
cout << endl << t2 << endl << t3;
return 0;
}
Baøi taäp V
1. Cho lôùp strtype vaø ñoaïn chöông trình sau. Haõy taïo boä cheøn cho lôùp strtype ñeå xuaát
chuoãi kyù töï ra maøn hình.
#include <iostream.h>
#include <string.h>
#include <stdlib.h>
class strtype {
char *p;
int len;
public:
strtype(char *ptr);
~strtype() {delete [] p;}
friend ostream &operator<<(ostream &stream, strtype &ob);
};
strtype::strtype(char *ptr)
{
len = strlen(ptr)+1;
p = new char [len];
if(!p) {
cout << "Allocation error\n";
exit(1);
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
219
}
strcpy(p, ptr);
}
// Create operator<< inserter function here.
// ...
int main()
{
strtype s1("This is a test."), s2("I like C++.");
cout << s1 << '\n' << s2;
return 0;
}
2. Haõy thay theá haøm show() trong chöông trình sau baèng boä cheøn do baïn taïo ra
#include <iostream.h>
class planet {
protected:
double distance; // miles from the sun
int revolve;
// in days
public:
planet(double d, int r) { distance = d; revolve = r; }
};
class earth : public planet {
double circumference; // circumference of orbit
public:
earth(double d, int r) : planet(d, r) {
circumference = 2*distance*3.1416;
}
// Rewrite this so that it displays the information using an inserter function.
void show() {
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
220
cout << "Distance from sun: " << distance << '\n';
cout << "Days in obit: " << revolve << '\n';
cout << "Circumference of orbit: " << circumference << '\n';
}
};
int main()
{
earth ob(93000000, 365);
cout << ob;
return 0;
}
VI. Taïo boä chieát (extractor)
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
221
•
Trong C++, thao taùc nhaäp coøn ñöôïc goïi laø chieát (extractor), toaùn töû >> coøn goïi
laø toaùn töû chieát. Khi quaù taûi toaùn töû naøy, nghiaõ laø taïo moät haøm chieát, hay coøn goïi
laø boä chieát (extractor) , do toaùn töû >> thöïc hieän chöùc naêng laáy thoâng tin töø moät
stream.
Cuù phaùp caùc boä chieát
istream
&operator >> (istream &stream, class_name &ob)
{
// body of extractor
}
stream : tham soá thöù nhaát tham chieáu ñeán moät stream nhaäp istream.
ob
: tham soá thöù hai tham chieáu ñeán ñoái töôïng nhaän thoâng tin nhaäp vaøo
Boä chieát seõ traû veà moät tham chieáu ñeán stream nhaäp kieåu istream.
Noäi dung cuûa boä chieát
coù theå thöïc hieän baát kyø thuû tuïc naøo. Tuy nhieân, neân giôùi haïn
chöùc naêng cuûa noù trong phaïm vi nhaäp thoâng tin.
•
Moät boä chieát khoâng ñöôïc pheùp laø thaønh phaàn cuûa lôùp maø boä chieát naøy thao taùc.
C++ cho pheùp boä cheøn laø haøm friend cuûa lôùp maø noù thao taùc.
Ví duï 6.1
Taïo boä chieát cho lôùp coord
// Add a friend extractor for objects of type coord.
#include <iostream.h>
class coord {
int x, y;
public:
coord() { x = 0; y = 0; }
coord(int i, int j) { x = i; y = j; }
friend ostream &operator<<(ostream &stream, coord ob);
friend istream &operator>>(istream &stream, coord &ob);
};
ostream &operator<<(ostream &stream, coord ob)
{
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
222
stream << ob.x << ", " << ob.y << '\n';
return stream;
}
istream
&operator>>(istream &stream, coord &ob)
{
cout << "Enter coordinates: "; // thoâng baùo nhaäp döõ lieäu naøy laø caàn thieát ôû boä
chieát
stream >> ob.x >> ob.y;
return stream;
}
int main()
{
coord a(1, 1), b(10, 23);
cout << a << b;
cin >> a;
cout << a;
return 0;
}
Ví duï 6.2
Lôùp inventory löu thoâng tin kieåm keâ haøng toàn kho goàm teân haøng, löôïng
toàn vaø trò giaù, chöùa boä cheøn vaø boä chieát.
#include <iostream.h>
#include <string.h>
class inventory {
char item[40];
// name of item
int onhand;
// number on hand
double cost;
// cost of item
public:
inventory(char *i, int o, double c)
{
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
223
strcpy(item, i);
onhand = o;
cost = c;
}
friend ostream &operator<<(ostream &stream, inventory ob);
friend istream &operator>>(istream &stream, inventory &ob);
};
ostream &operator<<(ostream &stream, inventory ob)
{
stream << ob.item << ": " << ob.onhand;
stream << " on hand at $" << ob.cost << '\n';
return stream;
}
istream
&operator>>(istream &stream, inventory &ob)
{
cout << "Enter item name: ";
stream >> ob.item;
cout << "Enter number on hand: ";
stream >> ob.onhand;
cout << "Enter cost: ";
stream >> ob.cost;
return stream;
}
int main()
{
inventory ob("hammer", 4, 12.55);
cout << ob;
cin >> ob;
cout << ob;
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
224
return 0;
}
Baøi taäp VI
1. Boå sung vaøo lôùp strtype trong baøi taäp 1 phaàn V, chöông 7, moät boä chieát ñeå nhaäp
thoâng tin cho lôùp strtype.
2. Haõy taïo ra moät lôùp factor duøng ñeå löu moät giaù trò nguyeân num vaø thöøa soá nhoû nhaát
cuûa noù laø lfact. Haõy taïo boä cheøn vaø boä chieát cho lôùp treân.
Baøi taäp chöông 7
1. Vieát moät chöông trình ñeå trình baøy giaù trò 1000 ôû daïng thaäp phaân, thaäp luïc phaân vaø
baùt phaân, söû duïng caùc côø ñònh daïng cuûa ios.
2. Vieát moät chöông trình ñeå trình baøy giaù trò 1000.1234 trong moät tröôøng coù chieàu
daøi 20 coät, con soá ñöôïc canh bieân traùi, soá coù hai chöõ soá sau daáu chaám thaäp phaân, vaø
ñöôïc laáp ñaày choã troáng baèng kyù töï * , söû duïng caùc côø ñònh daïng cuûa ios.
3. Thöïc hieän laïi baøi taäp 1 vaø 2, söû duïng boä taïo thao taùc nhaäp/xuaát thay cho côø ñònh
daïng.
4. Haõy taïo boä cheøn vaø boä chieát cho lôùp pwr tính haøm muõ x^n trong chöông trình sau
class pwr {
int base;
int exponent;
double result;
// base to the exponent power
public:
pwr(int b, int e);
};
pwr::pwr(int b, int e)
{
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
225
base = b;
exponent = e;
result = 1;
for( ; e; e--)
result = result * base;
}
5. Haõy taïo moät lôùp box ñeå löu tröõ thoâng tin veà kích thöôùc cuûa moät hình vuoâng. Haõy
taïo boä cheøn vaø boä chieát cho lôùp box ñeå in hình vuoâng ñoù ra maøn hình.
6. Haõy taïo boä cheøn ñeå xuaát noäi dung cuûa moät stack cuûa lôùp stack sau
#include <iostream.h>
#define SIZE 10
// Declare a stack class for characters
class stack {
char stck[SIZE]; // holds the stack
int tos;
// index of top-of-stack
public:
stack();
void push(char ch);
// push character on stack
char pop();
// pop character from stack
};
// Initialize the stack
stack::stack()
{
tos = 0;
}
// Push a character.
void stack::push(char ch)
{
if(tos==SIZE) {
cout << "Stack is full\n";
return;
}
Chöông 7 Heä thoáng Nhaäp / Xuaát C++
226
stck[tos] = ch;
tos++;
}
// Pop a character.
char stack::pop()
{
if(tos==0) {
cout << "Stack is empty\n";
return 0;
// return null on empty stack
}
tos--;
return stck[tos];
}
7. Haõy vieát chöông trình chöùa lôùp watch coù bieán rieâng t vôùi kieåu döõ lieäu laø time_t.
Haøm taïo cuûa lôùp naøy duøng haøm thôøi gian chuaån time() ñeå laáy giôø cuûa heä thoáng vaø
löu laïi vaøo bieán t. Haõy taïo boä cheøn ñeå trình baøy thôøi gian. Söû duïng caùc haøm
localtime() vaø asctime() .
8. Cho lôùp ft_to_inche duøng ñeå ñoåi ñôn vò chieàu daøi töø feet sang inch. Haõy taïo boä
chieát cho lôùp naøy ñeå nhaäp giaù trò baèng feet. Haõy taïo boä cheøn duøng ñeå trình baøy soá ño
ôû ñôn vò laø feet vaø inch. Vieát chöông trình ñeå bieåu dieãn hoaït ñoäng cuûa boä cheøn vaø boä
chieát.
class ft_to_inches {
double feet;
double inches;
public:
void set(double f) {
feet = f;
inches = f * 12;
// inserter and extractor
}
};
Chöông 8
Nhaäp/Xuaát C++ naâng cao
•
Taïo Boä thao taùc Nhaäp/Xuaát
•
Nhaäp/Xuaát File
•
Nhaäp/Xuaát File nhò phaân khoâng ñònh daïng
•
Caùc haøm Nhaäp/Xuaát nhò phaân
•
Truy caäp ngaãu nhieân
•
Kieåm tra traïng thaùi Nhaäp/Xuaát
•
Nhaäp/Xuaát theo ñôn ñaët haøng vaø caùc File
•
Nhaäp/Xuaát theo maûng
Chöông 8 Nhaäp / Xuaát C++
naâng cao
228
Chöông 8 Nhaäp / Xuaát C++
naâng cao
229
I/ Taïo Boä thao taùc Nhaäp/Xuaát
Ngoaøi boä cheøn vaø boä chieát, coù theå söûa ñoåi heä thoáng nhaäp/xuaát cuûa C++ baèng caùch
taïo ra boä thao taùc nhaäp/xuaát töï taïo
. Noù coù hai lyù do :
* moät boä thao taùc coù theå hôïp nhaát moät daõy caùc thao taùc nhaäp/xuaát thaønh moät boä thao
taùc töï taïo.
* moät boä thao taùc nhaäp/xuaát töï taïo caàn thieát khi nhaäp/xuaát treân caùc thieát bò khoâng
chuaån (maùy in ñaëc bieät hay heä thoáng nhaän daïng quang hoïc) .
Coù hai loaïi boä thao taùc, moät duøng cho caùc stream nhaäp, moät duøng cho caùc stream
xuaát. Ngoaøi ra ngöôøi ta coøn phaân thaønh hai nhoùm : boä thao taùc coù tham soá vaø boä thao
taùc khoâng coù tham soá
, chuùng khaùc nhau veà caùch taïo ra boä thao taùc. Vieäc taïo ra boä
thao taùc coù tham soá khoâng thuoäc phaïm vi baøi giaûng naøy.
•
Daïng toång quaùt cuûa caùc boä thao taùc xuaát khoâng coù tham soá :
ostream &manip_name(ostream &stream)
{
// program codes
return
stream
}
manip_name
teân cuûa boä thao taùc ñöôïc taïo ra
Löu yù : boä thao taùc treân coù ñoái soá laø moät tham chieáu ñeán stream maø noù thao taùc, khi
goïi boä naøy, khoâng ñöôïc keøm theo teân boä thao taùc baát kyø moät ñoái soá naøo.
•
Daïng toång quaùt cuûa caùc boä thao taùc nhaäp khoâng coù tham soá :
istream &manip_name(istream &stream)
{
// program codes
return
stream
}
Chöông 8 Nhaäp / Xuaát C++
naâng cao
230
Moät boä thao taùc nhaäp nhaän moät tham chieáu ñeán stream maø noù thao taùc. Stream naøy
phaûi ñöôïc traû veà bôûi boä thao taùc.
Ví duï 1.1
Chöông trình taïo ra boä thao taùc xuaát setup(). Khi ñöôïc goïi, boä naøy seõ
thieát laäp ñoä roäng tröôøng laø 10, ñoä chính xaùc laø 4 vaø daáu "* " laø kyù töï laáp ñaày.
#include <iostream.h>
ostream &setup(ostream &stream)
{
stream.width(10);
stream.precision(4);
stream.fill('*');
return stream;
}
int main()
{
cout << setup << 123.123456;
return 0;
}
Keát quûa chöông trình
**123.1234
Ví duï 1.2
Hai boä thao taùc atn() vaø note() ñôn giaûn sau ñaây laøm goïn hôn ñoaïn
chöông trình in caùc töø hay ñoaïn caâu hay laëp laïi trong chöông trình.
#include <iostream.h>
// Attention:
ostream &atn(ostream &stream)
{
stream << "Attention: ";
return stream;
}
Chöông 8 Nhaäp / Xuaát C++
naâng cao
231
// Please note:
ostream ¬e(ostream &stream)
{
stream << "Please Note: ";
return stream;
}
int main()
{
cout << atn << "High voltage circuit\n";
cout << note << "Turn off all lights\n";
return 0;
}
Ví duï 1.3
Chöông trình taïo boä thao taùc nhaäp getpass() thöïc hieän baùo tieáng chuoâng
vaø thoâng baùo ñeà nghò nhaäp maät khaåu.
#include <iostream.h>
#include <string.h>
// A simple input manipulator
istream &getpass(istream &stream)
{
cout << '\a'; // sound bell
cout << "Enter password: ";
return stream;
}
int main()
{
char pw[80];
do {
cin >> getpass >> pw;
Chöông 8 Nhaäp / Xuaát C++
naâng cao
232
} while (strcmp(pw, "password"));
cout << "Logon complete\n";
return 0;
}
Baøi taäp I
1. Haõy taïo moät boä thao taùc môùi teân laø td() duøng ñeå hieän giôø vaø ngaøy hieän taïi cuûa heä
thoáng.
2. Haõy taïo moät boä thao taùc môùi teân laøsethex() duøng ñeå thieát laäp caùc traïng thaùi ñeå in
moät soá thaäp luïc phaân, ñaët caùc côø uppercase vaø showbase. Ngoaøi ra, haõy taïo moät boä
thao taùc xuaát teân laø reset() ñeå phuïc hoài laïi traïng thaùi tröôùc khi goïi sethex().
3. Haõy taïo moät boä thao taùc môùi teân laø skipchar() duøng ñeå ñoïc vaø boû qua möôøi kyù töï
lieân tieáp töø moät stream nhaäp.
Chöông 8 Nhaäp / Xuaát C++
naâng cao
233
II/ Nhaäp/Xuaát File
1/ Khaùi nieäm
Ñeå söû duïng nhaäp/xuaát file trong chöông trình caàn phaûi naïp file fstream.h . File naøy
ñònh nghiaõ nhieàu lôùp goàm ifstream, ofstream vaø fstream. Ba lôùp naøy ñöôïc suy daãn
töø hai lôùp istream vaø ostream, vaø ios laø lôùp cô sôû cuûa chuùng. Do ñoù caùc lôùp ifstream,
ofstream vaø fstream cuõng coù theå truy xuaát ñeán taát caû caùc thao taùc ñaõ ñònh nghóa trong
ios
.
Trong C++, moät file ñöôïc môû baèng caùch lieân keát noù vôùi moät stream. Coù ba loaïi stream
: nhaäp, xuaát vaø nhaäp/xuaát
. Tröôùc khi môû file phaûi taïo ra stream töông öùng.
Ñeå taïo moät stream nhaäp, caàn khai baùo stream ñoù thuoäc lôùp ifstream.
Ñeå taïo moät stream xuaát, caàn khai baùo stream ñoù thuoäc lôùp ofstream.
Ñoái vôùi stream thöïc hieän caû thao taùc nhaäp vaø xuaát, caàn khai baùo stream ñoù thuoäc lôùp
fstream
.
Ví duï
ifstream
in
; // input stream
ofstream
out
; // output stream
fstream
io
; // input and output stream
2/ Môû file
a/ Sau khi taïo ra moät stream, coù theå môû file gaén vôùi stream ñoù baèng haøm open().
Haøm naøy laø haøm thaønh phaàn cuûa ba stream noùi treân, daïng toång quaùt :
void
open
(const char *filename, int mode, int access);
filename
teân cuûa file caàn môû, coù theå ñi keøm vôùi ñöôøng daãn.
mode
xaùc ñònh cheá ñoä cuûa file ñöôïc môû.
access
xaùc ñònh caùch truy caäp file
@ Caùc giaù trò nguyeân cuûa mode, coù theå laø moät hay nhieàu giaù trò (ñöôïc keá thöøa bôûi
fstream.h)
•
Cheá ñoä ios::app laøm cho keát xuaát ñöôïc theâm vaøo cuoái cuûa file. Duøng cho caùc
file xuaát.
Chöông 8 Nhaäp / Xuaát C++
naâng cao
234
•
Cheá ñoä ios::ate cho pheùp chuyeån ñeán vò trí cuoái file ngay sau khi file ñöôïc môû.
Löu yù, maëc duø ñang ôû vò trí cuoái file, caùc thao taùc nhaäp/xuaát vaãn coù theå xuaát
hieän ôû baát cöù vò trí naøo cuûa file.
•
Cheá ñoä ios::in xaùc ñònh file ñöôïc môû laø file nhaäp. Cheá ñoä ios::out xaùc ñònh file
ñöôïc môû laø file xuaát
.
Tuy nhieân, vieäc taïo ra moät stream baèng caùc khai baùo noù thuoäc lôùp ifstream ngaàm
ñònh noù laø moät stream nhaäp, cuõng nhö khai baùo stream thuoäc lôùp ofstream ngaàm
ñònh noù laø moät stream xuaát. Trong hai tröôøng hôïp treân, khoâng caàn phaûi xaùc ñònh caùc
giaù trò ios::in vaø ios::out khi môû file.
•
Cheá ñoä ios::binary laøm cho file ñöôïc môû ôû cheá ñoä nhò phaân.
Theo maëc ñònh, taát caû caùc file ñöôïc môû ôû cheá ñoä vaên baûn (text mode). Trong cheá ñoä
vaên baûn, seõ coù moät soá tröôøng hôïp kyù töï seõ bò chuyeån ñoåi. Ví duï, kyù töï taïo doøng môùi (
'\n' ) seõ ñöôïc chuyeån thaønh chuoåi lieân tieáp nhau cuûa hai kyù töï xuoáng doøng (carriage
return, maõ 13), vaø theâm moät doøng (line-feed, maõ 10).
Khi hoaït ñoäng ôû cheá ñoä nhò phaân, seõ khoâng coù baát kyø moät tröôøng hôïp chuyeån ñoåi kyù töï
naøo
. Baát kyø moät file naøo ñeàu coù theå hoaït ñoäng ôû hai cheá ñoä vaên baûn hay nhò phaân.
•
Cheá ñoä ios::nocreate laøm cho vieäc goïi haøm open() bò thaát baïi neáu file ñöôïc môû
laø moät file môùi (chöa coù saün treân ñiaõ). Coøn ios::noreplace laøm cho vieäc goïi haøm
open()
bò thaát baïi neáu file ñöôïc môû ñaõ coù saün treân ñiaõ.
•
Cheá ñoä ios::trunc laøm cho khi file coù saün truøng teân vôùi file ñöôïc môû seõ bò xoaù
saïch noäi dung.
Coù theå söû duïng keát hôïp hai hay nhieàu cheá ñoä ôû treân baèng pheùp toaùn OR.
@ Caùc giaù trò cuûa ñoái soá access xaùc ñònh caùch truy caäp file.
Giaù trò ngaàm ñònh cuûa ñoái soá naøy laø filebuf::openprot (filebuf laø lôùp cha cuûa caùc
lôùp stream). Trong moâi tröôøng UNIX noù coù giaù trò 0x644 ñoái vôùi caùc file thoâng
thöôøng.
Trong moâi tröôøng DOS/WINDOWS giaù trò cuûa ñoái soá access qui ñònh maõ thuoäc tính
cuûa file, bao goàm :
Chöông 8 Nhaäp / Xuaát C++
naâng cao
235
Thuoäc tính
YÙ nghiaõ
0
Archive
File bình thöôøng : ghi / ñoïc (maëc ñònh)
1
Read only File chæ ñoïc
2 Hidden File
aån
4 System File
heä
thoáng
8 Save
Thuoäc
tính
löu
tröõ
Coù theå söû duïng keát hôïp hai hay nhieàu thuoäc tính ôû treân baèng pheùp toaùn OR.
•
Ví duï ñoaïn chöông trình sau minh hoaï vieäc môû file bình thöôøng trong
DOS/WINDOWS
ofstream
out
;
// khai baùo stream xuaát
out.open
("test.txt", ios::out, 0) ;
hoaëc
out.open
("test.txt") ; // lôøi goïi ngaén goïn, thoâng thöôøng.
•
Ñeå môû file nhaäp/xuaát, caàn phaûi xaùc ñònh caû hai cheá ñoä ios::in vaø ios::out cho ñoái
soá mode, ñöôïc minh hoaï sau ñaây. Löu yù, khoâng coù giaù trò maëc ñònh cho tröôøng
hôïp naøy.
fstream
mystream
;
// khai baùo stream xuaát
mystream.open
("test.txt", ios::in | ios::out) ;
Neáu haøm open() khoâng thöïc thi ñöôïc, stream ñöôïc traû veà seõ mang giaù trò khoâng. Do
ñoù, caàn kieåm tra laïi vieäc môû file coù thaønh coâng hay khoâng, tröôùc khi truy xuaát noù. Ví
duï :
if(!
mystream)
{
cout << "Can't open file \n";
//
handle
error
}
b/ Duøng haøm taïo ñeå môû file
Chöông 8 Nhaäp / Xuaát C++
naâng cao
236
Thoâng thöôøng, khoâng caàn duøng haøm open() ñeå môû file, vì caùc lôùp ifstream,
ofstream
vaø fstream ñaõ coù saün caùc haøm taïo duøng ñeå môû file moät caùch töï ñoäng. Caùc
haøm taïo naøy coù caùc ñoái soá gioáng heät nhö cuûa haøm open(). Daïng thoâng thöôøng môû file
ñeå nhaäp
:
ifstream
mystream("test.txt");
Caàn kieåm tra laïi vieäc môû file coù thaønh coâng hay khoâng, tröôùc khi truy xuaát noù.
3/ Ñoùng file
Duøng haøm void close(). Haøm naøy khoâng coù ñoái soá vaø khoâng traû veà giaù trò naøo caû.
Ví duï ñoùng moät file ñang gaén vôùi stream mystream, caàn goïi :
mystream.close()
;
•
Ñeå kieåm tra tình traïng heát file duøng haøm eof()
int eof();
Haøm traû veà giaù trò
≠
0 khi ñang ôû tình traïng cuoái file.
giaù trò = 0 ngöôïc laïi.
Ví duï
mystream.eof()
;
4/ Truy xuaát noäi dung treân file
Toaùn töû xuaát << vaø toaùn töû nhaäp >> ñöôïc söû duïng ñeå truy xuaát noäi dung treân file,
caàn phaûi thay caùc stream cin vaø cout baèng stream lieân keát vôùi file.
Thoâng tin löu treân file coù cuøng ñònh daïng nhö khi noù ñöôïc trình baøy treân maøn hình.
Do ñoù, caùc file taïo ra baèng toaùn töû xuaát << vaø caùc file ñöôïc ñoïc vaøo baèng toaùn töû
nhaäp >> ñeàu laø caùc file vaên baûn coù ñònh daïng.
Ví duï 2.1
Taïo moät file xuaát, ghi leân file, ñoùng file. Môû file ñoù nhö moät file nhaäp,
ñoïc noäi dung cuûa file.
#include <iostream.h>
#include <fstream.h>
Chöông 8 Nhaäp / Xuaát C++
naâng cao
237
#include <iomanip.h>
int main()
{
ofstream fout("test.txt"); // create output file
if(!fout) {
cout << "Cannot open output file.\n";
return 1;
}
fout << "Hello!\n";
fout << 100 << ' ' << hex << 100 << endl;
fout.close();
ifstream fin("test.txt"); // open input file
if(!fin) {
cout << "Cannot open input file.\n";
return 1;
}
char str[80];
int i, j;
fin >> str >> i >> j;
cout << str << ' ' << i << ' ' << j << endl;
fin.close();
return 0;
}
Keát quaû chöông trình, noäi dung trong file test.txt
Chöông 8 Nhaäp / Xuaát C++
naâng cao
238
Hello!
100 64
Ví duï 2.2
Chöông trình ñoïc töø baøn phím moät chuoåi kyù töï, ghi leân file, ñoùng file.
Chöông trình keát thuùc khi nhaäp moät doøng troáng. Môû file ñoù nhö moät file nhaäp, ñoïc
noäi dung cuûa file.
// WRITE.CPP
#include <iostream.h>
#include <fstream.h>
#include <iomanip.h>
int main(int argc, char *argv[]) // argc : soá caùc tham soá ,
// *argv[] : chöùa noäi dung caùc tham soá
{
if(argc!=2) {
cout << "Usage: WRITE <filename> \n";
// argv[0] = '\<path>\WRITE.EXE'
// argv[1] = '<filename>'
return 1;
}
ofstream out(argv[1]); // output file
if(!out) {
cout << "Cannot open output file.\n";
return 1;
}
char str[80];
cout << "Write strings to disk, '$' to stop\n";
do {
cout << ": ";
cin >> str;
out << str << endl;
Chöông 8 Nhaäp / Xuaát C++
naâng cao
239
} while (*str != '$');
out.close();
return 0;
}
Ví duï 2.3
Chöông trình seõ sao cheùp moät text file, trong ñoù caùc daáu khoaûng caùch
seõ ñöôïc thay baèng daáu '|'.
// CONVERT.CPP
// Convert spaces to |s.
#include <iostream.h>
#include <fstream.h>
int main(int argc, char *argv[])
{
if(argc != 3) {
cout << "Usage: CONVERT <input> <output>\n";
return 1;
}
ifstream fin(argv[1]); // open input file to read
ofstream fout(argv[2]); // create output file to write
if(!fout) {
cout << "Cannot open output file.\n";
return 1;
}
if(!fin) {
cout << "Cannot open input file.\n";
return 1;
}
char ch;
fin.unsetf(ios::skipws);
// do not skip spaces
Chöông 8 Nhaäp / Xuaát C++
naâng cao
240
while(!fin.eof()) {
fin >> ch;
if(ch == ' ' )
ch = '|';
if(!fin.eof())
fout << ch
;
}
fin.close();
fout.close();
return 0;
}
Baøi taäp II
1. Vieát chöông trình sao cheùp moät text file sang moät file môùi, ñeám vaø in ra soá kyù töï
ñaõ cheùp. Taïi sao soá löôïng caùc kyù töï naøy khaùc vôùi soá löôïng caùc kyù töï khi in file keát
quaû ra maøn hình.
2. Vieát chöông trình ñeå ghi baûng döõ lieäu sau ñaây vaøo moät file coù teân laø phone.txt
Nguyeãn Coâng Tröù 08.8980168
Phaïm Nguõ Laõo
04.2325678
Traàn Nguyeân Haõn 04.6781234
3. Vieát chöông trình ñeám soá löôïng töø coù trong moät text file baát kyø.
III/ Nhaäp/Xuaát File nhò phaân khoâng ñònh daïng
Vieäc nhaäp/xuaát file nhò phaân khoâng ñònh daïng linh ñoäng hôn nhaäp/xuaát text file.
Chöông 8 Nhaäp / Xuaát C++
naâng cao
241
1/ Caùc haøm nhaäp/xuaát caáp thaáp
•
Ñoïc ghi töøng kyù töï
Daïng phoå bieán cuûa chuùng :
istream &get
(char &ch);
ostream &put
(char ch);
Haøm get() ñoïc moät kyù töï töø stream töông öùng vaø gaùn kyù töï ñoù vaøo noäi dung cuûa ch.
Haøm traû veà moät tham chieáu ñeán stream, noù seõ laø NULL neáu ñeán cuoái file.
Haøm put() ghi (xuaát) noäi dung cuûa ch ra moät stream vaø traû veà moät stream.
•
Ñoïc ghi caùc khoái döõ lieäu nhò phaân
istream &read
(unsigned char *buf, int num);
ostream &write
(const unsigned char *buf, int num);
Haøm read() ñoïc moät soá löôïng num caùc byte töø stream töông öùng vaø ghi leân moät vuøng
ñeäm ñöôïc troû bôûi buf.
Haøm write() ghi moät soá löôïng num caùc byte ôû vuøng ñeäm ñöôïc troû bôûi buf ñeán stream
töông öùng.
Neáu file ñöôïc ñoïc heát tröôùc khi ñuû num kyù töï, haøm read() hoaøn taát bình thöôøng vaø
vuøng ñeäm chöùa heát soá kyù töï cuûa laàn ñoïc cuoái. Ñeå bieát laàn cuoái naøy coù bao nhieâu kyù
töï ñöôïc ñöa ra vuøng ñeäm, duøng haøm gcount() coù daïng
int gcount();
Haøm seõ traû veà giaù trò laø toång soá kyù töï ñoïc ñöôïc ôû laàn ñoïc cuoái ngay tröôùc khi heát file.
Löu yù
: vieäc thieát laäp cheá ñoä ios::binary chæ nhaèm muïc ñích ngaên ngöøa vieäc chuyeån
ñoåi kyù töï. Khi söû duïng caùc haøm nhaäp/xuaát file nhò phaân khoâng ñònh daïng, khoâng caàn
môû file ôû cheá ñoä ios::binary.
Ví duï 3.1
Chöông trình xuaát noäi dung cuûa moät file baát kyø ra maøn hình
// PR.CPP
Chöông 8 Nhaäp / Xuaát C++
naâng cao
242
#include <iostream.h>
#include <fstream.h>
int main(int argc, char *argv[])
{
char ch;
if(argc!=2) {
cout << "Usage: PR <filename>\n";
return 1;
}
ifstream in(argv[1], ios::in | ios::binary);
if(!in) {
cout << "Cannot open file.\n";
return 1;
}
while(!in.eof()) {
in.get(ch);
cout << ch;
}
in.close();
return 0;
}
Ví duï 3.2
Chöông trình ghi caùc kyù töï leân moät file cho ñeán khi ngöôøi duøng nhaäp
vaøo kyù töï '$' .
// WRITE.CPP
#include <iostream.h>
#include <fstream.h>
int main(int argc, char *argv[])
{
char ch;
Chöông 8 Nhaäp / Xuaát C++
naâng cao
243
if(argc!=2) {
cout << "Usage: WRITE <filename>\n";
return 1;
}
ofstream out
(argv[1], ios::out | ios::binary);
if(!out) {
cout << "Cannot open file.\n";
return 1;
}
cout << "Enter a $ to stop\n";
do {
cout << ": ";
cin.get(ch);
out.put(ch);
} while (ch != '$');
out.close();
return 0;
}
Löu yù
: chöông trình duøng haøm get() ñeå ñoïc kyù töï töø stream cin vaøo. Neáu duøng toaùn
töû << caùc kyù töï khoaûng caùch seõ bò boû qua, trong khi söû duïng haøm get() caùc kyù töï
khoaûng caùch vaãn ñöôïc nhaän vaøo
.
Ví duï 3.3
Chöông trình duøng haøm write() ñeå ghi moät soá thöïc kieåu double vaø moät
chuoãi kyù töï leân moät file coù teân laø test.txt.
#include <iostream.h>
#include <fstream.h>
#include <string.h>
int main()
{
ofstream out("test.txt", ios::out | ios::binary);
Chöông 8 Nhaäp / Xuaát C++
naâng cao
244
if(!out) {
cout << "Cannot open output file.\n";
return 1;
}
double num = 100.45;
char str[] = "This is a test";
out.write((char *) &num, sizeof(double));
out.write(str, strlen(str));
out.close();
return 0;
}
Löu yù
: vieäc khai baùo linh hoaït (char *) khi goïi haøm write() laø caàn thieát khi vuøng
ñeäm khoâng ñöôïc ñònh nghiaõ laø moät daõy kyù töï. Do C++ kieåm tra kieåu raát kyõ, neân moät
con troû chæ ñeán kieåu döõ lieäu naøy khoâng theå ñöôïc töï ñoäng ñoåi thaønh moät con troû cuûa
kieåu khaùc.
Ví duï 3.4
Chöông trình duøng haøm read() ñeå ñoïc noäi dung text file test.txt töø ví duï
3 ôû treân.
#include <iostream.h>
#include <fstream.h>
int main()
{
ifstream in("test.txt", ios::in | ios::binary);
if(!in) {
cout << "Cannot open input file.\n";
return 1;
}
Chöông 8 Nhaäp / Xuaát C++
naâng cao
245
double num;
char str[80];
in.read((char *) &num, sizeof(double));
in.read(str, 14);
str[14] = '\0';
// null terminate str
cout << num << ' ' << str;
in.close();
return 0;
}
Ví duï 3.5
Chöông trình ghi moät maûng caùc giaù trò kieåu double moät file vaø sau ñoù
ñoïc laïi noäi dung file. Chöông trình coøn thoâng baùo soá löôïng caùc kyù töï ñaõ
ñoïc.
// Demonstrate gcount().
#include <iostream.h>
#include <fstream.h>
int main()
{
ofstream out("test.txt", ios::out | ios::binary);
if(!out) {
cout << "Cannot open output file.\n";
return 1;
}
double nums[4] = {1.1, 2.2, 3.3, 4.4 };
out.write((char *) nums, sizeof(nums));
out.close();
ifstream in("test.txt", ios::in | ios::binary);
if(!in) {
cout << "Cannot open input file.\n";
Chöông 8 Nhaäp / Xuaát C++
naâng cao
246
return 1;
}
in.read((char *) &nums, sizeof(nums));
int i;
for(i=0; i<4; i++)
cout << nums[i] << ' ';
cout << '\n';
cout << in.gcount() << " characters read\n";
in.close();
return 0;
}
Baøi taäp III
1. Vieát laïi chöông trình trong caùc baøi taäp 1 vaø 3 phaàn II chöông 8, thay baèng caùc haøm
get(), put(), read() hoaëc write() sao cho phuø hôïp nhaát.
2. Cho lôùp sau ñaây, vieát chöông trình ghi noäi dung cuûa lôùp leân moät file, söû duïng boä
cheøn.
class account {
int custnum;
char name[80];
double balance;
public:
account(int c, char *n, double b)
{
custnum = c;
strcpy(name, n);
balance = b;
Chöông 8 Nhaäp / Xuaát C++
naâng cao
247
}
// create inserter here
...
};
IV/ Caùc haøm Nhaäp/Xuaát nhò phaân
Hai daïng quaù taûi haøm get() thöôøng duøng :
•
istream &get
(char *buf, int num, char delim = '\n') ;
Haøm get() ñoïc caùc kyù töï vaøo moät daõy ñöôïc chæ bôûi buf, vôùi soá löôïng laø num kyù töï
hoaëïc khi ñoïc vaøo moät kyù töï phaân caùch delim.
Neáu trong ñoái soá cuûa haøm khoâng coù ñoái soá delim, giaù trò maëc ñònh cuûa kyù töï phaân
caùch laø kyù töï sang doøng môùi '\n'. Neáu kyù töï phaân caùch xuaát hieän trong stream nhaäp,
kyù töï seõ khoâng bò laáy ra, thay vaøo ñoù, kyù töï naøy seõ ôû trong stream cho ñeán khi gaëp
thao taùc nhaäp khaùc.
•
int get
() ;
Haøm get() traû veà kyù töï keá tieáp trong stream. Neáu gaëp tình traïng heát file, haøm traû veà
giaù trò EOF (gioáng nhö haøm getc() trong ngoân ngöõ C).
•
istream &getline
(char *buf, int num, char delim = '\n') ;
Haøm getline() cuõng thöïc hieän nhaäp döõ lieäu, ñoïc vaø boû caùc kyù töï phaân caùch ra khoûi
stream
(nhaäp ñöôïc moät chuoãi). Caùc ñoái soá töông töï nhö haøm get() ôû treân.
•
int peek
() ;
Haøm peek() coù theå laáy kyù töï tieáp theo trong stream nhaäp maø khoâng caàn phaûi ñöa noù
ra khoûi stream. Haøm traû veà giaù trò laø kyù töï tieáp theo cuûa stream, neáu heát file, haøm traû
veà giaù trò EOF.
•
istream &putback
(char ch) ;
Haøm putback() traû laïi giaù trò vöøa ñoïc vaøo stream. Ñoái soá ch laø kyù töï vöøa ñöôïc ñoïc
vaøo töø stream.
Chöông 8 Nhaäp / Xuaát C++
naâng cao
248
•
ostream &flush
() ;
Moãi khi thao taùc xuaát ñöôïc thöïc hieän, döõ lieäu khoâng ñöôïc ñöa ra ngay thieát bò vaät lyù
lieân keát vôùi stream, maø thoâng tin ñoù ñöôïc ñöa vaøo vuøng ñeäm. Khi vuøng ñeäm bò ñaày,
döõ lieäu cuûa vuøng ñeäm môùi ñöôïc xuaát ra ñiaõ. Tuy nhieân, neáu muoán thoâng tin xuaát ra
ñiaõ tröôùc khi ñaày vuøng ñeäm
, coù theå duøng haøm flush().
Neân duøng haøm naøy khi maùy tính hoaït ñoäng vôùi nguoàn ñieän hoaït ñoäng khoâng oån ñònh.
Ví duï 4.1
Duøng haøm getline() nhaäp vaøo moät chuoãi baát kyø.
// Use getline() to read a string that contains spaces.
#include <iostream.h>
#include <fstream.h>
int main()
{
char str[80];
cout << "Enter your name: ";
cin.getline(str, 79);
// töông töï nhö haøm gets(str) ;
cout << str << '\n';
return 0;
}
Ví duï 4.2
Duøng haøm peek() vaø putback() trôï giuùp xöû lyù deã daøng khi khoâng bieát
öôïc kieåu cuûa thoâng tin nhaäp vaøo
.
// Demonstrate peek().
#include <iostream.h>
#include <fstream.h>
#include <ctype.h>
int main()
{
Chöông 8 Nhaäp / Xuaát C++
naâng cao
249
char ch;
ofstream out("test.txt", ios::out | ios::binary);
if(!out) {
cout << "Cannot open output file.\n";
return 1;
}
char str[80], *p;
out << 123 << "this is a test" << 23;
out << "Hello there!" << 99 << "sdf" << endl;
out.close();
ifstream in("test.txt", ios::in | ios::binary);
if(!in) {
cout << "Cannot open input file.\n";
return 1;
}
do {
p = str;
ch = in.peek();
// see what type of char is next
if(isdigit(ch)) {
while(isdigit(*p = in.get() ) ) p++; // read integer
in.putback(*p);
// return char to stream
*p = '\0';
// null terminate the string
cout << "Integer: " << atoi(str);
}
else if(isalpha(ch)) {
// read a string
while(isalpha(*p = in.get() ) )
p++;
in.putback(*p);
// return char to stream
*p = '\0';
// null terminate the string
cout << "String: " << str;
}
else in.get();
// ignore
Chöông 8 Nhaäp / Xuaát C++
naâng cao
250
cout << '\n';
} while(!in.eof());
in.close();
return 0;
}
Baøi taäp IV
1. Vieát laïi chöông trình ví duï 4.1 söû duïng haøm get() thay cho haøm getline(). Hoaït
ñoäng cuûa chöông trình naøy nhö theá naøo ?
2. Vieát chöông trình ñoïc töøng doøng cuûa moät text file vaø in doøng vöøa nhaäp ra maøn
hình. Söû duïng haøm getline().
3. Vieát chöông trình minh hoaï hoaït ñoäng cuûa haøm flush() ?
V/ Truy caäp ngaãu nhieân
•
C++ cung caáp vieäc truy caäp ngaãu nhieân moät file qua caùc haøm :
istream &seekg
(streamoff offset, seek_dir origin) ;
ostream &seekp
(streamoff offset, seek_dir origin) ;
streamoff
laø kieåu ñònh nghiaõ trong iostream.h, noù coù theå löu tröõ ñöôïc giaù trò hôïp
leä
lôùn nhaát maø offset coù theå nhaän ñöôïc.
seek_dir
laø moät kieåu haèng lieät keâ vôùi caùc giaù trò nhö sau :
Giaù trò
YÙ nghiaõ
ios::beg
tìm töø vò trí ñaàu file
ios::cur
tìm töø vò trí hieän haønh
ios::end
tìm töø vò trí cuoái file
Haøm seekg() dôøi con troû get cuûa file töông öùng moät ñoaïn baèng offset byte töø moät vò
trí ñöôïc xaùc ñònh baèng origin.
Chöông 8 Nhaäp / Xuaát C++
naâng cao
251
Haøm seekp() dôøi con troû put cuûa file töông öùng ñi moät ñoaïn baèng offset byte tính töø
vò trí ñöôïc xaùc ñònh bôûi origin.
•
Heä thoáng nhaäp/xuaát cuûa C++ söû duïng hai con troû ñeå quaûn lyù moät file.
Thöù nhaát laø con troû get ñeå troû ñeán vò trí seõ ñöôïc ñöa vaøo neáu file ñöôïc thöïc hieän moät
taùc vuï nhaäp
nöõa.
Thöù hai laø con troû put xaùc ñònh vò trí cuûa file maø moät taùc vuï xuaát tieáp theo seõ ñoïc ra
töø ñoù.
Moãi khi thöïc hieän thao taùc nhaäp/xuaát file con troû seõ ñöôïc töï ñoäng taêng leân ñeå chæ vaøo
vò trí keá tieáp. Tuy nhieân, vaãn coù theå duøng haøm seekg() vaø seekp() ñeå truy caäp file
moät caùch ngaãu nhieân.
•
Coù theå xaùc ñònh vi trí hieän haønh cuûa caùc con troû get vaø put baèng caùc haøm :
streampos tellg()
;
streampos tellp()
;
streampos
laø kieåu ñònh nghiaõ trong iostream.h, noù coù theå löu tröõ ñöôïc giaù trò
lôùn nhaát maø haøm coù theå traû veà ñöôïc.
Ví duï 5.1
Duøng haøm seekp() cho pheùp ñoåi moät kyù töï xaùc ñònh cuûa file. Tham soá
cuûa chöông trình goàm teân file, soá thöù töï cuûa byte caàn thay theá vaø kyù töï caàn thay.
// CHANGE.CPP
#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if(argc != 4) {
cout << "Usage: CHANGE <filename> <byte> <char>\n";
return 1;
}
Chöông 8 Nhaäp / Xuaát C++
naâng cao
252
fstream out(argv[1], ios::in | ios::out | ios::binary);
if(!out) {
cout << "Cannot open file.\n";
return 1;
}
out.seekp(atoi(argv[2]), ios::beg);
out.put(*argv[3]);
out.close();
return 0;
}
AÙp duïng :
Cho file test.txt chöùa noäi dung "123 this is a sample"
Keát quûa chöông trình seõ ra sao khi thöïc hieän leänh töø daáu nhaéc MS-DOS :
C:\> CHANGE test.txt 4 T
?
Ví duï 5.2
Duøng haøm seekg() ñeå ñaët con troû get vaøo vò trí giöõa file vaø trình baøy
phaàn noäi dung cuûa file töø vò trí naøy cho ñeán cuoái file.
// LOCATE.CPP
// Demonstrate seekg().
#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>
int main( int argc, char *argv[])
{
char ch;
if(argc != 3) {
cout << "Usage: LOCATE <filename> <loc>\n";
Chöông 8 Nhaäp / Xuaát C++
naâng cao
253
return 1;
}
ifstream in(argv[1], ios::in | ios::binary);
if(!in) {
cout << "Cannot open input file.\n";
return 1;
}
in.seekg(atoi(argv[2]), ios::beg);
while(!in.eof()) {
in.get(ch);
cout << ch;
}
in.close();
return 0;
}
Cho file test.txt chöùa noäi dung
"Yesterday, all my troubles seemed so far away,
Now it looks as thought they're here to stay. Oh, I believe in yesterday ... "
Keát quûa chöông trình seõ ra sao khi thöïc hieän leänh töø daáu nhaéc MS-DOS :
C:\> LOCATE test.txt 10
?
Baøi taäp V
1. Vieát chöông trình xuaát noäi dung cuûa file theo thöù töï töø cuoái trôû veà ñaàu file.
2. Vieát chöông trình thöïc hieän traùo ñoåi vò trí cuûa töøng caëp kyù töï lieân tieáp nhau trong
file. Bieát raèng soá kyù töï trong file naøy laø soá chaün. Ví duï "abcd" thaønh "badc"
VI/ Kieåm tra traïng thaùi Nhaäp/Xuaát
Chöông 8 Nhaäp / Xuaát C++
naâng cao
254
Heä thoáng nhaäp/xuaát C++ löu laïi thoâng tin traïng thaùi keát quûa cuûa moãi taùc vuï
nhaäp/xuaát. Traïng thaùi hieän haønh cuûa heä thoáng nhaäp/xuaát ñöôïc maõ hoaù thaønh moät soá
nguyeân.
Teân
côø YÙ
nghiaõ
goodbit
laø 0 neáu khoâng gaëp loãi
laø 1 neáu gaëp loãi
eofbit
laø 0 neáu gaëp vò trí heát file
laø 1 neáu khoâng gaëp vò trí heát file
failbit
laø 0 neáu gaëp loãi loaïi non-fatal
laø 1 neáu khoâng gaëp loãi loaïi non-fatal
badbit
laø 0 neáu gaëp loãi loaïi fatal
laø 1 neáu khoâng gaëp loãi loaïi fatal
Caùc côø treân laø haèng kieåu lieät keâ ñöôïc ñònh nghiaõ trong ios.
•
Coù hai caùch ñeå nhaän thoâng tin traïng thaùi nhaäp/xuaát C++.
Caùch 1 duøng haøm int rdstate() ;
Haøm seõ traû veà giaù trò
thoâng tin traïng thaùi cuûa caùc côø baùo loãi döôùi daïng moät con
soá nguyeân.
Caùch 2 duøng moät trong caùc haøm sau :
int
bad();
return true neáu côø failbit laø 1
int eof();
return true neáu chöa ñeán cuoái file
int good();
return true neáu taát caû caùc côø baùo loãi ñeàu coù trò laø 0
int
fail();
•
Khi baét gaëp moät loãi nhaäp/xuaát, söû duïng haøm clear() ñeå xoaù loãi tröôùc khi thöïc thi
tieáp chöông trình.
void clear(
int flags = 0) ;
Neáu flags baèng 0, taát caû caùc côø ñeàu bò xoaù veà trò 0. Ngöôïc laïi, coù theå ñaët giaù
trò flags ñeå laäp côø theo yù rieâng.
Chöông 8 Nhaäp / Xuaát C++
naâng cao
255
Ví duï 5.1
Minh hoaï caùch söû duïng haøm rdstate() .Chöông trình xuaát noäi dung moät
text file. Neáu gaëp loãi, chöông trình seõ baùo loãi thoâng qua haøm
checkstatus().
// DISPLAY.CPP
#include <iostream.h>
#include <fstream.h>
void checkstatus(ifstream &in);
int main(int argc, char *argv[])
{
if(argc != 2) {
cout << "Usage: DISPLAY <filename>\n";
return 1;
}
ifstream in(argv[1]);
if(!in) {
cout << "Cannot open input file.\n";
return 1;
}
char c;
while(in.get(c)) {
cout << c;
checkstatus(in);
}
checkstatus(in); // check final status. Error message : EOF encountered
in.close();
return 0;
}
Chöông 8 Nhaäp / Xuaát C++
naâng cao
256
///////////////////////////////////////////////////////////////
void checkstatus(ifstream &in)
{
ios::iostate i;
i = in.rdstate();
if(i & ios::eofbit)
cout << "EOF encountered\n";
else
if(i & ios::failbit)
cout << "Non-Fatal I/O error\n";
else
if(i & ios::badbit)
cout << "Fatal I/O error\n";
}
Keát quaû chöông trình
Thoâng baùo loãi EOF encountered xuaát hieän do khi keát thuùc voøng while, laàn thöïc hieän
cuoái cuøng cuûa haøm checkstatus() töông öùng vôùi traïng thaùi heát file.
Ví duï 5.2
Minh hoaï caùch söû duïng haøm good() ñeå phaùt hieän loãi nhaäp/xuaát .
// PR.CPP
#include <iostream.h>
#include <fstream.h>
int main(int argc, char *argv[])
{
char ch;
if(argc != 2) {
cout << "PR: <filename>\n";
return 1;
}
Chöông 8 Nhaäp / Xuaát C++
naâng cao
257
ifstream in(argv[1]);
if(!in) {
cout << "Cannot open input file.\n";
return 1;
}
while( !in.eof() ) {
in.get(ch);
// check for error
if( ! in.good() && !in.eof()) {
cout << "I/O Error...terminating\n";
return 1; }
cout << ch;
}
in.close();
return 0;
}
Keát quaû chöông trình
Thoâng baùo loãi "I/O Error...terminating" seõ xuaát hieän khi coù loãi nhaäp/xuaát trong luùc
xuaát noäi dung cuûa file coù teân <filename> .
Baøi taäp VI
1. Haõy theâm phaàn kieåm tra vaø baùo loãi nhaäp/xuaát vaøo caùc chöông trình trong caùc baøi
taäp phaàn V, chöông 8.
Chöông 8 Nhaäp / Xuaát C++
naâng cao
258
VII/ Nhaäp/Xuaát theo ñôn ñaët haøng vaø caùc File
Trong C++ do taát caû caùc stream ñeàu ñöôïc xöû lyù nhö nhau, neân moät boä cheøn duøng ñeå
xuaát thoâng tin ra maøn hình coù theå duøng ñeå xuaát thoâng tin ra file maø khoâng caàn phaûi
thay ñoåi gì caû.
Ñaây laø moät trong nhöõng ñaëc tröng quan troïng vaø höõu hieäu cuûa caùch tieáp caän
nhaäp/xuaát C++.
Caùc boä cheøn vaø boä chieát ñaõ ñöôïc quaù taûi, cuõng nhö caùc boä thao taùc nhaäp/xuaát, coù theå
duøng cho baát kyø moät stream naøo
mieãn laø caùc boä naøy ñöôïc vieát moät caùch toång quaùt.
Do ñoù caàn phaûi toång quaùt hoaù caùc boä cheøn vaø boä chieát hay caùc boä thao taùc nhaäp/xuaát
baát cöù khi naøo coù theå laøm ñöôïc.
Ví duï 6.1
Quaù taûi caùc toaùn töû << vaø toaùn töû >> trong lôùp coord,
coù theå duøng chuùng ñeå xuaát thoâng tin ra maøn hình cuõng nhö ra file.
#include <iostream.h>
#include <fstream.h>
class coord {
int x, y;
public:
coord(int i, int j) { x = i; y = j; }
friend ostream &operator <<
(ostream &stream, coord ob);
friend istream &operator >> (istream &stream, coord &ob);
};
ostream &operator<<(ostream &stream, coord ob)
{
stream << ob.x << ' ' << ob.y << '\n';
return stream;
}
istream &operator>>(istream &stream, coord &ob)
{
Chöông 8 Nhaäp / Xuaát C++
naâng cao
259
stream >> ob.x >> ob.y;
return stream;
}
int main()
{
coord o1(1, 2), o2(3, 4);
ofstream out("test.txt");
if(!out) {
cout << "Cannot open output file.\n";
return 1;
}
out << o1 << o2;
// write to test.txt with the contents :
1 2
3 4
out.close();
ifstream in("test.txt");
if(!in) {
cout << "Cannot open input file.\n";
return 1; }
coord o3(0, 0), o4(0, 0);
in >> o3 >> o4;
// write to objects o3, o4 with the contents :
1 2
3 4
cout << o3 << o4;
// output to monitors :
1 2
3 4
in.close();
return 0;
}
Ví duï 6.2
Caùc boä thao taùc nhaäp/xuaát coù theå duøng ñeå xuaát thoâng tin ra maøn hình
cuõng nhö ra file
.
#include <iostream.h>
Chöông 8 Nhaäp / Xuaát C++
naâng cao
260
#include <fstream.h>
#include <iomanip.h>
// Attention:
ostream &atn(ostream &stream)
{
stream << "Attention: ";
return stream;
}
// Please note:
ostream ¬e(ostream &stream)
{
stream << "Please Note: ";
return stream;
}
int main()
{
ofstream out("test.txt");
if(!out) {
cout << "Cannot open output file.\n";
return 1;
}
// write to screen
cout << atn << "High voltage circuit\n";
cout << note << "Turn off all lights\n";
// write to file
out << atn << "High voltage circuit\n";
out << note << "Turn off all lights\n";
out.close();
return 0;
}
Chöông 8 Nhaäp / Xuaát C++
naâng cao
261
Baøi taäp VII
1. Vôùi moãi chöông trình trong chöông 8, haõy thöïc hieän caùc ñieàu chænh caùc boä cheøn,
boä chieát vaø caùc boä thao taùc nhaäp/xuaát ñeå chuùng coù theå laøm vieäc ñöôïc vôùi caùc file .
VIII/ Nhaäp/Xuaát theo maûng
Ngoaøi nhaäp/xuaát thieát bò chuaån (I/O console) vaø nhaäp/xuaát file, C++ coøn hoå trôï moät
boä ñaày ñuû caùc haøm duøng daõy kyù töï nhö moät thieát bò nhaäp hoaëc thieát bò xuaát
.
Nhaäp/xuaát theo maûng cuûa C++ meàm deûo vaø höõu hieäu hôn C (caùc haøm sscanf() vaø
sprintf()) vì noù cho pheùp söû duïng caùc kieåu do ngöôøi duøng ñònh nghóa.
Trong moät soá taøi lieäu khaùc veà C++, nhaäp/xuaát theo maûng coøn ñöôïc goïi laø nhaäp/xuaát
treân RAM
.
Phaàn naøy chæ khaûo saùt nhöõng ñaëc tröng quan troïng nhaát cuûa nhaäp/xuaát theo maûng.
•
Nhaäp/xuaát theo maûng vaãn hoaït ñoäng thoâng qua caùc stream. Caàn naïp file
strstream.h
vaøo chöông trình, noù ñònh nghóa 3 lôùp istrstream, ostrstream vaø
strstream.
Chuùng taïo ra stream nhaäp, stream xuaát vaø stream nhaäp/xuaát theo
maûng.
Caùc lôùp treân ñeàu coù chung moät lôùp cô sôû laø ios, neân taát caû caùc haøm vaø boä thao taùc
cuûa istream, ostream vaø iostream ñeàu coù maët trong istrstream, ostrstream vaø
strstream.
Moät soá haøm boå sung sau ñaây seõ lieân keát stream vôùi moät vuøng trong boä nhôù thoâng qua
buf
.
•
Daïng toång quaùt cuûa haøm taïo cuûa ostrstream, ñeå söû duïng moät maûng xuaát
ostrstream
ostr
(char *buf, int size, int mode = ios::out) ;
vôùi ostr laø stream töông öùng vôùi maûng buf. Kích thöôùc cuûa maûng xaùc ñònh bôûi size.
Cheá ñoä mode ñöôïc maëc ñònh laø xuaát, nhöng coù theå thay ñoåi baát kyø mode xuaát naøo
cuûa ios.
Chöông 8 Nhaäp / Xuaát C++
naâng cao
262
Khi moät maûng ñöôïc môû ñeå cho keát xuaát, caùc kyù töï seõ ñöôïc ñöa vaøo maûng cho ñeán khi
maûng bò ñaày, maûng khoâng ñöôïc pheùp bò traøn. Moïi caùch ñeå ghi leân maûng ñaày seõ gaây
loãi nhaäp/xuaát.
•
Haøm pcount() traû veà soá löôïng kyù töï ñaõ ñöôïc ghi vaøo trong maûng, keå caû kyù töï
NULL ñeå keát thuùc.
int pcount() ;
Khi goïi, caàn gaén teân haøm naøy vôùi moät stream cuï theå.
•
Daïng toång quaùt cuûa haøm taïo cuûa istrstream, duøng ñeå môû moät maûng nhaäp
istrstream
istr
(const char *buf) ;
vôùi istr laø stream nhaäp, buf laø moät con troû ñeán maûng ñöôïc duøng laøm maûng nhaäp.
Khi ñoïc moät maûng, haøm eof() seõ traû veà trò true khi gaëp heát maûng.
•
Ñeå taïo ra moät maûng nhaäp/xuaát, duøng haøm taïo cuûa strstream coù daïng
strstream
iostr
(char *buf, int size, int mode = ios::out) ;
vôùi iostr laø stream nhaäp/xuaát vaø noù söû duïng moät maûng ñöôïc troû bôûi buf. Kích thöôùc
cuûa maûng xaùc ñònh bôûi size. Ñoái vôùi caùc thao taùc nhaäp/xuaát, cheá ñoä mode phaûi laø
ios::in
| ios::out.
•
Ghi nhôù
, taát caû caùc haøm nhaäp/xuaát trong hai chöông 7 vaø 8 vaãn aùp duïng cho
nhaäp/xuaát theo maûng, keå caû caùc haøm nhaäp/xuaát nhò phaân vaø ngaãu nhieân .
Ví duï
8.1
chöông trình seõ môû moät maûng xuaát vaø ghi leân maûng
// A short example using array-based output.
#include <iostream.h>
#include <strstream.h>
int main()
{
Chöông 8 Nhaäp / Xuaát C++
naâng cao
263
char buf[255];
// output buffer
ostrstream ostr(buf, sizeof(buf));
// open output array
// output to monitor
ostr << "Array-based I/O uses streams just like ";
ostr << "'normal' I/O\n" << 100;
ostr << ' ' << 123.23 << '\n';
// you can use manipulators, too
ostr << hex << 100 << ' ';
// or format flags
ostr.setf(ios::scientific);
ostr << dec << 123.23;
ostr << endl << ends;
// ensure that buffer is null-terminated
// show resultant string
cout << buf;
return 0;
}
Keát quaû chöông trình
Array-based I/O uses streams just like 'normal' I/O
100 123.23
64 01.2323e+02
@ Coù theå thaáy caùc haøm nhaäp/xuaát quaù taûi, caùc boä thao taùc nhaäp/xuaát, caùc haøm thaønh
phaàn vaø caùc côø ñònh daïng ñeàu coù theå duøng ñöôïc trong nhaäp/xuaát theo maûng.
Chöông trình ñaõ xoaù maûng baèng boä thao taùc ends.
Ví duï
8.2
chöông trình minh hoaï nhaäp theo maûng
// An example using array-based input.
#include <iostream.h>
#include <strstream.h>
Chöông 8 Nhaäp / Xuaát C++
naâng cao
264
int main()
{
char buf[] = "Hello 100 123.125 a";
istrstream istr(buf);
// open input array
int i;
char str[80];
float f;
char c;
istr >> str >> i >> f >> c;
// from keyboard
cout << str << ' ' << i << ' ' << f;
cout << ' ' << c << '\n';
return 0;
}
•
Khi moät maûng nhaäp ñöôïc lieân keát vôùi moät stream, noù raát gioáng nhö moät file.
Ví duï
8.3
chöông trình söû duïng nhaäp/xuaát nhò phaân vaø haøm eof() ñeå
ñoïc noäi dung cuûa maûng buf
// Demonstrate get() and eof() with array-based I/O.
#include <iostream.h>
#include <strstream.h>
int main()
{
char buf[] = "Hello 100 123.125 a";
istrstream istr(buf);
char c;
while(!istr.eof()) {
istr.get(c);
Chöông 8 Nhaäp / Xuaát C++
naâng cao
265
if(!istr.eof())
cout << c;
}
return 0;
}
Ví duï
8.4
chöông trình minh hoaï maûng nhaäp/xuaát
// Demonstrate an input/output array.
#include <iostream.h>
#include <strstream.h>
int main()
{
char iobuf[255];
strstream iostr(iobuf, sizeof(iobuf), ios::in | ios::out);
// output to iobuf[]
iostr << "This is a test\n";
iostr << 100 << hex << ' ' << 100 << ends;
char str[80];
int i;
// read again from iobuf[]
iostr.getline(str, 79);
// read string up to \n
iostr >> dec >> i;
// read 100
cout << str << ' ' << i << ' ';
// read continue from iobuf[]
iostr >> hex >> i;
cout << hex << i;
return 0;
}
Chöông 8 Nhaäp / Xuaát C++
naâng cao
266
Baøi taäp VIII
1. Haõy hieäu chænh laïi chöông trình trong ví duï 8.1 chöông 8, sao cho noù in ra soá
löôïng kyù töï ñöôïc ghi vaøo buf tröôùc khi chöông trình keát thuùc.
2. Vieát chöông trình cho moät öùng duïng nhaäp/xuaát theo maûng ñeå sao cheùp noäi dung
moät maûng naøy sang moät maûng khaùc.
3. Vieát chöông trình cho moät öùng duïng nhaäp/xuaát theo maûng ñeå chuyeån moät chuoãi
kyù töï thaønh moät gía trò soá kieåu daáu chaám ñoäng töông öùng vôùi gía trò maø chuoãi ñoù
bieåu dieãn .
Baøi taäp chöông 8
1. Vieát chöông trình taïo ra moät boä thao taùc xuaát ra ba kyù töï tab vaø ñaët ñoä roäng cuûa
tröôøng laø 20.
2. Vieát chöông trình taïo ra moät boä thao taùc findalpha nhaäp vaø huûy boû caùc kyù töï
khoâng phaûi laø chöõ caùi. Khi baét gaëp kyù töï chöõ caùi ñaàu tieân, boä thao taùc naøy ñöa traû kyù
töï vöøa nhaäp trôû laïi stream vaø keát thuùc.
3. Vieát chöông trình sao cheùp moät text file. Trong quaù trình xöû lyù, haõy chuyeån kieåu
chöõ cuûa taát caû kyù töï sao cho chöõ in hoa bieán thaønh chöõ thöôøng vaø ngöôïc laïi.
4. Vieát chöông trình ñoïc vaøo moät text file vaø in ra soá löôïng chöõ caùi xuaát hieän trong
file.
5. Chöông trình sau ñaây coù hieäu chænh laïi cuûa lôùp inventory trong chöông 7. Haõy
vieát caùc haøm store() vaø retrieve(). Haõy taïo ra moät file toàn kho chöùa vaøi maãu tin. Sau
ñoù baèng nhaäp/xuaát ngaãu nhieân, haõy cho pheùp ngöôì duøng nhaäp vaøo soá thöù töï cuûa maãu
tin caàn xem , vaø trình baøy noäi dung cuûa maãu tin ñoù.
#include <iostream.h>
#include <fstream.h>
#include <string.h>
Chöông 8 Nhaäp / Xuaát C++
naâng cao
267
#define SIZE 40
class inventory {
char item[SIZE]; // name of item
int onhand;
// number on hand
double cost;
// cost of item
public:
inventory(char *i, int o, double c)
{
strcpy(item, i);
onhand = o;
cost = c;
}
void store(fstream &stream);
void retrieve(fstream &stream);
friend ostream &operator<<(ostream &stream, inventory ob);
friend istream &operator>>(istream &stream, inventory &ob);
};
ostream &operator<<(ostream &stream, inventory ob)
{
stream << ob.item << ": " << ob.onhand;
stream << " on hand at $" << ob.cost << '\n';
return stream;
}
istream &operator>>(istream &stream, inventory &ob)
{
cout << "Enter item name: ";
stream >> ob.item;
cout << "Enter number on hand: ";
stream >> ob.onhand;
cout << "Enter cost: ";
stream >> ob.cost;
Chöông 8 Nhaäp / Xuaát C++
naâng cao
268
return stream;
}
// define the functions here
// void store(fstream &stream)
{
...
}
// void retrieve(fstream &stream)
{
...
}
6. Haõy vieát chöông trình taïo ra lôùp stack chöùa caùc kyù töï vaø löu stack naøy vaøo moät
file.
Xuaát noäi dung file naøy ra maøn hình.
Chöông 9
Tính ña hình
•
Con troû vaø Lôùp daãn xuaát
•
Daãn nhaäp caùc haøm aûo
•
Caùc haøm aûo thuaàn tuùy
•
AÙp duïng ña hình
Chöông 9 Tính ña hình
270
I/ Con troû vaø Lôùp daãn xuaát
1/ Khaùi nieäm
Tính ña hình
(polymorphism) ñöôïc hoå trôï baèng hai caùch khaùc nhau trong C++ .
Caùch 1, ña hình ñöôïc hoå trôï khi bieân dòch chöông trình (compiler) thoâng qua vieäc quaù
taûi caùc haøm vaø toaùn töû
.
Caùch 2, ña hình ñöôïc hoå trôï ôû thôøi ñieåm thöïc thi chöông trình (run-time) thoâng qua
caùc haøm aûo
. Caùch naøy giuùp laäp trình vieân linh ñoäng hôn.
•
Cô sôû cuûa haøm aûo vaø ña hình khi thöïc thi chöông trình laø caùc con troû cuûa lôùp
daãn xuaát.
Chöông 3 coù khaûo saùt veà con troû, moät ñaëc tính môùi cuûa con troû seõ ñöôïc khaûo saùt
trong chöông naøy. Neáu p laø moät con troû tôùi lôùp cô sôû, thì coù theå söû duïng p ñeå troû tôùi
baát kyø lôùp naøo ñöôïc suy ra töø lôùp cô sôû
.
Chaúng haïn, coù hai lôùp cô sôû base vaø lôùp daãn xuaát derived keá thöøa base, caùc phaùt bieåu
sau ñeàu ñuùng
base *p;
// base class pointer
base base_ob;
// object of type base
derived derived_ob;
// object of type derived
// p can, of course, point to base objects
p = &base_ob;
// p points to base object
// p can also point to derived objects without error
p = &derived_ob; // p points to derived object
Moät con troû cuûa lôùp cô sôû coù theå troû tôùi baát kyø lôùp daãn xuaát naøo cuûa lôùp cô sôû maø
khoâng gaây ra baùo loãi khaùc kieåu
. Song chæ coù theå truy caäp ñöôïc caùc thaønh phaàn maø lôùp
daãn xuaát ñöôïc keá thöøa töø lôùp cô sôû
. Bôûi vì con troû cuûa lôùp cô sôû chæ bieát lôùp cô sôû maø
thoâi, noù khoâng bieát gì nhöõng thaønh phaàn ñöôïc theâm vaøo bôûi lôùp daãn xuaát.
Chöông 9 Tính ña hình
271
•
Moät con troû cuûa lôùp daãn xuaát khoâng theå duøng ñeå truy caäp moät ñoái töôïng cuûa lôùp
cô sôû
. (Vieäc söû duïng linh hoaït kieåu coù theå duøng ñeå khaéc phuïc haïn cheá noùi treân,
nhöng noù khoâng ñöôïc khuyeán khích söû duïng)
Caùc pheùp toaùn soá hoïc treân con troû lieân quan ñeán kieåu döõ lieäu maø con troû ñoù ñöôïc
khai baùo ñeå troû ñeán. Do ñoù, neáu con troû ñeán moät ñoái töôïng lôùp daãn xuaát, roài taêng noäi
dung con troû leân 1
. Ñieàu naøy khoâng laøm cho con troû chæ ñeán ñoái töôïng môùi cuûa lôùp
daãn xuaát, maø noù seõ chæ ñeán ñoái töôïng môùi cuûa lôùp cô sôû.
Ví duï 1.1
Duøng con troû cuûa lôùp cô sôû ñeå truy caäp ñeán lôùp daãn xuaát.
// Demonstrate pointer to derived class.
#include <iostream.h>
class base {
int x;
public:
void setx(int i) { x = i; }
int getx() { return x; }
};
class derived : public base {
int y;
public:
void sety(int i) { y = i; }
int gety() { return y; }
};
int main()
{
base *p;
// pointer to base type
base b_ob;
// object of base
derived d_ob;
// object of derived
// use p to access base object
p = &b_ob;
Chöông 9 Tính ña hình
272
p->setx(10);
// access base object
cout << "Base object x: " << p->getx() << '\n';
// use p to access derived object
p = &d_ob;
// point to derived object
p->setx(99);
// access derived object
// can't use p to set y, so do it directly
d_ob.sety(88);
cout << "Derived object x: " << p->getx() << '\n';
cout << "Derived object y: " << d_ob.gety() << '\n';
return 0;
}
II/ Daãn nhaäp haøm aûo (virtual function)
1/ Khaùi nieäm
Haøm aûo
laø haøm thaønh phaàn cuûa moät lôùp, noù ñöôïc khai baùo ôû lôùp cô sôû vaø ñöôïc ñònh
nghiaõ laïi trong lôùp daãn xuaát.
Khai baùo haøm aûo baét ñaàu baèng töø khoaù virtual . Moät lôùp coù chöùa haøm aûo ñöôïc keá
thöøa, lôùp daãn xuaát seõ taùi ñònh nghiaõ haøm aûo ñoù cho chính mình.
•
Caùc haøm aûo trieån khai yù töôûng chuû ñaïo cuûa ña hình laø "moät giao dieän cho nhieàu
phöông thöùc
". Haøm aûo beân trong moät lôùp cô sôû ñònh nghiaõ hình thöùc giao tieáp ñoái
vôùi haøm ñoù.
Vieäc taùi ñònh cuûa haøm aûo ôû lôùp daãn xuaát laø thi haønh caùc taùc vuï cuûa haøm lieân quan ñeán
chính lôùp daãn xuaát ñoù
. Noùi caùch khaùc, taùi ñònh caùc haøm aûo chính laø taïo ra caùc phöông
thöùc cuï theå. Haøm aûo taùi ñònh ôû lôùp daãn xuaát khoâng caàn söû duïng töø khoaù virtual.
•
Nguyeân lyù laøm vieäc cuûa ña hình trong khi thöïc thi chöông trình
:
Chöông 9 Tính ña hình
273
Haøm aûo ñöôïc goïi thöïc thi gioáng nhö caùc haøm thaønh phaàn bình thöôøng cuûa lôùp. Tuy
nhieân, khi goïi haøm aûo baèng con troû, vieäc hoå trôï tính ña hình trong khi thöïc thi chöông
trình seõ xaûy ra.
Khi moät con troû troû ñeán moät lôùp daãn xuaát coù chöùa haøm aûo vaø haøm aûo naøy ñöôïc goïi
baèng con troû thì trình bieân dòch seõ xaùc ñònh phieân baûn naøo cuûa haøm ñoù seõ ñöôïc thöïc
thi. Do ñoù neáu coù hai hay nhieàu lôùp daãn xuaát cuûa moät lôùp cô sôû naøo ñoù, vaø chuùng ñeàu
coù chöùa haøm aûo, thì con troû cuûa lôùp cô sôû coù theå troû ñeán caùc ñoái töôïng khaùc nhau cuûa
lôùp daãn xuaát noùi treân, töùc laø coù theå goïi ñeán nhieàu phieân baûn khaùc nhau cuûa caùc haøm
aûo.
•
Moät lôùp coù chöùa haøm aûo ñöôïc goïi laø lôùp ña hình.
Ví duï 2.1
// A simple example using a virtual function.
#include <iostream.h>
class base {
public:
int i;
base(int x) { i = x; }
virtual void func()
{
cout << "Using base version of func(): ";
cout << i << '\n';
}
};
class derived1 : public base {
public:
derived1(int x) : base(x) {}
void func()
{
cout << "Using derived1's version of func(): ";
cout << i * i << '\n';
}
Chöông 9 Tính ña hình
274
};
class derived2 : public base {
public:
derived2(int x) : base(x) {}
void func()
{
cout << "Using derived2's version of func(): ";
cout << i + i << '\n';
}
};
int main()
{
base *p;
base ob(10);
derived1 d_ob1(10);
derived2 d_ob2(10);
p = &ob;
p->func(); // use base's func()
p = &d_ob1;
p->func(); // use derived1's func()
p = &d_ob2;
p->func(); // use derived2's func()
return 0;
}
@ Kieåu cuûa ñoái töôïng ñöôïc troû ñeán seõ xaùc ñònh phieân baûn naøo cuûa haøm aûo ñöôïc thöïc
thi thoâng qua caùch goïi haøm baèng con troû. Ñieàu naøy chæ xaùc ñònh ñöôïc trong luùc run-
time.
2/ Haøm aûo vaø quaù taûi haøm
Giaûi thích keát quûa chöông trình ?
Using base version of func() : 10
Using derived1's version of func() : 100
Using derived2's version of func() : 20
Chöông 9 Tính ña hình
275
Vieäc taùi ñònh haøm aûo trong moät lôùp daãn xuaát coù töông töï nhö quaù taûi haøm khoâng ?
Caâu traû lôøi laø khoâng.
Quaù taûi haøm
Haøm aûo
Soá löôïng ñoái soá
Cho pheùp khaùc bieät
Phaûi gioáng nhau
Kieåu döõ lieäu cuûa ñoái soá
Cho pheùp khaùc bieät
Phaûi gioáng nhau
Haøm thaønh phaàn cuûa lôùp
Khoâng baét buoäc
Baét buoäc
Haøm taïo
Ñöôïc pheùp
Khoâng ñöôïc
Haøm huûy
Khoâng ñöôïc
Coù theå
Vò trí
Vieäc taùi ñònh haøm aûo trong moät lôùp daãn xuaát coøn ñöôïc goïi laø gaùn thöù töï öu tieân cao
hôn cho haøm ñoù
.
3/ Caùc haøm aûo ñöôïc phaân caáp theo thöù töï keá thöøa
.
Neáu lôùp daãn xuaát khoâng taùi ñònh haøm aûo naøo ñoù thì lôùp naøy seõ söû duïng phieân baûn
haøm cuûa lôùp cô sôû.
Ví duï 2.2
// Virtual functions are hierarchical.
#include <iostream.h>
class base {
public:
int i;
base(int x) { i = x; }
virtual void func()
{
cout << "Using base version of func(): ";
cout << i << '\n';
}
};
class derived1 : public base {
public:
derived1(int x) : base(x) {}
void func()
Chöông 9 Tính ña hình
276
{
cout << "Using derived1's version of func(): ";
cout << i*i << '\n';
}
};
class derived2 : public base {
public:
derived2(int x) : base(x) {}
// derived2 does not override func()
};
int main()
{
base *p;
base ob(10);
derived1 d_ob1(10);
derived2 d_ob2(10);
p = &ob;
p->func(); // use base's func()
p = &d_ob1;
p->func(); // use derived1's func()
p = &d_ob2;
p->func(); // use base's func()
return 0;
}
4/ Caùch ñaùp öùng cuûa haøm aûo ñoái vôùi moät bieán coá ngaãu nhieân ôû thôøi ñieåm run-
time
Ví duï 2.3
// This example illustrates how a virtual function can be used to respond to random
// events occurring at run time.
Keát quûa chöông trình
Using base version of func() : 10
Using derived1's version of func() : 100
Using base version of func() : 10
Chöông 9 Tính ña hình
277
#include <iostream.h>
#include <stdlib.h>
class base {
public:
int i;
base(int x) { i = x; }
virtual void func()
{
cout << "Using base version of func(): ";
cout << i << '\n';
}
};
class derived1 : public base {
public:
derived1(int x) : base(x) {}
void func() {
cout << "Using derived1's version of func(): ";
cout << i*i << '\n';
}
};
class derived2 : public base {
public:
derived2(int x) : base(x) {}
void func()
{
cout << "Using derived2's version of func(): ";
cout << i+i << '\n';
}
};
int main()
Chöông 9 Tính ña hình
278
{
base *p;
derived1 d_ob1(10);
derived2 d_ob2(10);
int i, j;
for(i=0; i<10; i++) {
j = rand();
if( ( j % 2) )
p = &d_ob1;
// if odd use d_ob1
else
p = &d_ob2;
// if even use d_ob2
p->func();
// call appropriate function
}
return 0;
}
Vieäc choïn löïa ñeå thöïc thi phieân baûn haøm aûo naøo (haøm func() cuûa lôùp derived1 hay
haøm func() cuûa lôùp derived2) chæ ñöôïc quyeát ñònh trong luùc run-time. Ñieàu naøy
khoâng theå naøo thöïc hieän ñöôïc ôû thôøi ñieåm bieân dòch chöông trình.
5/ Söû duïng haøm aûo ñeå trieån khai caùch thöùc giao dieän
Ví duï 2.4
// Use virtual function to define interface.
#include <iostream.h>
class area {
double dim1, dim2;
// dimensions of figure
public:
void setarea(double d1, double d2) {
dim1 = d1;
dim2 = d2;
}
Chöông 9 Tính ña hình
279
void getdim(double &d1, double &d2) {
d1 = dim1;
d2 = dim2;
}
virtual double getarea() {
cout << "You must override this function\n";
return 0.0;
}
};
class rectangle : public area {
public:
double getarea() {
double d1, d2;
getdim(d1, d2);
return d1 * d2;
}
};
class triangle : public area {
public:
double getarea() {
double d1, d2;
getdim(d1, d2);
return 0.5 * d1 * d2;
}
};
int main()
{
area *p;
rectangle r;
Chöông 9 Tính ña hình
280
triangle t;
r.setarea(3.3, 4.5);
t.setarea(4.0, 5.0);
p = &r;
cout << "Rectangle has area: " << p->getarea() << '\n';
p = &t;
cout << "Triangle has area: " << p->getarea() << '\n';
return 0;
}
@ Vieäc khai baùo haøm aûo trong lôùp cô sôû area chæ mang tính chaát giöõ choã, khoâng
thöïc hieän moät coâng vieäc cuï theå naøo.
Baøi taäp II
1. Vieát chöông trình taïo ra moät lôùp cô sôû num löu tröõ moät soá nguyeân , vaø haøm aûo cuûa
lôùp laø shownum() coù daïng
class num {
public
:
int i ;
num(int x) { i = x;}
virtual void shownum() { cout << i << '\n';}
};
Haõy taïo hai lôùp daãn xuaát cuûa num coù teân laø outhex vaø outoct. Haõy taùi ñònh caùc haøm
aûo cuûa hai lôùp daãn xuaát treân ñeå chuùng xuaát ra soá nguyeân döôùi daïng soá hec vaø soá oct.
2. Vieát chöông trình taïo ra moät lôùp cô sôû distance löu khoaûng caùch giöõa hai ñieåm vôùi
kieåu döõ lieäu double.
class distance {
public
:
double
d;
Chöông 9 Tính ña hình
281
distance (double f) { d = f;}
virtual void trav_time() {
// define here ...
}
};
Taïo haøm aûo trav_time() cuûa lôùp distance xuaát ra khoaûng thôøi gian caàn thieát ñeå ñi qua
khoaûng caùch naøy. Giaû söû raèng ñôn vò chieàu daøi laø mile vaø vaän toác di chuyeån laø 60
mile/hours.
Haõy taïo lôùp daãn xuaát metric töø lôùp distance, vôùi haøm aûo trav_time() in ra khoaûng
thôøi gian caàn thieát ñeå ñi qua khoaûng caùch treân, tuy nhieân luùc naøy ñôn vò chieàu daøi laø
km vaø vaän toác laø 100km/giôø.
III/ Caùc haøm aûo thuaàn tuùy (pure virtual function)
Moät tröôøng hôïp khaù phoå bieán khi lôùp cô sôû töï noù khoâng phaûi laø moät lôùp hoaøn chænh,
luùc ñoù haøm aûo ñöôïc khai baùo giöõ choã chöù khoâng thöïc hieän coâng vieäc cuï theå. Lôùp cô
sôû naøy chæ cung caáp moät boä khung goàm caùc haøm vaø bieán vaø ñeå daønh cho caùc lôùp daãn
xuaát caùc phaàn ñònh nghóa coøn laïi. Caùc lôùp daãn xuaát phaûi taùi ñònh taát caû caùc haøm aûo
khai baùo trong lôùp cô sôû ñoù. Ñeå ñaûm baûo cho ñieàu naøy, C++ hoå trôï moät coâng cuï goïi
laø haøm aûo thuaàn tuùy.
•
Haøm aûo thuaàn tuùy
khoâng coù moät ñònh nghiaõ naøo lieân quan ñeán lôùp cô sôû. Noù chæ
coù daïng haøm maø thoâi, caùch khai baùo
virtual
<type> func-name(arg-list) = 0 ;
Haøm ñöôïc gaùn trò zero vôùi muïc ñích thoâng baùo cho trình bieân dòch bieát laø khoâng coù
gì trong haøm laø lieân quan ñeán lôùp cô sôû.
Khi haøm aûo laø moät haøm aûo thuaàn tuùy, noù buoäc caùc lôùp daãn xuaát phaûi taùi ñònh noù, neáu
khoâng trình bieân dòch seõ baùo loãi luùc bieân dòch chöông trình
.
•
Neáu moät lôùp coù chöùa haøm aûo thuaàn tuùy, lôùp ñoù ñöôïc goïi laø lôùp tröøu töôïng.
Lôùp tröøu töôïng ñöôïc taïo ra vôùi muïc ñích phaûi ñöôïc keá thöøa, khoâng ñöôïc vaø khoâng
theå taïo ra ñeå toàn taïi ñôn ñoäc.
Chöông 9 Tính ña hình
282
Tuy nhieân, coù theå taïo ra moät con troû ñeán lôùp tröøu töôïng bôûi vì ñieàu naøy caàn thieát ñeå
hoå trôï cho ña hình trong khi run-time
. Ñieàu naøy cuõng cho pheùp tham chieáu ñeán moät
lôùp tröøu töôïng.
•
Khi moät haøm aûo ñöôïc keá thöøa, baûn chaát aûo cuûa noù cuõng ñöôïc keá thöøa
.
Ñieàu naøy coù nghiaõ laø khi moät lôùp daãn xuaát keá thöøa haøm aûo töø lôùp cô sôû, moät lôùp
daãn xuaát thöù hai laïi keá thöøa lôùp daãn xuaát thöù nhaát, haøm aûo coù theå ñöôïc ñònh nghiaõ
laïi ôû lôùp daãn xuaát thöù hai
(cuõng nhö noù ñöôïc ñònh nghiaõ laïi ôû lôùp daãn xuaát thöù
nhaát).
Ví duï 3.1
Taïo moät lôùp tröøu töôïng
#include <iostream.h>
class area {
double dim1, dim2;
// dimensions of figure
public:
void setarea(double d1, double d2) {
dim1 = d1;
dim2 = d2;
}
void getdim(double &d1, double &d2) {
d1 = dim1;
d2 = dim2;
}
virtual double getarea() = 0
; // pure virtual function
};
class rectangle : public area {
public:
double getarea() {
double d1, d2;
getdim(d1, d2);
return d1 * d2;
}
};
Chöông 9 Tính ña hình
283
class triangle : public area {
public:
double getarea() {
double d1, d2;
getdim(d1, d2);
return 0.5 * d1 * d2;
}
};
int main()
{
area *p;
rectangle r;
triangle t;
r.setarea(3.3, 4.5);
t.setarea(4.0, 5.0);
p = &r ;
cout << "Rectangle has area: " << p->getarea() << '\n';
p = &t ;
cout << "Triangle has area: " << p->getarea() << '\n';
return 0;
}
Ví duï 3.2
Minh hoaï vieäc baûo toàn baûn chaát aûo cuûa haøm khi noù ñöôïc keá thöøa.
// Virtual functions retain their virtual nature when inherited.
#include <iostream.h>
class base {
public:
virtual void func() {
cout << "Using base version of func()\n";
}
};
Chöông 9 Tính ña hình
284
class derived1 : public base {
public:
void func() {
cout << "Using derived1's version of func()\n";
}
};
// Derived2 inherits derived1.
class derived2 : public derived1 {
public:
void func() {
cout << "Using derived2's version of func()\n";
}
};
int main()
{
base *p;
base ob;
derived1 d_ob1;
derived2 d_ob2;
p = &ob;
p->func(); // use base's func()
p = &d_ob1;
p->func(); // use derived1's func()
p = &d_ob2;
p->func(); // use derived2's func()
return 0;
}
Keát quaû chöông trình ?
Ñieàu gì xaûy ra khi caû hai lôùp daãn xuaát ñeàu
khoâng taùi ñònh haøm aûo func() ?
Chöông 9 Tính ña hình
285
Baøi taäp III
1. Haõy taïo ra moät ñoái töôïng cho lôùp area trong ví duï 3.1 chöông 9, ñieàu gì seõ xaûy ra
?
2. Trong ví duï 3.2 chöông 9, thöû xoaù phaàn taùi ñònh haøm aûo func() cuûa lôùp derived2,
roài cho truy caäp d_ob2. Keát quûa cuûa chöông trình theá naøo ?
3. Taïi sao khoâng theå taïo ra moät ñoái töôïng thuoäc lôùp tröøu töôïng ?
IV/ Aùp duïng ña hình
Taïi sao caàn söû duïng ña hình ?
1/ Ña hình raát quan troïng vì noù ñôn giaûn hoaù caùc heä thoáng phöùc taïp
.
•
Ña hình laø moät quaù trình aùp duïng moät giao dieän cho hai hay nhieàu tröôøng hôïp
töông töï nhau (nhöng khaùc bieät veà maët kyõ thuaät), noù trieån khai tö töôûng "moät
giao dieän cho nhieàu phöông thöùc
" .
Moät giao dieän hay vaø ñôn giaûn ñöôïc duøng ñeå truy caäp ñeán moät soá caùc hoaït ñoäng coù
lieân heä vôùi nhau nhöng khaùc nhau, vaø laøm maát ñi söï phöùc taïp giaû taïo cuûa heä thoáng
caùc hoaït ñoäng naøy.
•
Ña hình laøm cho moái quan heä luaän lyù giöõa caùc hoaït ñoäng töông töï nhau ñöôïc trôû
neân roõ raøng hôn, ño ñoù noù giuùp cho laäp trình vieân deã daøng hôn trong vieäc ñoïc
hieåu vaø baûo trì chöông trình.
Moät khi caùc hoaït ñoäng coù lieân quan vôùi nhau ñöôïc truy caäp baèng duy nhaát moät giao
dieän, giuùp seõ nhôù hôn. Giao dieän ñoà hoaï treân heä ñieàu haønh Windows hoaëc Macintosh
laø moät ñieån hình.
2/ Khaùi nieäm veà lieân keát
Lieân keát
(binding) lieân quan ñeán OOP vaø ngoân ngöõ C++. Coù hai khaùi nieäm :
Chöông 9 Tính ña hình
286
•
Lieân keát sôùm
(early binding) gaén lieàn vôùi nhöõng bieán coá coù theå xaùc ñònh ôû thôøi
ñieåm bieân dòch chöông trình
. Ñaëc bieät, lieân keát sôùm lieân quan ñeán caùc goïi haøm
ñöôïc xöû lyù trong luùc bieân dòch bao goàm :
- Caùc haøm thoâng thöôøng
- Caùc haøm ñöôïc quaù taûi
- Caùc haøm thaønh phaàn khoâng phaûi laø haøm aûo
- Caùc haøm friend
Taát caû caùc thoâng tin veà ñòa chæ caàn thieát cho vieäc goïi caùc haøm treân ñöôïc xaùc ñònh roõ
raøng trong luùc bieân dòch.
Öu ñieåm : goïi caùc haøm lieân keát sôùm laø kieåu goïi haøm nhanh nhaát.
Nhöôïc ñieåm : thieáu tính linh hoaït.
•
Lieân keát muoän
(late binding) gaén lieàn vôùi nhöõng bieán coá xuaát hieän trong luùc
thöïc thi chöông trình (run-time)
.
Khi goïi caùc haøm lieân keát muoän, ñiaï chæ cuûa haøm ñöôïc goïi chæ bieát ñöôïc khi run-time.
Trong C++, haøm aûo laø moät ñoái töôïng lieân keát muoän. Chæ khi run-time, haøm aûo ñöôïc
truy caäp baèng con troû cuûa lôùp cô sôû, chöông trình môùi xaùc ñònh kieåu cuûa ñoái töôïng bò
troû vaø bieát ñöôïc phieân baûn naøo cuûa haøm aûo ñöôïc thöïc thi.
Öu ñieåm : tính linh hoaït cuûa noù ôû thôøi gian run-time, ñieàu naøy giuùp cho chöông trình
goïn gaøng vì khoâng coù nhöõng ñoaïn chöông trình xöû lyù caùc bieán coá ngaãu nhieân trong
khi thöïc thi.
Nhöôïc ñieåm : chaäm hôn so vôùi lieân keát sôùm, do phaûi qua nhieàu giai ñoaïn trung gian
keøm theo vieäc goïi thöïc thi moät haøm lieân keát muoän.
Moãi loaïi lieân keát ñeàu coù nhöõng öu khuyeát ñieåm rieâng cuûa noù, neân phaûi caân nhaéc ñeå
quyeát ñònh tình huoáng thích hôïp ñeå söû duïng hai loaïi lieân keát noùi treân.
Ví duï 4.1
Minh hoïa tö töôûng "moät giao dieän cho nhieàu phöông thöùc" .
Chöông 9 Tính ña hình
287
// Demonstrate virtual functons.
#include <iostream.h>
#include <stdlib.h>
#include <ctype.h>
class list {
public:
list *head; // pointer to start of list
list *tail; // pointer to end of list
list *next; // pointer to next item
int num; // value to be stored
list() { head = tail = next = NULL; }
virtual void store(int i) = 0;
virtual int retrieve() = 0;
};
// Create a queue type list.
class queue : public list {
public:
void store(int i);
int retrieve();
};
void queue::store(int i)
{
list *item;
item = new queue;
if(!item) {
cout << "Allocation error.\n";
exit(1);
}
item->num = i;
// put on end of list
Chöông 9 Tính ña hình
288
if(tail) tail->next = item;
tail = item;
item->next = NULL;
if(!head) head = tail;
}
int queue::retrieve()
{
int i;
list *p;
if(!head) {
cout << "List empty.\n";
return 0;
}
// remove from start of list
i = head->num;
p = head;
head = head->next;
delete p;
return i;
}
// Create a stack type list.
class stack : public list {
public:
void store(int i);
int retrieve();
};
void stack::store(int i)
{
list *item
;
item = new stack;
if(!item) {
Chöông 9 Tính ña hình
289
cout << "Allocation error.\n";
exit(1);
}
item->num = i;
// put on front of list for stack-like operation
if(head) item->next = head;
head = item;
if(!tail) tail = head;
}
int stack::retrieve()
{
int i;
list *p;
if(!head) {
cout << "List empty.\n";
return 0;
}
// remove from start of list
i = head->num;
p = head;
head = head->next;
delete p;
return i;
}
int main()
{
list *p;
// demonstrate queue
queue q_ob;
p = &q_ob;
// point to queue
p->store(1);
Chöông 9 Tính ña hình
290
p->store(2);
p->store(3);
cout << "Queue: ";
cout << p->retrieve();
cout << p->retrieve();
cout << p->retrieve();
cout << '\n';
// demonstrate stack
stack s_ob;
p = &s_ob; // point to stack
p->store(1);
p->store(2);
p->store(3);
cout << "Stack: ";
cout << p->retrieve();
cout << p->retrieve();
cout << p->retrieve();
cout << '\n';
return 0;
}
Ví duï 4.2
Duøng ña hình ñeå xöû lyù caùc bieán coá ngaãu nhieân.
Söû duïng caùc khai baùo vaø ñònh nghiaõ lôùp ôû ví duï 4.1 .
int main()
{
list *p;
stack s_ob;
queue q_ob;
Chöông 9 Tính ña hình
291
char ch;
int i;
for(i=0; i<10; i++) {
cout << "Stack or Queue? (S/Q): ";
cin >> ch;
ch = tolower(ch);
if(ch=='q')
p = &q_ob
;
else
p = &s_ob
;
p->store(i);
}
cout << "Enter T to terminate\n";
for(;;) {
cout << "Remove from Stack or Queue? (S/Q): ";
cin >> ch;
ch = tolower(ch);
if(ch=='t') break;
if(ch=='q')
p = &q_ob
;
else
p = &s_ob
;
cout << p->retrieve() << '\n';
}
cout << '\n';
return 0;
}
•
Trong HÑH Windows vaø OS2, thoâng qua giao dieän ngöôøi duøng giao tieáp vôùi moät
chöông trình baèng caùch gôûi ñeán chöông trình caùc messages. Nhöõng message naøy
ñöôïc phaùt sinh moät caùch ngaãu nhieân
vaø chöông trình cuûa baïn phaûi ñaùp öùng caùc
message naøy moãi khi nhaän ñöôïc noù. Do ñoù, ña hình giuùp thöïc thi chöông trình raát
höõu hieäu cho caùc chöông trình ñöôïc vieát ñeå söû duïng trong caùc HÑH noùi treân.
Ví duï 4.3
Moät chöông trình ñôn giaûn nhaát treân Windows, xuaát ra maøn hình
Chöông 9 Tính ña hình
292
moät khung cöûa soå chöùa noäi dung " Hello, Windows 98 ! "
#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("HelloWin") ;
HWND
hwnd ;
MSG
msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc
= WndProc ;
wndclass.cbClsExtra
= 0 ;
wndclass.cbWndExtra
= 0 ;
wndclass.hInstance
= hInstance ;
wndclass.hIcon
= LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor
= LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground
= (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName
= NULL ;
wndclass.lpszClassName
= szAppName ;
if (!RegisterClass (&wndclass)) {
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, // window class name
TEXT ("The Hello Program"),
// window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT,
// initial x position
CW_USEDEFAULT,
// initial y position
CW_USEDEFAULT,
// initial x size
Chöông 9 Tính ña hình
293
CW_USEDEFAULT,
// initial y size
NULL,
// parent window handle
NULL,
// window menu handle
hInstance,
// program instance handle
NULL) ;
// creation parameters
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0)) {
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM
wParam, LPARAM lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_CREATE :
PlaySound
(TEXT("hellowin.wav"),
NULL,
SND_FILENAME
|
SND_ASYNC) ;
return 0 ;
case WM_PAINT :
hdc = BeginPaint (hwnd, &ps) ;
GetClientRect (hwnd, &rect) ;
DrawText (hdc, TEXT (" Hello, Windows 98 ! "), -1, &rect,
Chöông 9 Tính ña hình
294
DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
Baøi taäp IV
1. Theâm vaøo chöông trình ôû ví duï 4.1 moät kieåu danh saùch lieân keát, laø loaïi danh saùch
coù chöùc naêng xeáp caùc phaàn töû theo thöù töï taêng daàn moãi khi theâm phaàn töû môùi vaøo
danh saùch. Ñaët teân cho lôùp naøy laø sorted thöøa keá lôùp cô sôû list.
Lôùp sorted chöùa hai haøm chung laø
- void store(int i) coù chöùc naêng theâm phaàn töû môùi vaøo danh saùch sao cho chuùng coù
thöù töï taêng daàn.
- vaø int retrieved() coù chöùc naêng hieån thò caùc phaàn töû trong danh saùch.
2. Haõy vieát moät chöông trình coù aùp duïng tính ña hình.
Baøi taäp chöông 9
Chöông 9 Tính ña hình
295
1. Xeùt ñoaïn chöông trình sau ñaây. Tìm loãi vaø giaûi thích taïi sao ?
class base {
public:
virtual int f(int a) = 0;
// ...
};
class derived : public base {
public:
int f(int a, int b) { return a*b; }
// ...
};
2. Trình baøy söï khaùc nhau giöõa haøm aûo vaø quaù taûi haøm.
3. Vieát chöông trình boå sung vaøo ví duï 4.1 chöông 9, baèng caùch quaù taûi hai toaùn töû +
vaø toaùn töû -- vaøo lôùp daãn xuaát stack vaø queue .
Toaùn töû + theâm moät phaàn töû vaøo danh saùch
stack operator + (int i) ;
queue operator + (int i) ;
vaø toaùn töû -- laáy moät phaàn töû ra khoûi danh saùch.
int operator -- (int unused) ;
// cho caû stack vaø queue .
4. Haõy söûa ñoåi moät soá ví duï veà quaù taûi haøm trong caùc chöông tröôùc, sao cho coù theå
chuyeån ñoåi caùc haøm ñöôïc quaù taûi thaønh caùc haøm aûo ?
Chöông 10
Template vaø ñieàu khieån ngoaïi leä
•
Haøm template
•
Lôùp template
•
Ñieàu khieån ngoaïi leä
•
Bieán tónh
•
Töø khoaù extern vaø asm
•
Haøm chuyeån kieåu
•
Nhöõng khaùc bieät giöõa C vaø C++
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
298
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
299
I/ Haøm template
Haøm template (haøm maãu) ñònh nghiaõ moät daõy toång quaùt caùc taùc vuï ñöôïc duøng cho
nhieàu kieåu döõ lieäu khaùc nhau
. Trong ñoù, kieåu döõ lieäu ñöôïc duøng seõ ñöôïc truyeàn ñeán
haøm döôùi daïng moät tham soá
.
Vôùi cô cheá naøy, moät thuû tuïc coù theå ñöôïc duøng cho nhieàu kieåu döõ lieäu khaùc nhau.
Trong moân hoïc Caáu truùc döõ lieäu vaø thuaät toaùn, nhieàu giaûi thuaät gioáng nhau veà maët
luaän lyù, baát keå noù laøm vieäc vôùi kieåu döõ lieäu gì. Ví duï giaûi thuaät QuickSort laø gioáng
nhau, khoâng caàn bieát noù seõ aùp duïng cho daõy soá nguyeân hay daõy soá thöïc. Vaán ñeà laø ôû
choã döõ lieäu ñöôïc xöû lyù khaùc nhau.
Baèng caùch taïo ra haøm template, coù theå ñònh nghiaõ baûn chaát cuûa giaûi thuaät ñoäc laäp vôùi
kieåu döõ lieäu maø noù xöû lyù. Döïa vaøo haøm template, trình bieân dòch seõ töï ñoäng sinh ra
maõ chöông trình ñeå duøng cho moät kieåu döõ lieäu cuï theå naøo ñoù khi thöïc thi chöông
trình. Thöïc chaát laø vieäc taïo ra moät haøm template ñoàng nghiaõ vôùi vieäc taïo ra moät haøm
maø noù coù theå töï quaù taûi leân chính noù
.
Khai baùo haøm template
template < class
Ttype > ret_type func_name(parameter list)
{
// body of function
}
Töø khoaù template duøng ñeå taïo ra moät daïng maãu moâ taû hoaït ñoäng cuûa haøm vaø
nhöôøng cho trình bieân dòch ñieàn vaøo moät caùch chi tieát khi caàn.
Ttype
laø teân hình thöùc cho kieåu döõ lieäu ñöôïc duøng beân trong haøm, noù seõ ñöôïc thay
theá bôûi moät kieåu döõ lieäu cuï theå khi trình bieân dòch sinh ra moät phieân baûn chi tieát cuûa
haøm.
Quaù trình taïo ra phieân baûn chi tieát cuûa haøm ñöôïc goïi laø quaù trình sinh haøm. Vieäc taïo
ra
baûn chi tieát cuûa haøm template ñöôïc goïi laø taïo ra ngay töùc khaéc (instantiating) moät
haøm. Noùi moät caùch khaùc laø moät haøm sinh ra phieân baûn duøng trong choác laùt cuûa haøm
template
.
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
300
Ví duï 1.1
Haøm template trao ñoåi noäi dung cuûa hai bieán
// Function template example.
#include <iostream.h>
// This is a function template.
template
<class X> void swapargs(X &a, X &b)
{
X temp;
temp = a;
a = b;
b = temp;
}
int main()
{
int i=10, j=20;
float x=10.1, y=23.3;
cout << "Original i, j: " << i << ' ' << j << endl;
cout << "Original x, y: " << x << ' ' << y << endl;
swapargs(i, j);
// swap integers
swapargs(x, y); // swap floats
cout << "Swapped i, j: " << i << ' ' << j << endl;
cout << "Swapped x, y: " << x << ' ' << y << endl;
return 0;
}
template
<class X> void swapargs(X &a, X &b)
Doøng naøy thoâng baùo vôùi chöông trình hai vaán ñeà :
- Ñaây laø moät haøm template.
- Ñaây laø ñieåm baét ñaàu cuûa phaàn ñònh nghiaõ moät haøm template.
X coù yù nghiaõ laø kieåu döõ lieäu cuûa caùc bieán caàn trao ñoåi noäi dung.
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
301
Haøm swapargs() ñöôïc goïi hai laàn trong haøm main() : moät laàn ñeå trao ñoåi noäi dung
hai bieán kieåu soá nguyeân, vaø laàn sau cho hai bieán kieåu soá thöïc. Do haøm swapargs() laø
moät haøm template, cho neân trình bieân dòch seõ töï ñoäng phaùt sinh ra hai phieân baûn cuûa
haøm swapargs() töông öùng vôùi kieåu döõ lieäu cuûa ñoái soá thöïc gôûi vaøo.
•
Phaàn khai baùo template cuûa moät haøm maãu khoâng baét buoäc phaûi vieát treân cuøng
moät doøng vôùi teân haøm.
Ví duï 1.2
template
<class X>
void swapargs(X &a, X &b)
{
X temp;
temp = a;
a = b;
b = temp;
}
•
Chuù yù raèng, khoâng theå ñaët baát kyø meänh ñeà naøo giöõa phaàn khai baùo template vaø
phaàn thaân haøm.
Ví duï 1.3
// This will not compile.
template <class X>
int i
;
// this is an error
void swapargs(X &a, X &b)
{
X temp;
temp = a;
a = b;
b = temp;
}
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
302
•
Trong haøm template, coù theå söû duïng nhieàu kieåu döõ lieäu khaùc nhau baèng caùch
ñöa vaøo moät danh saùch caùc kieåu döõ lieäu duøng trong haøm, trong ñoù teân hình thöùc
cuûa caùc kieåu ñöôïc phaân caùch nhau baèng daáu phaåy.
#include <iostream.h>
template
<class type1, class type2>
void myfunc(type1 x, type2 y)
{
cout << x << ' ' << y << endl;
}
int main()
{
myfunc(10, "hi");
myfunc(0.23, 10L);
return 0;
}
@ Khi phaùt sinh haøm, caùc kieåu hình thöùc type1 vaø type2 ñöôïc thay theá hai laàn : laàn
ñaàu baèng hai kieåu int vaø char*, laàn sau laø double vaø long .
•
Haøm template töông töï nhö haøm ñöôïc quaù taûi nhöng noù chòu nhieàu haïn cheá hôn.
Khi quaù taûi moät haøm, caùc phieân baûn coù theå mang nhieàu taùc vuï raát khaùc nhau,
trong khi moät haøm template chæ thöïc hieän ñöôïc moät coâng vieäc duy nhaát ôû taát caû
caùc phieân baûn
.
Ví duï khoâng theå thay theá haøm ñöôïc quaù taûi sau ñaây baèng moät haøm template bôûi vì
caùc haøm quaù taûi sau ñaây khoâng cuøng thöïc thi moät coâng vieäc.
void outdata(int i)
{
cout << i;
}
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
303
void outdata(double d)
{
cout << setprecision(10) << setfill('#');
cout << d;
cout << setprecision(6) << setfill(' ');
}
•
Moät haøm template coù theå töï quaù taûi khi caàn thieát, khi ñoù caàn quaù taûi noù moät caùch
töôøng minh. Neáu quaù taûi moät haøm template thì haøm ñöôïc quaù taûi seõ che haøm
template ñoù
.
// Overriding a template function.
#include <iostream.h>
template <class X> void swapargs(X &a, X &b)
{
X temp;
temp = a;
a = b;
b = temp;
}
// This overrides the generic version of swapargs().
void swapargs(int a, int b)
{
cout << "this is inside swapargs(int,int)\n";
}
int main()
{
int i=10, j=20;
float x=10.1, y=23.3;
cout << "Original i, j: " << i << ' ' << j << endl;
cout << "Original x, y: " << x << ' ' << y << endl;
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
304
swapargs(i, j); // this calls the explicitly overloaded swapargs()
swapargs(x, y); // swap floats
cout << "Swapped i, j: " << i << ' ' << j << endl;
cout << "Swapped x, y: " << x << ' ' << y << endl;
return 0;
}
@ Vieäc quaù taûi leân moät haøm template, cho pheùp laäp trình vieân thay ñoåi giaûi thuaät
cuûa moät phieân baûn cuûa haøm template ñeå phuø hôïp vôùi moät tình huoáng ñaëc bieät
. Tuy
nhieân, neáu muoán söû duïng nhöõng phieân baûn hoaøn toaøn khaùc nhau cuûa moät haøm trong
ñoù coù nhieàu kieåu döõ lieäu, haõy duøng quaù taûi haøm thay vì haøm template.
Baøi taäp I
1. Vieát moät chöông trình, trong ñoù coù haøm template teân laø min(), traû noù veà giaù trò ñoái
soá nhoû hôn trong hai giaù trò ñoái soá cuûa haøm. Laáy ví duï min(3,4) = 3, hoaëc min('c', 'a')
= 'a' .
2. Vieát moät chöông trình, trong ñoù coù haøm template teân laø bubblesort(), thöïc hieän
vieäc saép xeáp caùc döõ lieäu kieåu soá nguyeân, soá thöïc hoaëc kieåu kyù töï . Neáu thaønh coâng,
haøm traû veà giaù trò 1, ngöôïc laïi haøm seõ traû veà trò laø -1. Haøm coù daïng
int bubblesort (X a[], int n);
vôùi n xaùc ñònh soá löôïng caùc phaàn töû cuûa daõy a.
3. Vieát moät chöông trình, trong ñoù coù haøm template teân laø find(), thöïc hieän vieäc tìm
kieám moät ñoái töôïng treân moät daõy. Neáu tìm thaáy, haøm traû veà chæ soá cuûa ñoái töôïng tìm
ñöôïc, ngöôïc laïi haøm seõ traû veà trò laø -1. Haøm coù daïng
int find(int object, int *list, int size);
vôùi size xaùc ñònh soá löôïng caùc phaàn töû cuûa daõy.
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
305
II/ Lôùp template
Lôùp template
ñònh nghiaõ taát caû caùc thuaät toaùn ñöôïc duøng bôûi lôùp ñoù, tuy nhieân kieåu
döõ lieäu thöïc söï maø lôùp naøy xöû lyù seõ ñöôïc ñònh roõ döôùi daïng tham soá luùc taïo ra caùc ñoái
töôïng thuoäc lôùp template ñoù.
•
Khai baùo
template
< class Ttype > class class_name {
// body of class
};
Ttype
laø teân lôùp hình thöùc vaø noù seõ ñöôïc xaùc ñònh khi taïo ra moät lôùp. Khi caàn thieát,
coù theå ñònh nghiaõ lôùp template vôùi nhieàu kieåu döõ lieäu template baèng caùch duøng moät
danh saùch caùc teân kieåu hình thöùc ñöôïc phaân caùch nhau baèng daáu phaåy.
•
Sau khi taïo ra lôùp template, coù theå sinh ra moät lôùp cuï theå töø lôùp template
class_name <
type > object_name;
vôùi type laø teân thöïc cuûa kieåu döõ lieäu maø lôùp ñoù xöû lyù.
Caùc haøm thaønh phaàn cuûa moät lôùp template cuõng laø caùc haøm template moät caùch töï
ñoäng
vaø khoâng caàn phaûi duøng töø khoaù template ñeå khai baùo töôøng minh cho caùc haøm
ñoù.
Ví duï 2.1
Taïo ra lôùp template cho moät danh saùch lieân keát, duøng ñeå löu caùc kyù töï.
// A simple generic linked list.
#include <iostream.h>
template < class data_t
> class list {
data_t data;
list *next;
public:
list(data_t d) ;
void add(list *node) {
node->next = this;
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
306
next = 0;
}
list *getnext() { return next; }
data_t getdata() { return data; }
};
template <
class data_t > list < data_t > :: list(data_t d)
{
data = d;
next = 0;
}
int main()
{
list<char> start('a')
;
list<char> *p, *last ;
int i;
// build a list
last = &start;
for(i=1; i<26; i++) {
p = new list<char> ('a' + i);
p->add(last);
last = p;
}
// follow the list
p = &start;
while(p) {
cout << p->getdata();
p = p->getnext();
}
return 0;
}
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
307
@ Löu yù doøng leänh
list<char> start('a') ;
vôùi kieåu döõ lieäu ñöôïc truyeàn sang cho lôùp xuaát hieän beân trong caëp daáu
ngoaëc
< >.
Keát quaû chöông trình ?
@ Coù theå duøng danh saùch list ñeå löu tröõ caùc phaàn töû kieåu soá nguyeân hay khoâng ?
•
Coù theå söû duïng lôùp template list ôû treân cho moät kieåu döõ lieäu môùi do ngöôøi duøng
ñònh nghiaõ. Ví duï, veà moät caáu truùc löu thoâng tin veà danh baï ñieän thoaïi
struct addr {
char name[40];
char street[40];
char city[30];
char state[3];
char phone[40];
char zip[12];
};
Duøng lôùp template list ñeå sinh ra moät ñoái töôïng môùi obj laø moät danh saùch lieân keát
cuûa caùc phaàn töû thuoäc kieåu addr baèng khai baùo nhö sau
list<addr>
obj(structvar);
vôùi structvar laø bieán coù kieåu döõ lieäu laø addr.
•
Caùc haøm template vaø lôùp template laø moät coâng cuï maïnh laøm gia taêng hieäu quaû
laäp trình, bôûi vì noù cho pheùp ñònh nghiaõ moät giaûi thuaät ôû daïng toång quaùt vaø söû
duïng ñöôïc cho nhieàu loaïi döõ lieäu coù kieåu khaùc nhau
. Ngoaøi ra, coøn tieát kieäm ñöôïc
thôøi gian goõ chöông trình vaøo maùy tính
, do khoâng phaûi goõ laïi nhieàu ñoaïn maõ
chöông trình gioáng nhau veà maët giaûi thuaät nhöng khaùc nhau veà kieåu döõ lieäu maø
noù xöû lyù.
Ví duï 2.2
Taïo ra lôùp template cho stack, duøng ñeå löu caùc kieåu döõ lieäu kyù töï vaø
kieåu double.
// This function demonstrates a generic stack.
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
308
#include <iostream.h>
#define SIZE 10
// Create a generic stack class
template <class StackType
> class stack {
StackType stck[SIZE];
// holds the stack
int tos;
// index of top-of-stack
public:
void init() { tos = 0; }
// initialize stack
void push(StackType ch);
// push object on stack
StackType pop();
// pop object from stack
};
// Push an object.
template
<class StackType> void stack<StackType>::push(StackType ob)
{
if(tos==SIZE) {
cout << "Stack is full.\n";
return;
}
stck[tos] = ob;
tos++;
}
// Pop an object.
template
<class StackType> StackType stack<StackType>::pop()
{
if(tos==0) {
cout << "Stack is empty.\n";
return 0;
// return null on empty stack
}
tos--;
return stck[tos];
}
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
309
int main()
{
// Demonstrate character stacks.
stack<char> s1, s2;
// create two stacks
int i;
// initialize the stacks
s1.init();
s2.init();
s1.push('a');
s2.push('x');
s1.push('b');
s2.push('y');
s1.push('c');
s2.push('z');
for(i=0; i<3; i++) cout << "Pop s1: " << s1.pop() << "\n";
for(i=0; i<3; i++) cout << "Pop s2: " << s2.pop() << "\n";
// demonstrate double stacks
stack<double> ds1, ds2;
// create two stacks
// initialize the stacks
ds1.init();
ds2.init();
ds1.push(1.1);
ds2.push(2.2);
ds1.push(3.3);
ds2.push(4.4);
ds1.push(5.5);
ds2.push(6.6);
for(i=0; i<3; i++) cout << "Pop ds1: " << ds1.pop() << "\n";
for(i=0; i<3; i++) cout << "Pop ds2: " << ds2.pop() << "\n";
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
310
return 0;
}
Keát quaû chöông trình ?
•
Moät lôùp template coù theå chöùa nhieàu kieåu döõ lieäu toång quaùt (
generic data types) .
Khi ñoù caùc teân kieåu döõ lieäu template ñöôïc khai baùo trong phaàn template döôùi
daïng moät danh saùch vaø phaân caùch nhau baèng daáu phaåy.
Ví duï 2.3
Moät lôùp coù hai kieåu döõ lieäu toång quaùt
// This example uses two generic data types in a class definition.
#include <iostream.h>
template <class Type1
, class Type2> class myclass
{
Type1 i;
Type2 j;
public:
myclass(Type1 a, Type2 b) { i = a; j = b; }
void show() { cout << i << ' ' << j << '\n'; }
};
int main()
{
myclass<int, double> ob1(10, 0.23);
// a/
myclass<char, char *> ob2('X', "This is a test");
// b/
ob1.show();
// show int, double
ob2.show();
// show char, char *
return 0;
}
Keát quaû chöông trình ?
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
311
@ Trong caû hai tröôøng hôïp ôû treân (a/, b/) , trình bieân dòch seõ töï ñoäng sinh ra caùc döõ
lieäu vaø haøm töông öùng vôùi meänh ñeà taïo ra lôùp.
Baøi taäp II
1. Vieát chöông trình taïo vaø bieåu dieãn moät lôùp template löu tröõ queue.
2. Vieát chöông trình taïo moät lôùp template vôùi teân input, khi haøm taïo cuûa lôùp naøy
ñöôïc goïi noù seõ thöïc hieän caùc coâng vieäc sau :
- thoâng baùo nhaéc ngöôøi duøng nhaäp döõ lieäu : prompt message
- nhaän döõ lieäu töø baøn phím.
- thoâng baùo loãi neáu döõ lieäu khoâng naèm trong vuøng trò cho pheùp
giöõa min_value vaø max_value.
Ñoái töôïng thuoäc kieåu input ñöôïc khai baùo nhö sau
input ob("prompt message", min_value, max_value) ;
III/ Ñieàu khieån ngoaïi leä (exception handling)
C++ (theo chuaån ANSI C++, 1994) cung caáp saün moät cô cheá xöû lyù loãi goïi laø ñieàu
khieån ngoaïi leä. Qua ñoù coù theå khoáng cheá vaø ñaùp öùng laïi caùc loãi xuaát hieän luùc thöïc thi
chöông trình
.
1/ Ñieàu khieån ngoaïi leä cuûa C++ goàm ba töø khoaù : try, catch, throw .
Moät caùch toång quaùt, caùc meänh ñeà duøng ñeå giaùm saùt caùc ngoaïi leä ñöôïc ñaët beân trong
moät khoái try. Khi moät ngoaïi leä (töùc moät loãi) xuaát hieän beân trong khoái try, noù seõ ñöôïc
neùm ra (baèng töø khoaù throw). Tieáp theo ngoaïi leä naøy seõ bò baét laïi ñeå xöû lyù (baèng töø
khoaù catch).
Baát kyø moät meänh ñeà naøo thöïc hieän vieäc neùm ra ngoaøi moät ngoaïi leä phaûi ñaët ôû beân
trong khoái try (hoaëc beân trong moät haøm ñöôïc goïi ñeán töø moät meänh ñeà beân trong khoái
try). Taát caû caùc ngoaïi leä phaûi bò baét laïi bôûi moät meänh ñeà catch ñaët ngay sau khoái try
maø töø ñoù noù ñöôïc neùm ra
.
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
312
Daïng khai baùo toång quaùt
try
{
// try block
throw exception
;
}
catch
(type1 arg ) {
// catch block
}
catch
(type2 arg ) {
// catch block
}
...
catch
(typeN arg ) {
// catch block
}
exception
laø giaù trò ñöôïc neùm ra.
type1, type2, ..., typeN
kieåu döõ lieäu cuûa caùc ñoái soá
Kieåu döõ lieäu cuûa ngoaïi leä chính laø cô sôû ñeå quyeát ñònh xem ngoaïi leä ñoù ñöôïc xöû lyù
baèng meänh ñeà catch naøo
. Nghiaõ laø neáu kieåu döõ lieäu xaùc ñònh trong moät catch naøo ñoù
truøng hôïp vôùi kieåu döõ lieäu cuûa ngoaïi leä, thì meänh ñeà catch ñoù ñöôïc thöïc thi. Taát caû
caùc meänh ñeà catch khaùc seõ bò boû qua.
Khi moät ngoaïi leä bò baét laïi, arg seõ nhaän giaù trò cuûa ngoaïi leä naøy. Giaù trò ngoaïi leä coù
theå laø moät kieåu döõ lieäu baát kyø, keå caû kieåu döõ lieäu môùi do ngöôøi duøng taïo ra
.
Ví duï 3.1
Caùch ñieàu khieån ngoaïi leä cuûa C++
// A simple exception handling example.
#include <iostream.h>
int main()
{
cout << "start\n";
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
313
try {
// start a try block
cout << "Inside try block\n";
throw 10;
//
throw
an
error
cout << "This will not execute";
// not execution
}
catch (int i) {
// catch an error
cout << "Caught One! Number is: ";
cout << i << "\n";
}
cout << "end";
return 0;
}
Giaûi thích keát quaû chöông trình ?
start
Inside try block
Caught One ! Numbers is : 10
end
@ Khi moät ngoaïi leä ñöôïc neùm ra, ñieàu khieån cuûa chöông trình seõ chuyeån ñeán bieåu
thöùc cuûa catch vaø keát thuùc vieäc thöïc thi khoái try
.
Ngay sau khoái catch laø moät leänh goïi ñeán haøm exit(), hay abort(), v.v... vì phaàn ñieàu
khieån ngoaïi leä thöôøng ñöôïc duøng ñeå xöû lyù caùc loãi raát nghieâm troïng.
•
Kieåu cuûa ngoaïi leä phaûi gioáng vôùi kieåu xaùc ñònh trong meänh ñeà catch
.
Ví duï 3.2
Moät chöông trình keát thuùc khoâng bình thöôøng do meänh ñeà catch seõ
khoâng baét ñöôïc ngoaïi leä neùm ra.
// This example will not work.
#include <iostream.h>
int main()
{
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
314
cout << "start\n";
try
{
// start a try block
cout << "Inside try block\n";
throw 10;
//
throw
an
error
cout << "This will not execute";
}
catch (double i) {
// Won't work for an int exception
cout << "Caught One! Number is: ";
cout << i << "\n";
}
cout << "end";
return 0;
}
Giaûi thích keát quaû chöông trình ?
start
inside try block
Abnormal program terminal
(Daïng thoâng baùo loãi naøy coù theå khaùc nhau tuyø thuoäc vaøo moãi compiler)
•
Moät ngoaïi leä coù theå ñöôïc neùm ra töø moät meänh ñeà naèm ngoaøi khoái try chæ khi noù
ñöôïc ñaët trong moät haøm, maø haøm naøy ñöôïc goïi töø trong khoái try
.
Ví duï 3.3
Moät chöông trình keát thuùc bình thöôøng.
// Throwing an exception from a function outside the try block.
#include <iostream.h>
void Xtest(int test)
{
cout << "Inside Xtest, test is: " << test << "\n";
if(test)
throw
test;
}
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
315
int main()
{
cout << "start\n";
try {
// start a try block
cout << "Inside try block\n";
Xtest(0);
Xtest(1);
Xtest(2);
}
catch (int i) {
// catch an error
cout << "Caught One! Number is: ";
cout << i << "\n";
}
cout << "end";
return 0;
}
Giaûi thích keát quaû chöông trình
start
Inside try block
Inside Xtest, test is: 0
Inside Xtest, test is: 1
Caught One! Number is: 1
end
•
Moät khoái try coù theå thuoäc veà moät haøm khaùc haøm main() cuûa chöông trình
. Trong
tröôøng hôïp naøy, cöù moãi laàn thöïc hieän haøm, boä ñieàu khieån ngoaïi leä cuûa haøm ñoù seõ
ñöôïc laëp laïi.
Ví duï 3.4
Moät khoái try/catch coù theå ôû beân trong moät haøm khaùc haøm main().
#include <iostream.h>
// A try/catch can be inside a function other than main().
void Xhandler(int test)
{
try{
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
316
if(test) throw test;
}
catch(int i) {
cout << "Caught One! Ex. #: " << i << '\n';
}
}
int main()
{
cout << "start\n";
Xhandler(1);
Xhandler(2);
Xhandler(0);
// not throw
Xhandler(3);
cout << "end";
return 0;
}
@ Coù 3 ngoaïi leä ñöôïc neùm ra. Sau moãi ngoaïi leä, khi haøm ñöôïc goïi laàn nöõa thì boä xöû
lyù loãi ñöôïc laäp laïi.
•
Coù theå taïo nhieàu meänh ñeà catch cho moãi khoái try. Do moãi meänh ñeà catch coù theå
baét moät kieåu ngoaïi leä khaùc bieät vôùi kieåu ôû caùc catch khaùc.
Ví duï 3.5
Moãi bieåu thöùc catch ñöôïc kieåm tra theo thöù töï xuaát hieän vaø chæ coù moät
meänh ñeà truøng kieåu môùi ñöôïc thöïc thi. Taát caû caùc meänh ñeà coøn laïi ñeàu bò boû qua.
#include <iostream.h>
// Different types of exceptions can be caught.
void Xhandler(int test)
{
try
{
if(test) throw test;
else
throw
"Value is zero";
Giaûi thích keát quaû chöông trình ?
start
Caught One! Ex. #: 1
Caught One! Ex. #: 2
Caught One! Ex. #: 3
end
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
317
}
catch(int i) {
cout << "Caught One! Ex. #: " << i << '\n';
}
catch(char *str) {
cout << "Caught a string: ";
cout << str << '\n';
}
}
int main()
{
cout << "start\n";
Xhandler(1);
Xhandler(2);
Xhandler(0);
Xhandler(3);
cout << "end";
return 0;
}
2/
Trong moät soá tröôøng hôïp, seõ caàn moät boä ñieàu khieån ngoaïi leä coù theå baét ñöôïc taát caû
caùc kieåu cuûa ngoaïi leä thay vì moät kieåu naøo ñoù
. Söû duïng meänh ñeà catch theo daïng sau
catch
(...) {
// process all exceptions
}
Daáu "..." baét ñöôïc taát caû kieåu
•
Khi moät haøm ñöôïc goïi töø beân trong khoái block, coù theå haïn cheá kieåu döõ lieäu naøo
cuûa ngoaïi leä maø haøm coù theå neùm ñöôïc. Ñeå thöïc hieän caùc haïn cheá, caàn phaûi
throw vaøo ñònh nghiaõ haøm. Daïng toång quaùt
ret_type
func_name(arg_list) throw(type_list) {
//
.....
}
Giaûi thích keát quaû chöông trình ?
start
Caught One! Ex. #: 1
Caught One! Ex. #: 2
Caught a string: Value is zero
Caught One! Ex. #: 3
end
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
318
Chæ coù caùc ngoaïi leä coù kieåu trong danh saùch type_list (phaân caùch baèng daâuù phaåy) laø
ñöôïc neùm ra töø haøm. Ngöôïc laïi, vieäc neùm ra caùc ngoaïi leä thuoäc kieåu khaùc laø chöông
trình keát thuùc baát thöôøng.
Löu yù
Neáu ñang duøng trình bieân dòch tuaân theo chuaån ANSI C++, thì vieäc thöû neùm
ra moät ngoaïi leä maø khoâng coù meänh ñeà catch naøo baét ñöôïc seõ laøm goïi haøm
unexpected()
. Theo maëc ñònh, haøm unexpected() seõ goïi tieáp haøm abort() ñeå
laøm keát thuùc chöông trình moät caùch baát thöôøng.
Cuõng coù theå ñònh laïi ñeå haøm unexpected() goïi ñeán moät haøm xöû lyù keát thuùc khaùc neáu
laäp trình vieân muoán. Xem chi tieát taøi lieäu höôùng daãn di keøm trong trình bieân dòch.
•
Neáu muoán neùm moät laàn nöõa moät ngoaïi leä töø beân trong boä ñeàu khieån ngoaïi leä,
haõy goïi moät laàn nöõa töø khoaù throw khoâng caàn keøm theo giaù trò cuûa ngoaïi leä.
Caùch naøy cho pheùp ngoaïi leä hieän haønh ñöôïc truyeàn ñeán moät ñoaïn try/catch khaùc.
Ví duï 3.6
Duøng catch(...) ñeå baét moïi ngoaïi leä
// This example catches all exceptions.
#include <iostream.h>
void Xhandler(int test)
{
try{
if(test==0)
throw
test;
// throw int
if(test==1)
throw
'a';
// throw char
if(test==2)
throw
123.23;
// throw double
}
catch(...) {
// catch all exceptions
cout << "Caught One!\n";
}
}
int main()
{
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
319
cout << "start\n";
Xhandler(0);
Xhandler(1);
Xhandler(2);
cout << "end";
return 0;
}
•
Boä ñieàu khieån ngoaïi leä catch(...) coù khaû naêng baét ñöôïc ngoaïi leä thuoäc baát kyø kieåu
naøo
, baèng caùch ñöa catch(...) vaøo cuoái caùc boä ñieàu khieån ngoaïi leä catch khaùc
trong chöông trình.
Ví duï 3.7
// This example uses catch(...) as a default.
#include <iostream.h>
void Xhandler(int test)
{
try{
if(test==0)
throw
test;
// throw int
if(test==1)
throw
'a';
// throw char
if(test==2)
throw
123.23;
// throw double
}
catch(int i) {
// catch an int exception
cout << "Caught " << i << '\n';
}
catch(...) {
// catch all other exceptions
cout << "Caught One!\n";
}
}
int main()
{
Giaûi thích keát quaû chöông trình ?
start
Caught One!
Caught One!
Caught One!
end
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
320
cout << "start\n";
Xhandler(0);
Xhandler(1);
Xhandler(2);
cout << "end";
return 0;
}
Keát quaû chöông trình
start
Caught 0
Caught One!
Caught One!
end
@ Nhö vaäy catch(...) ñöôïc duøng ñeå taïo ra moät boä xöû lyù loãi maëc ñònh coù baét ñöôïc taát
caû caùc ngoaïi leä, ngoaøi caùc ngoaïi leä maø laäp trình vieân ñaõ quan taâm vaø xöû lyù moät caùch
töôøng minh. Hôn naøy, caùch duøng naøy giuùp ngaên ngöøa ñöôïc vieäc ngoaïi leä neùm ra maø
khoâng coù boä xöû lyù naøo baét ñöôïc
, laøm daãn ñeán keát thuùc chöông trình moät caùch baát
thöôøng .
•
Caùch haïn cheá caùc kieåu cuûa ngoaïi leä ñöôïc neùm ra töø trong moät haøm.
Ví duï 3.8
Haøm chæ bò haïn cheá kieåu ngoaïi leä ñöôïc neùm ra töø khoái try maø haøm ñöôïc
goïi
// Restricting function throw types.
#include <iostream.h>
// This function can only throw ints, chars, and doubles.
void Xhandler(int test) throw(int, char, double)
{
if(test==0) throw test;
// throw int
if(test==1) throw 'a';
// throw char
if(test==2) throw 123.23;
// throw double
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
321
}
int main()
{
cout << "start\n";
try{
Xhandler(0);
// also, try passing 1 and 2 to Xhandler()
}
catch(int i) {
cout << "Caught int\n";
}
catch(char c) {
cout << "Caught char\n";
}
catch(double d) {
cout << "Caught double\n";
}
cout << "end";
return 0;
}
@ Ñieàu gì xaûy ra khi khoâng coù doøng catch(int i) {cout << "Caught int\n"; } ?
@ Noäi dung môùi cuûa haøm void Xhandler() giuùp noù ngaên ngöøa vieäc neùm baát kyø ngoaïi
leä naøo .
Ví duï 3.9
// This function can throw NO exceptions!
void Xhandler(int test) throw()
{
/* The following statements no longer work. Instead,
They will cause an abnormal program termination. */
if(test==0) throw test;
if(test==1) throw 'a';
if(test==2) throw 123.23;
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
322
}
•
Coù theå neùm ra moät laàn nöõa moät ngoaïi leä. Nguyeân nhaân thöôøng gaëp cuûa vieäc
neùm laïi naøy laø cho pheùp boä xöû lyù truy caäp nhieàu laàn moät ngoaïi leä.
Ví duï 3.10
Chöông trình neùm ra moät ngoaïi leä kieåu char *
// Example of "rethrowing" an exception.
#include <iostream.h>
void Xhandler()
{
try {
throw "hello";
// throw a char *
}
catch(char *) {
// catch a char *
cout << "Caught char * inside Xhandler\n";
throw ;
// rethrow char * out of function
}
}
int main()
{
cout << "start\n";
try{
Xhandler();
}
catch(char *) {
cout << "Caught char * inside main\n";
}
cout << "end";
return 0; }
Baøi taäp III
Giaûi thích keát quaû chöông trình ?
start
Caught char * inside Xhandler
Caught char * inside main
end
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
323
1. Tìm ñieåm sai vaø söûa loãi trong chöông trình sau
int main()
{
throw 12.23;
... }
2. Tìm ñieåm sai vaø söûa loãi trong chöông trình sau
try {
// ...
throw 'a';
// ...
}
catch(char *) {
// ...
}
3. Ñieàu gì xaûy ra khi moät ngoaïi leä bò neùm ra maø khoâng coù meänh ñeà catch töông öùng
?
4. Tìm ñieåm sai vaø söûa loãi trong chöông trình sau
try {
// ...
throw 10;
}
catch(int *p) {
// ...
}
5. Haõy theâm vaøo haøm sau ñaây chöùc naêng kieåm tra loãi khi chia chi giaù trò zero.
double divide(double a, double b)
{
// add error handling
return a/b;
}
IV/ Bieán tónh
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
324
1/ Khaùi nieäm
Moät bieán phaàn töû cuûa lôùp coù theå ñöôïc khai baùo laø bieán tónh. Moät haøm thaønh phaàn cuûa
lôùp cuõng coù theå ñöôïc khai baùo laø tónh, nhöng ít söû duïng (khoâng baøn ñeán trong baøi
giaûng naøy).
Söû duïng bieán tónh, coù theå traùnh ñöôïc moät soá vaán ñeà phöùc taïp.
Khi khai baùo moät bieán laø bieán tónh, coù nghóa laø cho pheùp moät baûn duy nhaát cuûa bieán
ñoù ñöôïc toàn taïi
baát keå coù bao nhieâu ñoái töôïng thuoäc lôùp ñoù ñöôïc sinh ra. Taát caû caùc
ñoái töôïng ñoù söû duïng chung bieán tónh
. Ngoaøi ra, coøn cho taát caû caùc lôùp khaùc thöøa keá
töø lôùp ñoù söû duïng bieán tónh.
Moät bieán tónh toàn taïi ngay tröôùc khi lôùp cuûa noù ñöôïc taïo ra. Xeùt veà baûn chaát, bieán
tónh laø moät bieán toaøn cuïc nhöng phaïm vi coù nghóa cuûa noù chæ giôùi haïn trong lôùp maø
noù ñöôïc khai baùo. Do ñoù coù theå truy caäp moät bieán tónh ñoäc laäp vôùi baát kyø ñoái töôïng
naøo.
Nguyeân nhaân chính maø C++ hoå trôï caùc bieán tónh laø ñeà phoøng nhu caàu söû duïng bieán
toaøn cuïc. Löu yù, vieäc söû duïng caùc lôùp vaøo caùc bieán toaøn cuïc thöôøng xuyeân vi phaïm
nguyeân taéc ñoùng goùi, moät nguyeân taéc caên baûn cuûa laäp trình höôùng ñoái töôïng .
2/ Khai baùo, ñònh nghóa vaø khôûi taïo
Bieán tónh ñöôïc khai baùo trong moät lôùp. Phaàn ñònh nghóa bieán tónh laïi ôû beân ngoaøi
lôùp. Do ñoù caàn söû duïng toaùn töû phaïm vi ñi keøm vôùi bieán tónh.
Taát caû caùc bieán tónh ñeàu ñöôïc khôûi taïo baèng giaù trò zero theo maëc ñònh
. Maëc khaùc coù
theå khôûi taïo baèng giaù trò khaùc.
Ví duï 4.1
// A static member variable example.
#include <iostream.h>
class myclass {
static int i;
public:
void seti(int n) { i = n; }
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
325
int geti() { return i; }
};
// Definition of myclass::i. i is still private to myclass.
int myclass::i ;
int main()
{
myclass o1, o2;
o1.seti(10);
cout << "o1.i: " << o1.geti() << '\n'; // displays 10
cout << "o2.i: " << o2.geti() << '\n'; // also displays 10
return 0;
}
@ Veà maët kyõ thuaät, khai baùo moät lôùp chæ laø moät söï thoâng baùo. Vì bieán tónh haøm yù
raèng boä nhôù ñöôïc daønh cho bieán ñoù, phaàn ñònh nghóa bieán caàn thieát ñeå caát leân vuøng
ñöôïc caáp
.
•
Bieán tónh coù theå ñöôïc truy caäp moät caùch ñoäc laäp vôùi ñoái töôïng bôûi vì noù coù
tröôùc caùc ñoái töôïng.
Ví duï 4.2
// Use a static member variable independent of any object.
#include <iostream.h>
class myclass {
public:
static int i;
void seti(int n) { i = n; }
int geti() { return i; }
};
int myclass::i;
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
326
int main()
{
myclass o1, o2;
// set i directly
myclass::i = 100;
// no object is referenced.
cout << "o1.i: " << o1.geti() << '\n'; // displays 100
cout << "o2.i: " << o2.geti() << '\n'; // also displays 100
return 0;
}
@ Bieán tónh i ñöôïc gaùn gía trò 100 maø khoâng caàn tham khaûo ñeán moät ñoái töôïng cuï
theå naøo.
•
Caùch söû duïng thoâng thöôøng cuûa bieán tónh laø ñònh vò truy caäp ñeán moät taøi
nguyeân duøng chung
nhö file, maùy in hay server. Vieäc ñònh vò naøy ñoøi hoûi moät
soá phöông tieän ñeå saép haøng caùc bieán coá
.
Ví duï 4.3
Chöông trình seõ taïo ra moät lôùp output, duøng moät bieán tónh kieåu maûng
kyù töï laøm vuøng ñeäm xuaát vôùi teân laø outbuf. Vuøng ñeäm naøy ñöôïc duøng ñeå nhaän caùc
keát xuaát sinh ra bôûi haøm thaønh phaàn putbuf(). Haøm putbuf() gôûi töøng kyù töï cuûa noäi
dung bieán chuoåi str, cuï theå laø noù ñoøi quyeàn truy caäp ñeán vuøng ñeäm roài gôûi taát caû caùc
kyù töï cuûa chuoåi str. Trong suoát thôøi gian keát xuaát, haøm putbuf() khoaù khoâng cho caùc
ñoái töôïng khaùc truy caäp ñeán vuøng ñeäm.
// A shared resource example.
#include <iostream.h>
#include <string.h>
class output {
static char outbuf[255]; // this is the shared resource
static int inuse;
// buffer available if 0; in use otherwise
static int oindex;
// index of outbuf
char str[80];
int i;
// index of next char in str
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
327
int who;
// identifies the object, must be > 0
public:
output(int w, char *s) { strcpy(str, s); i = 0; who = w; }
/* This function returns -1 if waiting for buffer,
it returns 0 if it is done outputting, and
it returns who if it is still using the buffer. */
int putbuf()
// from str[] to outbuf[]
{
if(!str[i]) {
// done outputting
inuse = 0;
// release buffer
return 0;
// signal termination
}
if(!inuse) inuse = who;
// get buffer
if(inuse != who) return -1; // in use by someone else
if(str[i]) {
// still chars to output
outbuf[oindex] = str[i];
i++; oindex++;
outbuf[oindex] = '\0';
// always keep null-terminated
return 1;
}
return 0;
}
void show() { cout << outbuf << '\n'; }
};
char output::outbuf[255];
// this is the shared resource
int output::inuse = 0;
// buffer available if 0; in use otherwise
int output::oindex = 0;
// index of outbuf
int main()
{
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
328
output o1(1, "This is a test"), o2(2, " of statics");
while(o1.putbuf() | o2.putbuf()) ;
// output chars
o1.show();
return 0;
}
Keát quaû chöông trình ?
Baøi taäp IV
1. Vieát laïi chöông trình trong ví duï 4.3 chöông 10, ñeå coù theå trình baøy teân cuûa ñoái
töôïng ñang truy caäp ñeán vuøng ñeäm vaø teân caùc ñoái töôïng ñang bò caám truy caäp vuøng
ñeäm.
2. Bieán tónh ñöôïc öùng duïng ñeå theo doõi soá löôïng caùc ñoái töôïng cuûa moät lôùp toàn taïi ôû
moät thôøi ñieåm baát kyø
. Baèng caùch seõ taêng trò soá ñeám cuûa moät bieán tónh moãi luùc haøm
taïo cuûa lôùp ñöôïc goïi, vaø laøm giaûm trò soá ñeám moãi khi haøm huûy cuûa lôùp ñöôïc goïi.
Vieát chöông trình taïo moät lôùp test coù bieán tónh count laø bieán rieâng, moät haøm taïo, haøm
huûy vaø haøm getcount() traû veà gía trò cuûa count. Chöông trình coù söû duïng 3 ñoái töôïng
vaø moät con troû ñoái töôïng p.
V/ Töø khoaù extern vaø asm
C++ cung caáp hai cô cheá quan troïng laøm cho vieäc keát noái giöõa chöông trình C++ vaø
chöông trình ngoân ngöõ khaùc trôû neân deã daøng hôn.
Cô cheá 1 : boä chæ ñònh keát noái (extern) duøng ñeå thoâng baùo vôùi trình bieân dòch raèng
moät hay moät soá haøm naøo ñoù trong chöông trình seõ ñöôïc keát noái vôùi moät ngoân ngöõ
khaùc, vaø chuùng coù theå coù nhöõng qui öôùc khaùc veà vieäc truyeàn tham soá. Daïng toång
quaùt
extern
“Language” {
function_prototypes
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
329
}
Language
: teân cuûa ngoân ngöõ maø haøm cuûa chöông trình caàn keát noái
function_prototypes
: caùc haøm caàn keát noái
Taát caû caùc chæ ñònh keát noái phaûi mang tính toaøn cuïc vaø noù khoâng theå naèm beân trong
moät haøm. Ngoaøi ra coù theå chæ ñònh keát noái cho caùc ñoái töôïng (ít xaûy ra).
Ví duï
5.1 Chöông trình sau keát noái haøm func() theo kieåu haøm cuûa C hôn laø haøm cuûa
C++
// Illustrate linkage specifier.
#include <iostream.h>
extern
"C" int func(int x);
// link as C function
// This function now links as a C function.
int func(int x)
{
return x/3;
}
Ví duï
5.2 Ñoaïn chöông trình sau thoâng baùo vôùi trình bieân dòch raèng f1(), f2(), f3()
seõ ñöôïc keát noái nhö caùc haøm cuûa C.
extern
"C" {
void f1();
int f2(int x);
double f3(double x, int *p);
}
Cô cheá 2 : töø khoaù asm cho pheùp laäp trình vieân nhuùng ñoaïn maõ leänh hôïp ngöõ vaøo
trong chöông trình nguoàn C++.
Öu ñieåm : chöông trình öùng duïng hoaøn toaøn laø moät chöông trình C++ vaø noù khoâng
caàn phaûi keát noái vôùi caùc file chöông trình hôïp ngöõ khaùc. Daïng toång quaùt
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
330
asm
(“op_code”) ;
op_code
laø moät caâu leänh hôïp ngöõ nhuùng trong chöông trình.
Löu yù Turbo C++ vaø Borland C++ chaáp nhaän moät soá daïng khaùc nhau cuûa meänh ñeà
asm :
asm
op_code;
asm
op_code newline;
asm
{
//
statements;
}
Ví duï
5.3 Ñoaïn chöông trình sau nhuùng nhieàu caâu leänh hôïp ngöõ vaøo haøm func()
// Don't try this function!
void func()
{
asm("mov bp, sp");
asm("push ax");
asm("mov cl, 4");
// ...
}
Baøi taäp V
1. Nghieân cöùu taøi lieäu höôùng daãn söû duïng caùc trình bieân dòch sau ñaây, nhöõng noäi
dung lieân quan ñeán chæ ñònh keát noái vaø giao tieáp vôùi asembly :
- Borland C++ version 4.5 hoaëc cao hôn
- Visual C++ version 6.0 hoaëc cao hôn
VI/ Haøm chuyeån kieåu
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
331
Vieäc chuyeån ñoåi moät ñoái töôïng thuoäc kieåu naøy thaønh moät ñoái töôïng kieåu khaùc toû ra
höõu ích trong moät soá tröôøng hôïp. Coù theå söû duïng quaù taûi toaùn töû ñeå thöïc hieän vieäc
chuyeån ñoåi, nhöng caùch söû duïng haøm chuyeån kieåu laø moät giaûi phaùp deã daøng vaø hay
hôn.
Moät haøm chuyeån kieåu thöïc hieän töï ñoäng vieäc chuyeån ñoåi moät ñoái töôïng thaønh moät giaù
trò töông thích vôùi kieåu cuûa bieåu thöùc maø ñoái töôïng ñoù coù tham gia
.
Daïng toång quaùt
operator
type() { return value; }
type
laø kieåu caàn chuyeån
value
laø gía trò cuûa ñoái töôïng sau khi ñöôïc chuyeån
Haøm seõ traû veà gía trò thuoäc kieåu type.
Haøm chuyeån kieåu khoâng coù tham soá vaø noù phaûi laø haøm thaønh phaàn cuûa lôùp trong ñoù
haøm thöïc hieän vieäc chuyeån kieåu.
Haøm chuyeån kieåu cung caáp moät caùch tieáp caän saùng suûa hôn cho vieäc chuyeån kieåu
cuûa ñoái töôïng so vôùi caùc phöông phaùp cuûa C++, bôûi vì noù cho pheùp moät ñoái töôïng
ñöôïc söû duïng tröïc tieáp trong bieåu thöùc thuoäc kieåu caàn chuyeån ñeán.
Ví duï
6.1
Lôùp coord coù moät haøm chuyeån kieåu thaønh kieåu nguyeân.
Haøm traû veà gía trò tích cuûa hai toaï ñoä
// A simple conversion function example.
#include <iostream.h>
class coord {
int x, y;
public:
coord(int i, int j) { x = i; y = j; }
operator int() { return x*y; }
// conversion function
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
332
};
int main()
{
coord o1(2, 3), o2(4, 3);
int i;
i = o1;
// automatically convert to integer
cout << i << '\n';
i = 100 + o2;
// convert o2 to integer
cout << i << '\n';
return 0;
}
@ Baèng caùch duøng haøm chuyeån kieåu, caùc lôùp töï taïo ñöôïc hoaø nhaäp vaøo trong moät
bieåu thöùc thoâng thöôøng cuûa C++ maø khoâng caàn phaûi söû duïng moät maûng caùc toaùn töû
quùa taûi raát phöùc taïp.
Ví duï
6.2
Lôùp strtype coù moät haøm chuyeån kieåu chuyeån chuoåi kyù töï thaønh
moät con troû ñeán chuoåi str
#include <iostream.h>
#include <string.h>
class strtype {
char str[80];
int len;
public:
strtype(char *s) { strcpy(str, s); len = strlen(s); }
operator char *() { return str; }
// convert to char*
};
int main()
{
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
333
strtype s("This is a test\n");
char *p, s2[80];
p = s;
// convert to char *
cout << "Here is string: " << p << '\n';
// convert to char * in function call
strcpy(s2, s);
cout << "Here is copy of string: " << s2 << '\n';
return 0;
}
@ Haøm chuyeån kieåu khoâng chæ ñöôïc goïi khi ñoái töôïng s bò gaùn cho con troû p, maø coøn
ñöôïc goïi khi ñoái töôïng s ñöôïc duøng nhö moät tham soá cuûa haøm strcpy() coù daïng
char *strcpy(char *s1, char *s2) ;
Vì s2 coù kieåu char *, neân haøm chuyeån kieåu thaønh char * seõ ñöôïc goïi thöïc thi moät
caùch töï ñoäng.
@ Nhö vaäy haøm chuyeån kieåu coù theå giuùp laäp trình vieân tích hôïp caùc lôùp töï taïo vaøo
thö vieän haøm chuaån cuûa C++
moät caùch eâm thaám.
Baøi taäp VI
1. Qua lôùp strtype trong ví duï 7.2 chöông 10, vieát chöông trình taïo ra moät haøm
chuyeån sang kieåu nguyeân. Haøm seõ traû veà gía trò laø chieàu daøi cuûa chuoãi kyù töï str.
2. Cho moät lôùp sau
class pwr {
int
base;
int
exp;
public:
pwr(int b, int e) {base = b; exp = e;}
// create conversion to integer here
};
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
334
Haõy taïo ra moät haøm chuyeån moät ñoái töôïng kieåu pwr thaønh kieåu nguyeân. Haøm seõ traû
veà gía trò cuûa bieán base.
VII/ Nhöõng khaùc bieät giöõa C vaø C++
C++ laø moät sieâu taäp hôïp cuûa C, vaãn coù moät soá khaùc bieät giöõa C vaø C++, söï khaùc bieät
naøy coù theå laøm cho trình bieân dòch C++ khoâng bieân dòch ñöôïc moät soá chöông trình C
naøo ñoù. Do ñoù laäp trình vieân caàn naém vöõng ñeå vieát moät chöông trình C++ ñöôïc toát.
Caùc khaùc bieät
C
C++
1/ Haøm khoâng coù ñoái soá Nguyeân maãu cuûa haøm coù töø
khoaù void
Vd : char f1(void);
Töø khoaù void laø tuyø yù
Vd : char f1();
2/ Haèng kyù töï
ñöôïc töï ñoäng chuyeån thaønh
soá nguyeân
Khoâng theå
3/ Bieán toaøn cuïc khai
baùo nhieàu laàn ôû nhieàu
nôi
Khoâng baùo loãi
baùo loãi
4/ Teân (identifier) toái ña 31 kyù töï
1024 kyù töï
5/ Goïi haøm main()
Töø beân trong chöông trình
Cho pheùp, khoâng neân
laïm duïng
Baøi taäp chöông 10
Chöông 10 Template vaø ñieàu khieån ngoaïi leä
335
1. Söï khaùc bieät giöõa caùc bieán tónh vaø caùc bieán khaùc cuûa moät lôùp laø gì ?
2. Ngoaøi vieäc nhaäp/xuaát theo maûng söû duïng boä nhôù nhö moät thieát nhaäp/xuaát, coøn coù
söï khaùc bieät naøo giöõa noù vaø nhaäp/xuaát thoâng thöôøng trong C++ hay khoâng ?
3. Haõy vieát moät haøm int counter(int array[], int size) ñeám soá caùc phaàn töû cuûa array
coù gía trò leû döôùi daïng ngoân ngöõ C, laøm theá naøo lieân keát vaøo chöông trình C++ coù söû
duïng lôùp.
4. Haõy taïo ra haøm chung traû veà giaù trò mode cuûa moät maûng (giaù trò mode laø giaù trò
baét gaëp nhieàu trong daõy) vaø soá laàn xuaát hieän cuûa noù.
5. Haõy taïo haøm tính vaø traû veà giaù trò toång cuûa caùc phaàn töû trong moät maûng ?
6. Haõy taïo ra haøm chung thöïc hieän moät soá giaûi thuaät saép xeáp (ñaõ hoïc trong moân Caáu
truùc döõ lieäu vaø thuaät toaùn)
7. Vieát chöông trình ñònh nghóa laïi lôùp stack ñeå noù löu tröõ moät caëp goàm hai ñoái töôïng
coù kieåu döõ lieäu khaùc nhau.
8. Vieát chöông trình ñònh nghóa laïi lôùp stack ñeå noù coù khaû naêng xöû lyù caùc loãi : full
stack vaø empty stack .
9. Vieát chöông trình ñònh nghóa laïi lôùp array trong ví du 7.3 chöông 3 , chuyeån lôùp
naøy thaønh moät lôùp chung.
10. Vieát chöông trình ñònh nghóa haøm chung abs() trong ví du 3.7 chöông 1, sao cho
noù tính vaø traû veà giaù trò tuyeät ñoái cuûa moät giaù trò thuoäc baát kyø kieåu naøo.
Chöông 11
Phaùt trieån caùc heä thoáng höôùng ñoái töôïng
•
Giôùi thieäu
•
Caùc moâ hình höôùng-thuû tuïc
•
Caùc coâng cuï phaùt trieån höôùng-thuû tuïc
•
Moâ hình höôùng ñoái töôïng
•
Caùc kyù hieäu vaø ñoà thò höôùng ñoái töôïng
•
Caùc böôùc phaân tích höôùng ñoái töôïng
•
Caùc böôùc thieát keá höôùng ñoái töôïng
•
Caøi ñaët
•
Moâ hình maãu
•
Toùm taét
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
338
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
339
I/ Giôùi thieäu
Caùc kyõ sö phaàn meàm ñaõ duøng nhieàu coâng cuï (tools), phöông phaùp (methods) vaø thuû
tuïc
(procedures) khaùc nhau ñeå thöïc hieän tieán trình phaùt trieån phaàn meàm nhaèm xaây
döïng caùc saûn phaåm phaàn meàm chaát löôïng cao vôùi hieäu suaát ngaøy caøng caûi tieán.
Caùc phöông phaùp
cung caáp khaùi nieäm “laøm nhö theá naøo” ñeå xaây döïng phaàn meàm
trong khi caùc coâng cuï cung öùng caùc hoå trôï töï ñoäng vaø baùn töï ñoäng cho caùc phöông
phaùp. Hoï söû duïng moïi giai ñoaïn phaùt trieån cuûa tieán trình phaùt trieån phaàn meàm, ñoù laø,
laäp keá hoaïch, phaân tích, thieát keá, phaùt trieån vaø baûo trì.
Caùc thuû tuïc
phaùt trieån phaàn meàm tích hôïp caùc phöông phaùp vaø caùc coâng cuï laïi vôùi
nhau vaø laøm cho söï phaùt trieån caùc heä thoáng phaàn meàm trôû neân hôïp lyù vaø hôïp thôøi.
(hình 11.1). Chuùng cung caáp caùc nguyeân taéc chæ ñaïo nhö laøm theá naøo aùp duïng caùc
phöông phaùp vaø coâng cuï, laøm theá naøo ñeå tieán haønh phaân phoái ôû moãi giai ñoaïn, caùc
ñieàu khieån naøo seõ aùp duïng, vaø nhöõng coät moác naøo ñöôïc duøng ñeå ñaùnh giaù söï phaùt
trieån.
Software
development
Procedures
Methods
Tools
Hình 11.1 Caùc thaønh toá phaùt trieån phaàn meàm
Coù moät soá moâ hình phaùt trieån phaàn meàm, moãi moâ hình bao goàm moät taäp hôïp caùc
phöông phaùp vaø coâng cuï khaùc nhau. Vieäc löïa choïn moät moâ hình phuï thuoäc vaøo baûn
chaát cuûa moät öùng duïng, ngoân ngöõ laäp trình ñöôïc duøng, nhöõng ñieàu khieàn vaø phaân
phoái ñöôïc yeâu caàu.
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
340
Söï phaùt trieån moät heä thoáng hoaøn chænh khoâng nhöõng phuï thuoäc vaøo nhöõng phöông
phaùp vaø kyõ thuaät thích hôïp maø coøn phuï thuoäc caùc raøng buoäc cuûa nhöõng nhaø phaùt
trieån vaøo caùc ñoái töôïng cuûa heä thoáng. Moät heä thoáng hoaøn chænh phaûi laø :
1. thoaû maõn nhöõng yeâu caàu cuûa ngöôøi duøng.
2. trôû neân deå hieåu ñoái vôùi ngöôøi duøng vaø ngöôøi vaän haønh
3. trôû neân deå thao taùc
4. coù giao dieän toát
5. deã daøng chænh lyù
6. coù theå phaùt trieån ñöôïc
7. coù nhöõng ñieàu khieån baûo maät thích hôïp choáng laïi söï laïm duïng döõ lieäu
8. baét loãi vaø xöû lyù ngoaïi leä thaät haøi loøng
9. phaân phoái saûn phaåm theo ñuùng ngaøy giôø ñaõ aán ñònh
Trong chöông naøy chuùng ta seõ xem xeùt moät vaøi caùch tieáp caän truyeàn thoáng ñöôïc öùng
duïng roäng raõi trong phaùt trieån phaàn meàm vaø thaûo luaän moät vaøi yù töôûng hieän nay coù
theå aùp duïng ñöôïc vaøo phaùt trieån phaàn meàm höôùng ñoái töôïng.
II/ Caùc moâ hình höôùng-thuû tuïc
Prolem
definition
Analysis
Design
Coding
Testing
Maintenance
Hình 11.2 Chu kyø soáng phaùt trieån phaàn meàm coå ñieån
(moâ hình “thaùc nöôùc” nhuùng ñöôïc)
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
341
Phaùt trieån phaàn meàm thöôøng ñöôïc moâ taû bôûi moät boä caùc traïng thaùi moâ taû caùc taùc vuï
khaùc nhau bao goàm trong tieán trình phaùt trieån. Hình 11.2 minh hoaï chu kyø soáng phaàn
meàm coå ñieån ñöôïc öùng duïng roäng raõi trong phaùt trieån höôùng-thuû tuïc (procedure-
oriented).
Chu kyø soáng coå ñieån döïa treân moät moâ hình cô baûn, thoâng thöôøng laø moâ hình “thaùc
nöôùc”. Moâ hình naøy coá gaéng laøm roõ nhöõng hoaït ñoäng coù theå nhaän bieát ñöôïc trong
moät chuoãi caùc haønh ñoäng, moãi moät trong soá chuùng phaûi hoaøn taát tröôùc khi haønh ñoäng
khaùc laïi baét ñaàu. Caùc hoaït ñoäng bao goàm, xaùc ñònh vaán ñeà, phaân tích caùc yeâu caàu,
thieát keá, laäp trình, kieåm nghieäm, vaø baûo trì. Söï tinh cheá hôn nöõa cho moâ hình naøy
bao goàm caùc böôùc laëp quay lui nhöõng giai ñoaïn tröôùc ñoù nhaèm keát hôïp chaët cheõ baát
kyø söï bieán ñoåi naøo hoaëc caùc lieân keát coøn thieáu.
Xaùc ñònh vaán ñeà
: Haønh ñoäng naøy yeâu caàu moät ñònh nghóa chính xaùc veà vaán ñeà trong
nhöõng thuaät ngöõ ñang duøng. Moät phaùt bieåu roõ raøng cuûa vaán ñeà laø moät quyeát ñònh cho
söï thaønh coâng cuûa saûn phaåm. Noù khoâng chæ giuùp cho nhaø phaùt trieån maø coøn giuùp
ngöôøi söû duïng hieåu vaàn ñeà ñöôïc toát hôn.
Phaân tích caùc yeâu caàu
: Ñieàu naøy bao truøm söï nghieân cöùu chi tieát veà nhöõng yeâu caàu
cuûa caû ngöôøi duøng laãn saûn phaåm. Haønh ñoäng naøy laø moät böôùc cô baûn coù lieân quan
ñeán “caùi gì” (What) cuûa heä thoáng nhö laø :
•
Nhöõng ñaàu vaøo cho heä thoáng laø caùi gì ?
•
Caùc tieán trình yeâu caàu caùi gì ?
•
Nhöõng ñaàu ra mong muoán seõ laø caùi gì ?
•
Nhöõng raøng buoäc (constraints) laø gì ?
Thieát keá
: pha thieát keá giaûi quyeát nhöõng quan nieäm khaùc nhau cuûa thieát keá heä thoáng
nhö caáu truùc döõ lieäu, kieán truùc saûn phaåm, vaø caùc thuaät toaùn. Pha naøy chuyeån nhöõng
yeâu caàu vaøo caùch bieåu dieãn (representation) cuûa saûn phaåm. Giai ñoaïn naøy traû lôøi caâu
hoûi “How”.
Laäp trình
: Maõ hoaù coù lieân quan ñeán söï chuyeån dòch baûn thieát keá sang daïng maõ-maùy-
coù-theå-ñoïc-ñöôïc. Chi tieát hoaù baûn thieát keá, deã daøng hôn ñoù laø söï maõ hoaù vaø laøm cho
tính tin caäy cuûa thieát keá ñöôïc toát hôn.
Kieåm nghieäm
: moät baûn maõ leänh ñöôïc vieát xong , caàn phaûi kieåm nghieäm nghieâm ngaët
giuùp cho baûn maõ vaø keát quaû ñöôïc toát nhaát. Söï kieåm nghieäm coù theå laø moät vaøi modul
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
342
rieâng leõ hoaëc coù khi laø toaøn boä heä thoáng. Noù yeâu caàu moät keá hoaïch chi tieát nhö kieåm
tra caùi gì, khi naøo vaø laøm nhö theá naøo (what, when, how to test)
Baûo trì
: sau khi saûn phaåm ñaõ ñöôïc hoaøn chænh, noù coù theå phaûi chòu moät vaøi thay ñoåi.
Ñieàu naøy thöôøng xaûy ra theo yeâu caàu cuûa ngöôøi duøng vaø cuûa caû moâi tröôøng ñieàu
haønh, hoaëc moät loãi naøo ñoù trong saûn phaåm bò soùt trong quaù trình kieåm nghieäm. Söï
baûo trì baûo ñaûm raèng moïi thay ñoåi seõ ñöôïc keát hôïp chaët cheõ baát cöù luùc naøo thaáy caàn
thieát.
Moãi pha cuûa chu kyø soáng ñeàu coù muïc ñích vaø ñaàu ra. Ñaàu ra cuûa pha naøy seõ laø ñaàu
vaøo cuûa pha tieáp theo. Baûng 11.1 seõ chiû ra caùc kieåu cuûa ñaàu ra
Pha
Ñaàu ra (outputs)
Xaùc ñònh vaán ñeà
* Phieáu phaùt bieåu cuûa vaán ñeà
(why)
* Taøi lieäu ñeà nghò cuûa döï aùn
Phaân tích
* Taøi lieäu yeâu caàu
(what)
* Baùo caùo khaû thi
* Taøi lieäu ñaëc taû
* Tieâu chuaån kieåm nghieäm ñöôïc coâng nhaän
Thieát keá
* Taøi lieäu thieát keá
(how)
* Thieát keá caùc tình huoáng cho kieåm nghieäm
Maõ hoaù
* Taøi lieäu maõ hoaù (chöông trình)
(how)
* Keá hoaïch kieåm nghieäm
* Taøi lieäu cho ngöôøi duøng
Kieåm nghieäm
* Caùc maõ hoaù ñaõ ñöôïc kieåm nghieäm
(what & how)
* Caùc keát quaû kieåm nghieäm
* Taøi lieäu cho heä thoáng
Baûo trì
* Caùc phieáu nhaät kyù baûo trì
* Taøi lieäu caùc phieân baûn
Baûng 11.1 Caùc ñaàu ra cuûa chu kyø soáng phaàn meàm coå ñieån
Chu kyø soáng phaàn meàm, ñöôïc moâ taû ôû treân, thöôøng ñöôïc xem nhö kyõ thuaät phaân raõ
chöùc naêng (the functional decomposition), ñöôïc bieát roäïng raõi nhö caùch tieáp caän töø
treân xuoáng (top-down), hoaëc theo modun (modular). Kyõ thuaät phaân raõ chöùc naêng döïa
treân söï theå hieän khoâng gian vaán ñeà vaø noù chuyeån sang khoâng gian lôøi giaûi nhö laø söï
thoâng dòch moät taäp caùc haøm. Caùc haøm ñöôïc phaân raõ theo trình töï taêng daàn, nhöõng
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
343
haøm ñôn giaûn nhaát seõ ñöôïc thöïc thi cuoái cuøng. Heä thoáng cuoái cuøng ñöôïc xem nhö
moät taäp caùc haøm ñöôïc toå chöùc theo caáu truùc phaân caáp top-down .
Cuõng coù moät vaøi thieáu soùt trong caùch tieáp caän top-down, tieáp caän phaân raõ chöùc naêng.
Chuùng bao goàm :
1. Khoâng cho pheùp nhöõng thay ñoåi tieán hoaù trong phaàn meàm.
2. Heä thoáng ñöôïc ñaëc tröng bôûi moät haøm ñôn (a single function) ôû ñænh cuûa caây
phaân caáp nhöng khoâng phaûi luùc naøo cuõng hoaøn toaøn ñuùng. Trong nhieàu
tröôøng hôïp thöïc teá caùc heä thoáng khoâng coù haøm ñôn ôû ñænh.
3. Döõ lieäu khoâng ñöôïc xem laø ñaùng quan troïng.
4. Noù khoâng khuyeán khích vieäc taùi söû duïng maõ leänh ñaõ coù.
III/ Caùc coâng cuï phaùt trieån höôùng-thuû tuïc
Caùc coâng cuï phaùt trieån hieän nay coù theå phaân loaïi theo 3 theá heä.
Caùc coâng cuï theá heä 1 ñöôïc phaùt trieån vaøo thaäp nieân 60 vaø 70 ñöôïc goïi laø caùc coâng cuï
truyeàn thoáng.
Caùc coâng cuï theá heä 2 ñöôïc giôùi thieäu vaøo cuoái thaäp nieân 70 vaø ñaàu thaäp nieân 80 daønh
cho phaân tích vaø thieát keá caùc heä thoáng coù caáu truùc vaø do ñoù chuùng ñöôïc bieát nhö laø
caùc coâng cuï coù caáu truùc.
Caùc coâng cuï theá heä 3 ñöôïc giôùi thieäu vaøo cuoái thaäp nieân 80 cho ñeán nay daønh cho
phaân tích vaø thieát keá caùc heä thoáng höôùng ñoái töôïng.
Baûng 11.2 chæ cho thaáy moät soá coâng cuï thoâng duïng daønh cho caùc tieán trình phaùt trieån
theo 3 chuûng loaïi. Phaàn naøy seõ giôùi thieäu toång quaùt moät vaøi coâng cuï thöôøng duøng ôû
theá heä 1 vaø 2.
Process
First
generation
Second generation Third generation
Physical
processes
System
flowcharts
Context diagrams Inheritance graphs
Object-relationship
charts
Data
Layout
forms Data
dictionary Objects
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
344
representation
Grid charts
Object dictionary
Logic
processes
Playscript
English
narrative
Decision tables
trees
Data flow
diagrams
Inheritance
graphs
Data flow diagrams
Program
representation
Program
flowcharts
I/O layouts
Structure
charts
Warrier/Orr
diagrams
State change diagrams
Ptech diagrams
Coad/Yourdon charts
Baûng 11.2 Caùc coâng cuï phaùt trieån heä thoáng
!"
Löu ñoà heä thoáng (System flowcharts)
!"
Löu ñoà chöông trình (Program flowcharts)
!"
Kòch baûn töøng giai ñoaïn (Playscripts)
!"
Caùc khuoân daïng sô boä (Layout forms) cho vieäc nhaäp vaø xuaát keát quaû .
!"
Bieåu ñoà (Grid charts) bieåu dieãn moái quan heä giöõa caùc modun cuûa heä thoáng.
!"
Löôïc ñoà ngöõ caûnh (Context diagrams) bieåu dieãn ñaàu vaøo vôùi taøi nguyeân cuûa
chuùng vaø ñaàu ra vôùi caùc ñích cuûa chuùng.
!"
Löôïc ñoà doøng döõ lieäu (Data flow diagrams) bieåu dieãn doøng döõ lieäu giöõa caùc thaønh
phaàn khaùc nhau cuûa heä thoáng
!"
Töø ñieån döõ lieäu (Data dictionary)
!"
Bieåu ñoà caáu truùc (Structures chart) bieåu dieãn ñoà thò caùc ñieàu khieån logic giöõa caùc
modun cuûa heä thoáng.
!"
Baûng quyeát ñònh (Decision table) moät baûng caùc tình huoáng baát ngôø daønh cho vieäc
xaùc ñònh vaán ñeà vaø caùc haønh ñoäng ñeå thöïc hieän.
!"
Caây quyeát ñònh (Decision tree)
!"
Löôïc ñoà Warnier/Orr : moät bieåu ñoà phaân caáp haøng ngang söû duïng moät taäp caùc daáu
moùc, maõ giaû (pseudo-code) vaø caùc kyù hieäu logic ñeå chæ caùc caáu truùc chöông trình.
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
345
IV/ Moâ hình höôùng-ñoái töôïng
Moâ hình höôùng-ñoái töôïng ñaët naëng treân lyù thuyeát heä thoáng toång quaùt nhö laø neàn taûng
thuoäc veà khaùi nieäm. Moät heä thoáng coù theå ñöôïc xem nhö moät söï taäp hôïp caùc thöïc theå
(entities), chuùng töông taùc vôùi nhau nhaèm ñaït ñeán muïc tieâu naøo ñoù
(hình 11.3).
Caùc thöïc theå coù theå bieåu dieãn caùc ñoái töôïng vaät lyù nhö caùc thieát bò hay con ngöôøi, vaø
caùc khaùi nieäm tröøu töôïng nhö caùc file döõ lieäu hoaëc caùc haøm. Trong phaân tích höôùng-
ñoái töôïng caùc thöïc theå ñöôïc goïi laø caùc ñoái töôïng (objects).
PROCESS
INPUT
OUTPUT
Hình 11.3 Moät heä thoáng vôùi caùc quan heä-beân trong cuûa caùc thöïc theå
Theo nhö teân goïi, moâ hình höôùng-ñoái töôïng ñaët ñeå taàm quan troïng nhaát vaøo caùc ñoái
töôïng ñoù laø tính ñoùng goùi döõ lieäu vaø haøm. Chuùng ñoùng vai troø trung taâm trong moïi
giai ñoaïn cuûa phaùt trieån phaàn meàm vaø do ñoù seõ toàn taïi ôû möùc cao söï goái leân nhau
(overlap) vaø söï laëp ñi laëp laïi (iteration) giöõa caùc giai ñoaïn. Tieán trình phaùt trieån toaøn
theå trôû thaønh söï tieán hoaù nhö trong töï nhieân. Baát kyø moät bieåu dieãn ñoà hoaï naøo cuûa
caùc phieân baûn höôùng-ñoái töôïng cuûa chu kyø phaùt trieån phaàn meàm ñeàu phaûi löu taâm
ñeán hai khía caïnh goái leân nhau vaø vaø söï laëp ñi laëp laïi. Keát quaû laø moâ hình “voøi phun
nöôùc” (fountain model) ñaõ thay theá moâ hình “thaùc nöôùc coå ñieån” (hình 11.4).
Entity
Entity
Entity
Entity
Entity
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
346
Maintenance
Further
development
Application
Object-oriented
OOP
Objects
programming in
program
Object-oriented
OOD
Objects
design
in solution space
Object-oriented
OOA
Objects
analysis
in problem space
Hình 11.4 Moâ hình “voøi phun nöôùc” trong phaùt trieån
phaàn meàm höôùng-ñoái töôïng
Phaân tích höôùng-ñoái töôïng
(OOA) coù lieân quan ñeán caùc phöông phaùp cuûa caùc yeâu
caàu ñaëc taû cuûa phaàn meàm theo thuaät ngöõ caùc ñoái töôïng cuûa theá giôùi thöïc, caùc haønh vi
öùng xöû vaø caùc töông taùc cuûa chuùng.
Thieát keá höôùng-ñoái töôïng
(OOD) chuyeån nhöõng yeâu caàu cuûa phaàn meàm sang nhöõng
ñaëc taû cho ñoái töôïng vaø caùc lôùp daãn xuaát phaân caáp töø ñoù caùc ñoái töôïng seõ ñöôïc taïo ra.
Laäp trình höôùng-ñoái töôïng
(OOP) coù lieân quan ñeán caøi ñaët chöông trình trong moät
ngoân ngöõ laäp trình höôùng ñoái töôïng nhö C++.
Töông phaûn vôùi caùch tieáp caän phaân raõ chöùc naêng top-down, tieáp caän höôùng ñoái töôïng
söû duïng caùc thieát keá top-down laãn bottom-up. Kyõ thuaät phaân raõ chöùc naêng töø treân
xuoáng coù theå aùp duïng ñeå thieát keá caùc lôùp rieâng leõ trong khi heä thoáng cuoái coù theå
ñöôïc xaây döïng vôùi söï trôï giuùp caùc modun lôùp söû duïng tieáp caän töø döôùi leân.
Problem
space Objects
defined
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
347
in
problem
space
during
analysis
!
!
!
!
!
!
! ! Solution
specific
objects
defined
! ! !
during
design
Solution space
Hình 11.5 Caùc taàng cuûa caùc ñaëc taû ñoái töôïng
V/ Caùc kyù hieäu vaø ñoà thò höôùng ñoái töôïng
Caùc kyù hieäu ñoà hoaï (graphical notations) laø phaàn khoâng theå thieáu cuûa baát kyø quaù
trình thieát keá vaø phaùt trieån naøo, thieát keá höôùng ñoái töôïng cuõng vaäy. Chuùng ta caàn caùc
kyù hieäu ñeå bieåu dieãn caùc lôùp, caùc ñoái töôïng, caùc lôùp con, vaø moái quan heä qua laïi cuûa
chuùng. Thaät khoâng may, khoâng coù caùc kyù hieäu chuaån ñeå bieåu dieãn caùc ñoái töôïng vaø
caùc töông taùc uûua chuùng. Moãi taùc giaû vaø caùc nhaø nghieân cöùu ñeàu coù caùch kyù hieäu
rieâng cuûa mình. Döôùi ñaây laø moät soá kyù hieäu thoâng duïng , töø hình 11.6 ñeán 11.14
1. lôùp vaø ñoái töôïng
2. caùc theå hieän cuûa ñoái töôïng
3. message truyeàn thoâng giöõa caùc ñoái töôïng
4. quan heä keá thöøa
5. quan heä phaân loaïi
6. quan heä hôïp thaønh
7. bieåu ñoà phaân caáp thöù baäc
8. quan heä client-server
9. caùc tieán trình
Classname
Classname
Classname
Function 1
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
348
Functions
Data
Data
Functions
(a)
(b)
(c)
Hình 11.6 Caùc daïng khaùc nhau duøng bieåu dieãn lôùp/ñoái töôïng
Person Class
is-a
is-a
is-a
John
Hung
Ahmed
objects
Hình 11.7 Caùc theå hieän cuûa caùc ñoái töôïng
Object A
Object B
Hình 11.8 message truyeàn thoâng giöõa caùc ñoái töôïng
A
Base
class
Function 2
Function 3
data
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
349
B
Derived class
Hình 11.9 quan heä keá thöøa
Vehicle
a-kind-of
Car
Cycle
(a)
Vehicle
Car
Cycle
(b)
Hình 11.10
quan heä phaân loaïi
House
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
350
a-part-of
Door
Window
(a)
House
Door
Window
(b)
Hình 11.11
quan heä hôïp thaønh
A
B C D
B1 B2
Hình 11.12
bieåu ñoà phaân caáp thöù baäc
X
Y
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
351
Server
Client
Hình 11.13
quan heä client-server
Process
A
Process
B
Process
C
Process
D
Hình 11.14
caùc tieán trình
(moät tieán trình coù theå coù töø 5 ñeán 7 ñoái töôïng tieâu bieåu)
VI/ Caùc böôùc trong phaân tích höôùng ñoái töôïng
Phaân tích höôùng ñoái töôïng (OOA) cung caáp cho chuùng ta moät cô cheá ñôn giaûn nhöhg
ñaày söùc maïnh ñeå nhaän bieát caùc ñoái töôïng, caùc khoái xaây döïng (the buiding blocks) cuûa
phaàn meàm ñaõ ñöôïc phaùt trieån.
Vieäc phaân tích coù lieân quan veà cô baûn ñeán söï phaân raõ cuûa vaán ñeà thaønh caùc boä phaän
caáu thaønh (component parts) cuûa noù vaø thieát laäp moät moâ hình logic nhaèm moâ taû caùc
chöùc naêng cuûa heä thoáng.
Tieáp caän phaân tích höôùng ñoái töôïng goàm coù caùc böôùc sau ñaây :
1. Hieåu vaø naém vöõng vaán ñeà
2. Phaùc thaûo nhöõng ñaëc taû yeâu caàu cuûa ngöôøi duøng vaø cuûa phaàn meàm
3. Nhaän bieát caùc ñoái töôïng vaø caùc thuoäc tính cuûa chuùng
4. Nhaän bieát caùc dòch vuï trong ñoù moãi ñoái töôïng ñöôïc mong ñôïi cung caáp (giao
dieän)
5. Thieát laäp caùc quan heä noái lieàn vôùi nhau (coäng taùc - collaborations) giöõa caùc ñoái
töôïng döôùi daïng caùc dòch vuï ñöôïc yeâu caàu vaø caùc dòch vuï ñaùp laïi (services
rendered) .
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
352
Maëc duø, chuùng ta ñaõ chæ ra caùc taùc vuï nhö moät taäp caùc böôùc rieâng leû, ba böôùc cuoái
ñöôïc thöïc hieän phuï thuoäc laãn nhau nhö hình 11.15
Problem
definition
Requirement
specifications
Objects
in
problem
space
Identify
Objects
Identify
services
Identify
collaborations
Design
Hình 11.15 Caùc hoaït ñoäng cuûa phaân tích höôùng ñoái töôïng
1/ Hieåu vaø naém vöõng vaán ñeà
(problem understanding)
Phaùt bieåu vaán ñeà phaûi roõ raøng vaø xaùc ñònh laïi döôùi daïng coâng ngheä heä thoáng maùy
tính sao cho gôïi yù ra nhöõng lôøi giaûi döïa treân maùy tính. Phaùt bieåu vaán ñeà cung caáp cô
sôû cho vieäc phaùc thaûo ñaëc taû caùc yeâu caàu cuûa caû ngöôøi duøng laãn phaàn meàm.
2/ Ñaëc taû caùc yeâu caàu
(requirements specification)
Moät khi vaán ñeà ñöôïc xaùc ñònh roõ raøng, böôùc tieáp theo seõ bieát ñöôïc ñieàu gì heä thoáng
ñöôïc yeâu caàu thöïc hieän. Ñieàu quan troïng ôû giai ñoaïn naøy laø taïo cho ñöôïc moät danh
saùch caùc yeâu caàu cuûa ngöôøi duøng. Moät söï hieåu bieát thoâng suoát phaûi coù giöõa ngöôøi
duøng vaø nhaø phaùt trieån (developer) vôùi caùi gì ñöôïc yeâu caàu. Döïa treân nhöõng yeâu caàu
cuûa ngöôøi duøng, caùc ñaëc taû cho phaàn meàm seõ ñöôïc phaùc thaûo. Nhaø phaùt trieån phaûi
dieãn ñaït heát söùc roõ raøng (what) :
•
Caùc ñaàu ra (outputs) ñöôïc yeâu caàu laø gì
•
Caùc tieán trình naøo ñöôïc goïi ñeå cho ra caùc ñaàu ra ñoù
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
353
•
Nhöõng ñaàu vaøo (inputs) caàn thieát ñoù laø gì
•
Nhöõng taøi nguyeân naøo ñöôïc yeâu caàu
Nhöõng ñaëc taû naøy thöôøng duøng nhö moät tham khaûo ñeå kieåm nghieäm saûn phaåm cuoái
nhaèm thöïc thi caùc taùc vuï mong ñôïi.
3/ Nhaän bieát caùc ñoái töôïng
(Identication of objects)
Caùc ñoái töôïng thöôøng ñöôïc nhaän bieát duôùi daïng caùc ñoái töôïng theá giôùi thöïc hôn laø
caùc ñoái töôïng tröøu töôïng. Do ñoù, nôi toát nhaát ñeå xem xeùt caùc ñoái töôïng laø ngay chính
öùng duïng. ÖÙng duïng coù theå ñöôïc phaân tích baèng caùch söû duïng moät trong hai tieáp caän
sau ñaây :
•
Caùc löôïc ñoà doøng döõ lieäu (DFD – Data flow diagrams)
•
Phaân tích theo nguyeân baûn (TA – Textual analysis)
a/ Löôïc ñoà doøng döõ lieäu
Moät öùng duïng coù theå bieåu dieãn döôùi daïng DFD chæ cho thaáy döõ lieäu seõ ñöôïc löu
chuyeån töø nôi naøy ñeán nôi khaùc trong heä thoáng. Caùc kyù hieäu hoäp (boxe) vaø khung
löu tröõ döõ lieäu (data store) trong DFD laø nhöõng öùng vieân toát cho bieåu dieãn caùc ñoái
töôïng.
Tieán trình noåi boït “bubbles” seõ töông öùng vôùi caùc thuû tuïc. Hình 11.16 minh hoaï moät
löôïc ñoà doøng döõ lieäu ñieån hình. Noù cuõng ñöôïc bieát ñeán nhö moät ñoà thò doøng döõ lieäu
(data flow graph) hoaëc moät bieåu ñoà noåi boït (bubble chart)
Bookseller
: nguôøi baùn saùch
Order
: ñôn ñaët haøng
Process order
: xöû lyù ñôn ñaët haøng
Shipping instructions : chæ thò/lôøi chæ daãn veà vaän chuyeån haøng baèøng ñuôøng thuûy
Stores/ Warehouse : cöûa haøng/ kho haøng
Check credit status : kieåm tra tình traïng cuûa theû tín duïng
Shipment information : thoâng tin veà vieäc gôûi haøng leân taøu thuûy
Shipping notice
: lôøi baùo tröôùc/thôøi haïn veà vaän chuyeån haøng baèøng ñuôøng thuûy
Data store
Books database
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
354
boxe
Shipping
Bookseller
Order
Process
order
instructions
Stores
Check credit status
Data store Customer
database
Shipping
notice
Shipment information
Collect
customer
order
Hình 11.16 DFD cho xöû lyù ñôn ñaët haøng vaø vaän chuyeån haøng cho cty saùch
Moät DFD coù theå ñöôïc söû duïng ñeå bieåu dieãn moät heä thoáng ôû baát kyø möùc tröøu töôïng
naøo. Laáy ví duï, DFD ñöôïc chæ ra ôû hình 11.16 coù theå môû roäng ñeå bao goàm nhieàu
thoâng tin hôn nöõa (nhö caùc chi tieát traû tieàn) hoaëc coâ ñoïng laïi nhö minh hoaï trong hình
11.17 ñeå trình baøy chæ cho moät noåi boït.
Order
Instructions
Hình 11.17 Löôïc ñoà doøng döõ lieäu cô sôû
b/ Phaân tích theo nguyeân baûn
Tieáp caän naøy döïa treân söï moâ taû nguyeân baûn cuûa vaán ñeà hoaëc lôøi giaûi ñöôïc ñeà xuaát.
Moâ taû naøy coù theå laø moät trong hai caâu hoaëc moät trong hai ñoaïn tuøy thuoäc vaøo kieåu vaø
söï phöùc taïp cuûa vaán ñeà. Caùc danh töø laø nhöõng boä chæ thò (indicator) toát cuûa caùc ñoái
töôïng. Caùc teân coù theå ñöôïc phaân loaïi hôn nöõa nhö caùc danh töø chính xaùc (proper
nouns
), caùc danh töø chung (common nouns), vaø caùc danh töø soá nhieàu (mass nouns)
hoaëc caùc danh töø tröøu töôïng (abstract nouns). Baûng 11.3 chæ cho thaáy caùc kieåu khaùc
nhau cuûa caùc danh töø vaø yù nghóa cuûa chuùng
Customer
Process order
Warehouse
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
355
Type of noun
Meaning
Examples
Commun
noun
Describe classes of things
(entities)
Vehicle, customer, income
(lôïi töùc), deduction
Proper noun
Names of specific things
Maruti car, John,
ABC Company
Mass or
abstract
noun
Describe a quality,
quantity or an activity
associated with a noun
Salary-income,
House-loan, feet,
traffic
Baûng 11.3 Caùc kieåu cuûa caùc danh töø
Ñieàu quan troïng caàn chuù yù laø ngöõ caûnh vaø ngöõ nghóa phaûi ñöôïc söû duïng ñeå xaùc ñònh
caùc loaïi danh töø. Moät töø ñaëc thuø coù yù nghóa laø moät danh töø chung trong ngöõ caûnh naøy
vaø moät danh töø soá nhieàu hoaëc moät danh töø tröøu töôïng trong ngöõ caûnh khaùc.
Caùc tieáp caän naøy chæ laø moät söï höôùng daãn vaø khoâng phaûi laø caùc coâng cuï cuoái cuøng.
Söï nhaän thöùc saùng taïo vaø khaû naêng tröïc giaùc cuûa caùc nhaø phaùt trieån coù kinh nghieäm
ñoùng moät vai troø quan troïng trong vieäc nhaän bieát caùc ñoái töôïng.
Ñeå söû duïng moät trong nhöõng caùch tieáp caän treân, caàn chuaån bò moät danh saùch caùc ñoái
töôïng cho vaán ñeà öùng duïng. Ñieàu naøy phaûi bao goàm nhöõng taùc vuï sau :
1. Chuaån bò moät baûng ñoái töôïng
2. Nhaän bieát nhöõng ñoái töôïng coù lieân quan ñeán khoâng gian lôøi giaûi vaø nhöõng ñoái
töôïng chæ lieân quan ñeán khoâng gian vaán ñeà (the problem space) . Caùc ñoái töôïng
cuûa khoâng gian vaán ñeà seõ ôû beân ngoaøi phaïm vi cuûa phaàn meàm.
3. Nhaän bieát nhöõng thuoäc tính cuûa caùc ñoái töôïng khoâng gian lôøi giaûi (the
solution space objects
).
4/ Nhaän bieát caùc dòch vuï
Moät khi caùc ñoái töôïng trong khoâng gian lôøi giaûi ñaõ ñöôïc nhaän bieát, böôùc tieáp theo laø
nhaän bieát moät taäp hôïp caùc dòch vuï trong ñoù moãi ñoái töôïng töông öùng phaûi ñöôïc ñeà
nghò.
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
356
Caùc dòch vuï ñöôïc nhaän bieát baèng caùch thaåm tra moïi ñoäng töø vaø caùc thaønh ngöõ ñoäng
töø trong phaùt bieåu moâ taû vaán ñeà. Caùc ñoäng töø ñoù coù theå dieãn ñaït caùc haønh ñoäng hoaëc
nhöõng bieán coá coù theå ñöôïc phaân loaïi theo baûng 11.4 sau
Type of verb
Meaning
Examples
Doing verbs
Operations
read, get, display, buy
Being verbs
Classifications
is an, belongs to
Having verbs composition
has an, is part of
Compare
vebs
Operations
is less than,
is equal to
Stative vebs Invariance-condition
to be present, are owned
Baûng 11.4 Phaân loaïi caùc ñoäng töø
5/ Thieát laäp caùc quan heä coäng taùc
Böôùc naøy nhaän bieát caùc dòch vuï maø caùc ñoái töôïng cung caáp vaø thu nhaän (receive) .
Coù theå duøng löôïc ñoà doøng thoâng tin IFD (information flow diagram) hoaëc löôïc ñoà
quan heä-thöïc theå ERD (entity-relationship diagram) ñeå thu ñöôïc thoâng tin naøy. ÔÛ
ñaây chuùng ta phaûi thieát laäp moái töông quan giöõa caùc dòch vuï vaø thoâng tin hieän taïi
(caùc messages) baèng caùch truyeàn thoâng.
VII/ Caùc böôùc thieát keá höôùng ñoái töôïng
Thieát keá coù lieân quan ñeán vieäc aùnh xaï cuûa caùc ñoái töôïng trong khoâng gian vaán ñeà
sang caùc ñoái töôïng trong khoâng gian lôøi giaûi vaø taïo ra moät caáu truùc toång theå (moâ hình
kieán truùc) vaø caùc moâ hình tính toaùn cuûa heä thoáng.
Giai ñoaïn naøy thöôøng duøng caùch tieáp caän bottum-up ñeå xaây döïng caáu truùc cuûa heä
thoáng vaø tieáp caän phaân raõ chöùc naêng top-down ñeå thieát keá caùc haøm thaønh vieân cuûa
lôùp maø chuùng cung caáp caùc dòch vuï. Ñoù laø ñieàu heát söùc quan troïng ñeå xaây döïng caáu
truùc phaân caáp, ñeå nhaän bieát caùc lôùp tröøa töôïng, vaø ñeå ñôn giaûn hoaù nhöõng truyeàn
thoâng (lieân laïc) beân trong ñoái töôïng (the inter-object communications)
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
357
Vieäc söû duïng laïi caùc lôùp töø caùc thieát keá tröôùc ñoù, phaân loaïi caùc ñoái töôïng vaøo caùc heä
thoáng con vaø xaùc ñònh caùc giao thöùc thích hôïp seõ laø moät soá caùc quan taâm cuûa giai
ñoaïn thieát keá.
Tieáp caän thieát keá höôùng ñoái töôïng coù theå bao goàm caùc böôùc sau :
1. Xem xeùt caùc ñoái töôïng ñaõ taïo ra trong pha phaân tích
2. Ñaëc taû caùc phuï thuoäc lôùp (class dependencies)
3. Toå chöùc söï phaân caáp lôùp
4. Thieát keá caùc lôùp
5. Thieát keá caùc haøm thaønh vieân
6. thieát keá chöông trình qua moät ngoân ngöõ laäp trình cuï theå
1/ Xem xeùt caùc ñoái töôïng trong khoâng gian vaán ñeà
Moät vaøi höôùng daãn giuùp tieán trình xem xeùt ñoù laø :
1. Neâùu chæ moät ñoái töôïng laø caàn thieát cho moät dòch vuï (hoaëc moät hoaït ñoäng), thì
noù thao taùc chæ treân ñoái töôïng ñoù.
2. Neáu coù hai hoaëc nhieàu ñoái töôïng ñöôïc yeâu caàu cho moät hoaït ñoäng ñang dieãn
ra, thì noù caàn nhaän bieát phaàn vieäc rieâng cuûa ñoái töôïng naøo phaûi ñöôïc nhaän ra
ñeå haønh ñoäng.
3. Neáu moät hoaït ñoäng yeâu caàu söï hieåu bieát nhieàu hôn moät kieåu naøo ñoù cuûa caùc
ñoái töôïng, thì hoaït ñoäng khoâng dính líu veà maët chöùc naêng vaø caàn phaûi loaïi boû.
Aùp duïng caùc höôùng daãn naøy seõ giuùp chuùng ta tinh loïc caùc dòch vuï cuûa caùc ñoái töôïng.
Hôn nöõa, caùc ñoái töôïng dö thöøa vaø khoâng lieân quan seõ ñöôïc boû ñi, caùc dòch vuï coù
cuõng nghóa ñöôïc keát hôïp laïi vaø caùc teân cuûa caùc thao taùc (caùc haøm) ñöôïc caûi tieán
nhaèm bieåu hieän trong saùng caùc daïng xöû lyù ñöôïc yeâu caàu.
2/ Caùc phuï thuoäc lôùp
Phaân tích caùc quan heä giöõa caùc lôùp laø trung taâm cuûa caáu truùc moät heä thoáng. Do ñoù,
noù quan troïng ñeå nhaän bieát caùc lôùp thích hôïp ñeå bieåu dieãn caùc ñoái töôïng trong khoâng
gian lôøi giaûi vaø thieát laäp moái quan heä cuûa chuùng. Nhöõng quan heä chuû yeáu ñoùng vai
troø quan troïng trong ngöõ caûnh cuûa thieát keá ñoù laø :
1. quan heä keá thöøa
2. quan heä bao haøm
3. quan heä söû duïng
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
358
a/ Quan heä keá thöøa laø moái quan heä cao nhaát coù theå ñöôïc bieåu dieãn trong C++. Ñoù laø
caùch bieåu dieãn ñaày naêng löïc veà moái quan heä phaân caáp thöù baäc tröïc tieáp. Neáu xem
hình 11.12 minh hoïa lôùp cô sôû A vaø caùc lôùp keá thöøa cuûa noù thì baûng quan heä keá thöøa
seõ ñöôïc chæ ra ôû baûng 11.5 nhö sau :
Class
Depends
on
A
-
B
A
C
A
D
A
B1
B
B2
B
Baûng 11.5 Baûng quan heä keá thöøa
b/ Quan heä bao haøm coù nghóa laø duøng moät ñoái töôïng cuûa lôùp nhö laø thaønh vieân cuûa
lôùp khaùc. Ñaây laø kyõ thuaät “daâng taëng” vaø kyõ thuaät loaïi tröø ñeå duøng keá thöøa lôùp.
Nhöng noù thöôøng ñoøi hoûi söï kheùo leùo ñeå choïn löïa giöõa hai kyõ thuaät.
Thoâng thöôøng, neáu caàn ñeå quaù taûi caùc thuoäc tính hoaëc caùc haøm, thì keá thöøa laø söï löïa
choïn laø toát nhaát. Maët khaùc, neáu chuùng ta muoán bieåu dieãn moät ñaëc tính bôûi söï ña daïng
cuûa caùc kieåu, thì quan heä bao haøm laø phöông phaùp caàn ñeán. Moät luùc naøo ñoù chuùng ta
caàn duøng moät ñoái töôïng nhö moät thaønh vieân thì khi ñoù chuùng ta caàn gôûi moät thuoäc
tính cuûa lôùp nhö moät ñoái soá ñeán haøm taïo cuûa lôùp khaùc. Lôùp “khaùc” phaûi coù moät ñoái
töôïng thaønh vieân ñöôïc bieåu dieãn nhö ñoái soá.
Tính keá thöøa bieåu dieãn quan heä is_a vaø quan heä bao haøm bieåu dieãn quan heä has_a .
c/ Quan heä söû duïng
Ví duï, lôùp A coù theå duøng lôùp B vaø C qua moät vaøi caùch
A ñoïc (reads) moät thaønh vieân cuûa B
A goïi (calls) moät thaønh vieân cuûa C
A taïo ra (creates) B söû duïng toaùn töû new
Söï hieåu bieát veà caùc quan heä nhö theá laø quan troïng ñeå thieát keá moät chöông trình.
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
359
3/ Toå chöùc söï phaân caáp thöù baäc lôùp
bao goàm söï nhaän bieát caùc thuoäc tính vaø caùc
haøm chung nhaát giöõa moät nhoùm caùc lôùp coù quan heä nhau vaø keát hôïp chuùng vaøo daïng
moät lôùp môùi naøo ñoù. Lôùp môùi naøy seõ phuïc vuï nhö moät sieâu lôùp (super class) vaø
nhöõng lôùp khaùc nhö laø caùc lôùp phuï thuoäc (vôùi nhöõng thuoäc tính daãn xuaát töø sieâu lôùp).
Lôùp môùi coù theå hoaëc khoâng theå coù yù nghóa cuûa ñoái töôïng bôûi chính noù. Neáu moät ñoái
töôïng ñöôïc taïo ra thuaàn tuùy ñeå keát hôïp caùc thuoäc tính chung, noù ñöôïc goïi laø lôùp tröøu
töôïng.
Tieán trình naøy coù theå laëp laïi ôû caùc möùc khaùc nhau cuûa söï tröøu töôïng vôùi moät muïc
ñích duy nhaát cuûa vieäc baønh tröôùng caùc lôùp.
Ví duï hình 11.18 minh hoïa tieán trình laëp hai möùc.
A
B X Y
C
D
E
A B C D E
(a) Caùc ñoái töôïng trong
(b) Caây phaân caáp möùc thöù nhaát
khoâng gian lôøi giaûi
Z
X Y
A B C D E
(c) Caây phaân caáp möùc thöù hai
Hình 11.18 Caùc möùc cuûa phaân caáp thöù baäc lôùp
Tieán trình cuûa toå chöùc lôùp coù theå keát quaû cuoái cuøng trong moät moâ hình caây ñôn
(single-tree model) hoaëc moâ hình röøng caây (forest). Hình 11.19
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
360
4/ Thieát keá caùc lôùp
Chuùng ta ñaõ nhaän bieát caùc lôùp, caùc thuoäc tính cuûa noù, vaø moät taäp hôïp toái thieåu caùc
thao taùc ñöôïc yeâu caàu qua khaùi nieäm moät lôùp ñöôïc bieåu dieãn. Baây giôø chuùng ta haõy
xem xeùt caùc chi tieát ñaày ñuû maø moãi lôùp bieåu dieãn. Vaán ñeà quan troïng laø quyeát ñònh
nhöõng haøm naøo ñeå xaây döïng lôùp. Vôùi moät lôùp thoâng thöôøng, caàn coù caùc haøm thöïc
hieän caùc chöùc naêng sau ñaây :
(a) moâ hình caây ñôn
(b) moâ hình röøng caây
Hình 11.19 Toå chöùc caùc lôùp
1. caùc haøm quaûn lyù lôùp
•
moät ñoái töôïng ñöôïc taïo ra nhö theá naøo ?
•
moät ñoái töôïng ñöôïc huûy nhö theá naøo ?
2. caùc haøm thöïc thi lôùp
•
nhöõng thao taùc naøo seõ ñöôïc thöïc hieän treân kieåu döõ lieäu cuûa lôùp ?
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
361
3. caùc haøm truy xuaát lôùp
•
chuùng ta seõ laáy thoâng tin töø caùc bieán beân trong cuûa lôùp nhö theá naøo ?
4. caùc haøm tieän ích lôùp
•
chuùng ta seõ xöû lyù loãi nhö theá naøo ?
Moät vaán ñeà nöõa caàn xem xeùt ñeán :
1. Loaïi ñieàu khieãn truy xuaát naøo ñöôïc yeâu caàu cho lôùp cô sôû ?
2. Caùc haøm naøoseõ laø haøm aûo ?
3. Caùc lôùp thö vieän naøo seõ duøng trong moät lôùp ?
Vieäc thieát keá caùc lôùp rieâng leõ coù aûnh huôûng khaù lôùn ñeán chaát löôïng cuûa phaàm meàm.
Sau ñaây laø moät vaøi nguyeân taéc chæ ñaïo ñöôïc duøng ñeå xem xeùt trong khi thieát keá moät
lôùp :
1. giao tieáp chung cuûa lôùp chæ giao cho moät haøm cuûa lôùp.
2. moät ñoái töôïng cuûa moät lôùp khoâng theå gôûi message tröïc tieáp ñeán thaønh vieân
cuûa lôùp khaùc.
3. moät haøm ñöôïc khai baùo laø public chæ khi naøo noù ñöôïc ñoøi hoûi söû duïng bôûi caùc
ñoái töôïng cuûa lôùp.
4. moãi haøm truy xuaát, thay ñoåi hoaëc caû hai ñeán moät vaøi döõ lieäu cuûa lôùp maø noù
bieåu dieãn.
5. moät lôùp coù theå phuï thuoäc vaøo moät vaøi lôùp khaùc neáu coù theå.
6. söï töôngtaùc giöõa caùc lôùp phaûi töôøng minh.
7. moãi lôùp phuï thuoäc (subordinate class) phaûi ñöôïc thieát keá nhö moät söï chuyeân
moân hoaù cuûa lôùp cô sôû vôùi moät muïc ñích duy nhaát boå sung caùc ñaëc tính phuï.
8. lôùp treân cao nhaát cuûa moät caáu truùc neân bieåu dieãn nhö moâ hình lôùp tröøu töôïng.
5/ Thieát keá caùc haøm thaønh vieân
Ñeán ñaây chuùng ta ñaõ nhaän bieát ñöôïc :
1. Caùc lôùp vaø caù ñoái töôïng
2. caùc thaønh vieân döõ lieäu
3. caùc giao dieän
4. caùc phuï thuoäc vaø
5. phaân caáp thöù baäc lôùp
Luùc naøy caàn xem xeùt vieäc thieát keá caùc haøm thaønh vieân. Caùc haøm thaønh vieân ñònh
nghóa caùc thao taùc duøng ñeå thöïc hieän treân döõ lieäu cuûa ñoái töôïng. Caùc haøm naøy cuõng
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
362
gioáng nhö baát kyø caùc haøm ngoân ngöõ C vaø do ñoù chuùng ta coù theå söû duïng kyõ thuaät
phaân raõ chöùc naêng top-down ñeå thieát keá chuùng nhö chæ ra trong hình 11.20
Chuùng ta cuõng coù theå aùp duïng caùc kyõ thuaät thieát keá caáu truùc (structured design) cho
moãi modun. Caùc kyõ thuaät thieát keá caáu truùc cô sôû ñöôïc hoå trôï bôûi C++ ñöôïc chæ ra ôû
hình 11.21. Chuùng ta coù theå thöïc thi chuùng trong keát hôïp baát kyø naøo vaø keå caû söû
duïng khaùi nieäm moät-ñaàu vaøo, moät-ñaàu ra (one-entry, one-exit) .
Hình 11.20 Thieát keá top-down cuûa caùc haøm
Function
1
Data
Function
2
Object
A
B C D
B1 B2 D1 D2
B12
D12
Modules of function 2
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
363
Hình 11.21 Caùc kyõ thuaät thieát keá caáu truùc
Entry
Task
1
Task
2
Task
3
Exit
(a)
Sequence
Entry
True
False
Test
Task
1
Task
2
Exit
(b)
Selection
Entry
Test
Task
Exit
(c)
Loop
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
364
6/ Thieát keá chöông trình qua moät ngoân ngöõ laäp trình cuï theå
Moãi chöông trình C++ phaûi bao goàm maõ haøm main() ñöôïc goïi laø chöông trình ñieàu
khieån (driver program) Thöïc thi chöông trình baét ñaàu vaø keát thuùc ôû ñaây. Chöông
trình ñieàu khieån chòu traùch nhieäm chính veà :
1. nhaän caùc döõ lieäu töø ngöôøi duøng
2. taïo caùc ñoái töôïng töø nhöõng ñònh nghóa lôùp
3. saép seáp söï truyeàn thoâng giöõa caùc ñoái töôïng nhö moät söï tuaàn töï caùc message ñeå
goïi caùc haøm thaønh vieân
4. hieån thò keát quaû xuaát theo daïng thöùc cuûa ngöôøi duøng yeâu caàu
Moïi hoaït ñoäng bao goàm xöû lyù trong khi thöïc thi keát quaû chöông trình ñeàu töø nhöõng
taùc ñoäng laãn nhau cuûa caùc ñoái töôïng. Moät thieát keá chính yeáu quyeát ñònh thöïc hieän thöù
töï logic cuûa caùc message gôûi ñeán.
Chöông trình ñieàu khieån laø coång noái vôùi ngöôøi duøng. Do ñoù, thieát keá giao dieän ngöôøi
duøng caàn phaûi caân nhaéc thích ñaùng trong khi thieát keá chöông trình. Heä thoáng ñöôïc
thieát keá sao cho coù tính thaân thieän ñeå ngöôøi duøng thao taùc ñöôïc töï nhieân vaø thoaûi maùi
nhaát.
VIII/ Caøi ñaët
Caøi ñaët (implementation) bao goàm maõ hoaù vaø kieåm nghieäm. Maõ hoaù (coding) goàm coù
vieát maõ leänh cho caùc lôùp, haøm thaønh vieân vaø chöông trình main() giöõ nhieäm vuï ñieàu
khieån trong chöông trình. Vieäc maõ hoaù trôû neân deã daøng khi vieäc thieát keá chi tieát ñaõ
ñöôïc thöïc hieän heát söùc caån thaän.
Khoâng moät chöông trình naøo coù theå laøm vieäc toát trong laàn ñaàu tieân. Vì vaäy vieäc kieåm
nghieäm (testing) chöông trình tröôùc khi duøng laø phaàn thieát yeáu cuûa tieán trình phaùt
trieån phaàn meàm. Keá hoaïch kieåm nghieäm chi tieát phaûi ñöôïc phaùc thaûo laø kieåm
nghieäm caùi gì, khi naøo vaø nhö theá naøo. Caùc giao tieáp lôùp caùc phuï thuoäc lôùp laø nhöõng
khía caïnh qua n troïng cuûa vieäc kieåm nghieäm. Muïc ñích cuoái cuøng cuûa kieåm nghieäm
laø xem xeùt heä thoáng thöïc thi nhöõng coâng vieäc ñònh truôùc coù laøm thoaû maõn hay khoâng.
IX/ Moâ hình nguyeân maãu (prototyping paradigm)
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
365
Haàu heát caùc baøi toaùn öùng duïng trong theá giôùi thöïc ñeàu phöùc taïp vaø do ñoù caáu truùc
cuûa heä thoáng trôû neân quaù lôùn ñeå thöïc hieän caùc yeâu caàu chính xaùc luùc ban ñaàu. Moät
vaøi thaønh phaàn chæ bieát ñöôïc roõ raøng luùc chuùng ta xaây döïng vaø kieåm nghieäm heä
thoáng. Sau khi moät heä thoáng ñoà soä ñöôïc hoaøn thaønh, vieäc hôïp nhaát caùc ñaëc ñieãm coù
theå daãn ñeán vieäc “thieáu soùt“ chuùng luùc kieåm nghieäm hoaëc caùc giai ñoaïn cuûa öùng
duïng phaûi traû giaù ñaét vaø tieâu toán quaù nhieàu thôøi gian. Caùch toát nhaát ñeå am hieåu thieát
keá heä thoáng vaø phaân chia chuùng tröôùc khi xaây döïng heä thoáng hoaøn chænh ñoù laø xaây
döïng vaø kieåm nghieäm moät moâ hình laøm vieäc cuûa heä thoáng ñöôïc ñeà xuaát. Moät heä
thoáng moâ hình ñöôïc bieát roäng raõi nhö moät nguyeân maãu (prototype) vaø söï tieán haønh
ñöôïc goïi laø prototyping. Töø khi caùch tieáp caän phaân tích vaø thieát keá höôùng ñoái töôïng
ñöôïc giôùi thieäu, noù trôû neân phuø hôïp nhaát ñoái vôùi moâ hình nguyeân maãu (prototyping
paradigm
) ñöôïc minh hoïa trong hình 11.22
Hình 11.22 moâ hình nguyeân maãu
Moät nguyeân maãu laø moät phieân baûn keát vaûy haï thaáp daàn (scaled down) cuûa heä thoáng
vaø coù theå khoâng coù tieâu chuaån thöïc thi nghieâm ngaët vaø caùc yeâu caàu taøi nguyeân. Caùc
System
Specifications
Outline
requirements
Design
prototype
model
Build
Prototype
Make
detailed
design
Full
System
Evaluate
prototype
performance
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
366
nhaø phaùt trieån vaø caùc khaùch haøng ñoàng yù theo caùc “ñaëc taû ñöôøng neùt ñaïi cöông”
(outline specifications) cuûa heä thoáng vaø thieát keá nguyeân maãu ñöôïc ñeà nghò vôùi caùc
yeâu caàu ñöôøng neùt ñaïi cöông vaø caùc taøi nguyeân coù theå coù. Nguyeân maãu seõ ñöôïc xaây
döïng vaø ñaùnh giaù. Ñieàu quan taâm chính khoâng phaûi laø nguyeân maãu maø laø söï thöïc thi
cuûa chuùng duøng ñeå tinh chænh caùc ñaëc taû yeâu caàu.
Caùc nguyeân maãu cung caáp moät cô hoäi ñeå thöû nghieäm vaø phaân tích caùc khía caïnh
khaùc nhau cuûa heä thoáng nhö caáu truùc heä thoáng, thieát keá beân trong, caùc yeâu caàu phaàn
cöùng vaø caùc yeâu caàu heä thoáng cuoái cuøng. Lôïi ích cuûa caùch tieáp caän nguyeân maãu laø :
1. Chuùng ta coù theå trình dieãn caùc ñaëc taû coù theå hieåu ñöôïc, chuùng hôïp lyù vaø ñaày
ñuû ñeå coù theå chaáp nhaän ñöôïc.
2. Ngöôøi duøng coù theå hieåu ñöôïc ñieàu gì ñaõ xaûy ra.
3. Nhöõng thay ñoåi veà baûo trì ñöôïc yeâu caàu laø toái thieåu khi heä thoáng ñaõ caøi ñaët
roài.
4. Caùc kyõ sö phaùt trieån coù theå laøm vieäc töø moät taäp hôïp caùc ñaëc taû maø chuùng ñaõ
ñöôïc kieåm nghieäm vaø chaáp thuaän.
Prototype coù theå nghóa laø ñaõ qua kinh nghieäm. Thöôøng haàu heát chuùng khoâng ñöôïc
ñieàu chænh vaøo moät saûn phaåm. Tuy nhieân, ñoâi khi coù theå ñieàu chænh moät prototype
vaøo saûn phaåm cuoái neáu söï thaän troïng thích ñaùng ñöôïc thöïc hieän trong vieäc taùi thieát
keá prototype. Caùch tieáp caän toát nhaát ñoù laø haõy vöùt boû prototype sau khi söû duïng.
X/ Toùm taét
Chuùng ta ñaõ thaûo luaän caùc khía caïnh khaùc nhau cuûa phaân tích vaø thieát keá höôùng ñoái
töôïng. Haõy nhôù raèng, ñoù khoâng phaûi laø caùch tieáp caän luoân luoân ñem laïi tính ñuùng
ñaén. Baïn phaûi xem xeùt caùc yù töôûng ñöôïc ñeà xuaát ôû chöông naøy xem noù chæ laø caùc
nguyeân taéc chæ ñaïo vaø haõy duøng nhöõng kinh nghieäm, söï ñoåi môùi, vaø söï saùng taïo cuûa
baïn trong moïi luùc coù theå.
Sau ñaây laø moät vaøi ñieåm baïn neân suy nghó vaø tieáp tuïc ñoåi môùi :
1. Thieát laäp caùc muïc ñích roõ raøng vaø thöïc teá
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
367
2. Coá gaéng duøng caùc heä thoáng ñaõ toàn taïi nhö laø caùc ví duï hoaëc moâ hình maãu ñeå
phaân tích heä thoáng cuûa baïn.
3. Söû duïng caùc lôùp ñeå bieåu dieãn caùc khaùi nieäm.
4. Haõy luoân nhôù raèng heä thoáng maø baïn taïo ra phaûi coù tính linh ñoäng, khaû chuyeån
vaø coù theå môû roäng.
5. Haõy taïo caùc söu lieäu roõ raøng cho baát cöù ñieàu gì cho heä thoáng cuûa baïn.
6. Coá gaéng söû duïng laïi caùc haøm vaø lôùp ñaõ coù saün.
7. Baûo veä vöõng chaéc caùc haøm ñaõ ñònh kieåu baát cöù luùc naøo coù theå ñöôïc.
8. Söû duïng caùc prototype baát cöù luùc naøo coù theå ñöôïc.
9. Haõy laøm cho phuø hôïp giöõa thieát keá vaø kieåu laäp trình
10. Haõy giöõ cho heä thoáng saùng suûa, ñôn giaûn, goïn nhoû vaø coù hieäu quaû
Baøi taäp chöông 11
1. Haõy lieät keâ 5 ñaëc tính quan troïng nhaát, theo yù kieán cuûa baïn, maø caùc nhaø phaùt trieån
phaàn meàm caàn löu taâm khi phaùt trieån moät heä thoáng ?
2. Haõy moâ taû taïi sao vieäc kieåm nghieäm moät phaàn meàm laø quan troïng ?
3. Theo baïn baûo trì phaàn meàm nghóa laø ? Vieäc thöïc hieän nhö theá naøo vaø luùc naøo ?
4. Ai laø “ngöôøi chôi” chính trong moãi giai ñoaïn cuûa chu kyø soáng phaùt trieån heä thoáng
?
5. Coù caàn thieát nghieân cöùu caùc heä thoáng ñaõ toàn taïi trong caùc giai ñoaïn phaân tích ?
Neáu coù, taïi sao ? Neáu khoâng, taïi sao ?
6. Nhöõng giôùi haïn cuûa chu kyø soáng phaùt trieån heä thoáng coå ñieån laø gì ?
7. Haõy thaûo luaän, “Tieán trình phaùt trieån heä thoáng laø tieán trình laëp ñi laëp laïi” .
8. Haõy phaân bieät giöõa moâ hình thaùc nöôùc vaø moâ hình voøi phun nöôùc ?
Chöông 11 Phaùt trieån heä thoáng höôùng ñoái töôïng
368
9. Haõy phaân bieät giöõa phaân tích caùc heä thoáng höôùng ñoái töôïng vaø thieát keá heä thoáng
höôùng ñoái töôïng ? Caùi naøo yeâu caàu taøi naêng saùng taïo hôn cuûa nhaø phaùt trieån heä thoáng
?
10. Haõy phaân bieät giöõa nhöõng ñieàu sau :
(a) quan heä phaân loaïi (classification) vaø quan heä hôïp thaønh (composition)
(b) quan heä keá thöøa vaø quan heä client-server
(c) Caùc ñoái töôïng trong khoâng gian vaán ñeà vaø trong khoâng gian lôøi giaûi
(d) Caùc löôïc ñoà doøng döõ lieäu vaø bieåu ñoà phaân caáp thöù baäc
11. Thaûo luaän öùng duïng veà caùc kyõ thuaät thieát keá coù caáu truùc trong laäp trình höôùng ñoái
töôïng.
12. Caùc vaán ñeà tieâu chuaån naøo ñöôïc xem xeùt trong khi thieát keá caùc chöông trình ñieàu
khieån ? Taïi sao ?
13. Giaûi thích lôøi nhaän xeùt “khoâng moät chöông trình naøo coù theå chaïy toát trong laàn
ñaàu tieân”
14. Prototyping laø gì ? Noù giuùp cho vieäc caûi tieán thieát keá heä thoáng nhö theá naøo ?
15. Caùc phaùt bieåu sau ñaây laø ñuùng hay sai :
(a) Moät söï xem xeùt quan troïng trong khi thieát keá moät heä thoáng môùi chính laø ngöôøi
duøng cuoái.
(b) Ngöôøi duøng khoâng ñoùng vai troø naøo trong phaân tích vaø thieát keá heä thoáng
(c) Moät baûng quyeát ñònh laø moät bieåu dieãn baèng hình aûnh doøng döõ lieäu
(d) MuÏc ñích söû duïng duy nhaát cuûa löôïc ñoà doøng döõ lieäu laø caùc tö lieäu
(e) Löôïc ñoà doøng döõ lieäu nhaán maïnh doøng logic cuûa döõ lieäu choáng laïi doøng vaät lyù
cuûa döõ lieäu
(f) Caùc ñaàu ra (outputs) cuûa maùy tính coù theå ñöôïc thieát keá theo aûnh höôûng mang
tính con ngöôøi
(g) Caùc kyõ thuaät laäp trình coù caáu truùc khoâng coù moät vò trí naøo trong thieát keá chöông
trình höôùng ñoái töôïng.
(h) Moät prototype khoâng theå ñöôïc caûi tieán trong moät saûn phaåm cuoái