Giáo trình môn Lập trình hướng đối tượng | Đại học Đà Nẵng

Tài liệu gồm 165 trang, có 9 chương chính bao gồm các kiến thức cơ bản liên quan:giới thiệu về lập trình hướng đối tượng; Các mở rộng của C++;.... giúp bạn ôn luyện và nắm vững kiến thức môn học đại cương Lập trình hướng đối tượng . Mời bạn đọc đón xem!

Thông tin:
165 trang 1 năm trước

Bình luận

Vui lòng đăng nhập hoặc đăng ký để gửi bình luận.

Giáo trình môn Lập trình hướng đối tượng | Đại học Đà Nẵng

Tài liệu gồm 165 trang, có 9 chương chính bao gồm các kiến thức cơ bản liên quan:giới thiệu về lập trình hướng đối tượng; Các mở rộng của C++;.... giúp bạn ôn luyện và nắm vững kiến thức môn học đại cương Lập trình hướng đối tượng . Mời bạn đọc đón xem!

174 87 lượt tải Tải xuống
ĐI HC ĐÀ NNG
TRNG ĐI HC K THUT
KHOA CÔNG NGH THÔNG TIN - ĐIN T VIN THÔNG
GIÁO TRÌNH MÔN HC
LP TRÌNH HƯỚNG ĐỐI TƯỢNG
BIÊN SON: LÊ TH M HNH
ĐÀ NNG, 09/2002
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
2
MC LC

CHNG 1: GII THIU V LP TRÌNH HNG ĐI TNG.......................... 5
I. LP TRÌNH HNG ĐI TNG (OOP) LÀ GÌ ? .............................................. 5
I.1. Lp trình tuyn tính ............................................................................................ 5
I.2. Lp trình cu trúc................................................................................................ 5
I.3. S tru tng hóa d liu................................................................................... 6
I.4. Lp trình hng đi tng ................................................................................. 6
II. MT S KHÁI NIM MI TRONG LP TRÌNH HNG ĐI TNG........... 8
II.1. S đóng gói (Encapsulation) .............................................................................. 8
II.2. Tính k tha (Inheritance).................................................................................. 9
II.3. Tính đa hình (Polymorphism) .......................................................................... 10
III. CÁC NGÔN NG VÀ VÀI NG DNG CA OOP............................................ 11
CHNG 2: CÁC M RNG CA C++...................................................................... 12
I. LCH S CA C++ ................................................................................................. 12
II. CÁC M RNG CA C++..................................................................................... 12
II.1. Các t khóa mi ca C++................................................................................. 12
II.2. Cách ghi chú thích............................................................................................ 12
II.3. Dòng nhp/xut chun...................................................................................... 13
II.4. Cách chuyn đi kiu d liu ........................................................................... 14
II.5. V trí khai báo bin........................................................................................... 14
II.6. Các bin const................................................................................................... 15
II.7. V struct, union và enum.................................................................................. 16
II.8. Toán t đnh phm vi ....................................................................................... 16
II.9. Toán t new và delete....................................................................................... 17
II.10. Hàm inline ........................................................................................................ 23
II.11. Các giá tr tham s mc đnh............................................................................ 24
II.12. Phép tham chiu ............................................................................................... 25
II.13. Phép đa nĕng hóa (Overloading)...................................................................... 29
CHNG 3: LP VÀ ĐI TNG .............................................................................. 39
I. DN NHP.............................................................................................................. 39
II. CÀI ĐT MT KIU DO NGI DÙNG ĐNH NGHƾA VI MT STRUCT. 39
III. CÀI ĐT MT KIU D LIU TRU TNG VI MT LP...................... 41
IV. PHM VI LP VÀ TRUY CP CÁC THÀNH VIÊN LP.................................. 45
V. ĐIU KHIN TRUY CP TI CÁC THÀNH VIÊN ............................................ 47
VI. CÁC HÀM TRUY CP VÀ CÁC HÀM TIN ÍCH............................................... 48
VII. KHI ĐNG CÁC ĐI TNG CA LP : CONSTRUCTOR......................... 49
VIII.S DNG DESTRUCTOR..................................................................................... 51
IX. KHI NÀO CÁC CONSTRUTOR VÀ DESTRUCTOR ĐC GI ?.................. 53
X. S DNG CÁC THÀNH VIÊN D LIU VÀ CÁC HÀM THÀNH VIÊN ........ 54
XI. TR V MT THAM CHIU TI MT THÀNH VIÊN D LIU PRIVATE.. 57
XII. PHÉP GÁN BI TOÁN T SAO CHÉP THÀNH VIÊN MC ĐNH ................. 59
XIII.CÁC ĐI TNG HNG VÀ CÁC HÀMTHÀNH VIÊN CONST..................... 60
XIV.LP NH LÀ CÁC THÀNH VIÊN CA CÁC LP KHÁC ............................... 64
XV. CÁC HÀM VÀ CÁC LP FRIEND........................................................................ 67
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
3
XVI.CON TR THIS ...................................................................................................... 68
XVII.CÁC ĐI TNG ĐC CP PHÁT ĐNG ................................................... 71
XVIII.CÁC THÀNH VIÊN TƾNH CA LP................................................................. 72
CHNG 4: ĐA NĔNG HÓA TOÁN T...................................................................... 76
I. DN NHP.............................................................................................................. 76
II. CÁC NGUYÊN TC C BN CA ĐA NĔNG HÓA TOÁN T...................... 76
III. CÁC GII HN CA ĐA NĔNG HÓA TOÁN T.............................................. 76
IV. CÁC HÀM TOÁN T CÓ TH LÀ CÁC THÀNH VIÊN CA LP HOC
KHÔNG LÀ CÁC THÀNH VIÊN........................................................................... 77
V. ĐA NĔNG HOÁ CÁC TOÁN T HAI NGÔI ....................................................... 80
VI. ĐA NĔNG HÓA CÁC TOÁN T MT NGÔI ..................................................... 87
VII. ĐA NĔNG HÓA MT S TOÁN T ĐC BIT ................................................ 90
VII.1.Toán t [] ............................................................................................................ 91
VII.2.Toán t () ............................................................................................................ 92
VIII.TOÁN T CHUYN ĐI KIU............................................................................ 94
IX. TOÁN T NEW VÀ DELETE................................................................................ 95
IX.1.Đa nĕng hóa toán t new và delete toàn cc........................................................ 96
IX.2.Đa nĕng hóa toán t new và delete cho mt lp .................................................. 97
X. ĐA NĔNG HÓA CÁC TOÁN T CHÈN DÒNG << VÀ TRÍCH DÒNG >> ...... 98
XI. MT S VÍ D ....................................................................................................... 99
XI.1.Lp String............................................................................................................. 99
XI.2.Lp Date............................................................................................................. 103
CHNG 5: TÍNH K THA...................................................................................... 107
I. DN NHP............................................................................................................ 107
II. K THA ĐN..................................................................................................... 107
II.1.Các lp c s và các lp dn xut ....................................................................... 107
II.2.Các thành viên protected...................................................................................... 109
II.3.Ép kiu các con tr lp c s ti các con tr lp dn xut.................................. 109
II.4.Đnh nghƿa li các thành viên lp c s trong mt lp dn xut:........................ 113
II.5.Các lp c s public, protected và private........................................................... 113
II.6.Các contructor và destructor lp dn xut........................................................... 113
II.7.Chuyn đi ngm đnh đi tng lp dn xut sang đi tng lp c s........... 116
III. ĐA K THA (MULTIPLE INHERITANCE)..................................................... 116
IV. CÁC LP C S O (VIRTUAL BASE CLASSES) ......................................... 119
CHNG 6: TÍNH ĐA HÌNH ....................................................................................... 122
I. DN NHP............................................................................................................ 122
II. PHNG THC O (VIRTUAL FUNCTION).................................................. 122
III. LP TRU TNG (ABSTRACT CLASS) ....................................................... 125
IV. CÁC THÀNH VIÊN O CA MT LP............................................................ 127
IV.1.Toán t o........................................................................................................... 127
IV.2.Có constructor và destructor o hay không?...................................................... 129
CHNG 7: THIT K CHNG TRÌNH THEO HNG ĐI TNG ......... 132
I. DN NHP............................................................................................................ 132
II. CÁC GIAI ĐON PHÁT TRIN H THNG..................................................... 132
III. CÁCH TÌM LP .................................................................................................... 133
IV. CÁC BC CN THIT Đ THIT K CHNG TRÌNH............................. 133
V. CÁC VÍ D ............................................................................................................ 134
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
4
CHNG 8: CÁC DNG NHP/XUT...................................................................... 143
I. DN NHP............................................................................................................ 143
II. CÁC DÒNG(STREAMS) ...................................................................................... 143
II.1.Các file header ca th vin iostream.................................................................. 143
II.2.Các lp và các đi tng ca dòng nhp/xut..................................................... 144
III. DÒNG XUT......................................................................................................... 145
III.1.Toán t chèn dòng.............................................................................................. 145
III.2.Ni các toán t chèn dòng và trích dòng............................................................ 146
III.3.Xut ký t vi hàm thành viên put(); Ni vi nhau hàm put() .......................... 147
IV. DÒNG NHP......................................................................................................... 148
IV.1.Toán t trích dòng:............................................................................................. 148
IV.2.Các hàm thành viên get() và getline()................................................................ 149
IV.3.Các hàm thành viên khác ca istream................................................................ 151
IV.4.Nhp/xut kiu an toàn....................................................................................... 151
V. NHP/XUT KHÔNG ĐNH DNG VI READ(),GCOUNT() VÀ WRITE() 151
VI. DÒNG NHP/ XUT FILE .................................................................................. 152
VI.1.Nhp/xut file vĕn bn ....................................................................................... 154
CHNG 9: HÀM VÀ LP TEMPLATE................................................................... 159
I. CÁC HÀM TEMPLATE........................................................................................ 159
II. CÁC LP TEMPLATE........................................................................................... 161
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
5
CHƯƠNG 1
GII THIU V LP TRÌNH HNG ĐI TNG
I. LP TRÌNH HNG ĐI TNG (OOP) LÀ GÌ ?
Lp trình hng đi tng (Object-Oriented Programming, vit tt là OOP) là mt phng pháp mi
trên bc đng tin hóa ca vic lp trình máy tính, nhm làm cho chng trình tr nên linh hot, tin cy
và d phát trin. Tuy nhiên đ hiu đc OOP là gì, chúng ta hãy bt đu t lch s ca quá trình lp trình –
xem xét OOP đã tin hóa nh th nào.
I.1. Lp trình tuyn tính
Máy tính đu tiên đc lp trình bng mã nh phân, s dng các công tt c khí đ np chng trình.
Cùng vi s xut hin ca các thit b lu tr ln và b nh máy tính có dung lng ln nên các ngôn ng
lp trình cp cao đu tiên đc đa vào s dng . Thay vì phi suy nghƿ trên mt dãy các bit và byte, lp
trình viên có th vit mt lot lnh gn vi ting Anh và sau đó chng trình d
ch thành ngôn ng máy.
Các ngôn ng lp trình cp cao đu tiên đc thit k đ lp các chng trình làm các công vic tng
đi đn gin nh tính toán. Các chng trình ban đu ch yu liên quan đn tính toán và không đòi hi gì
nhiu ngôn ng lp trình. Hn na phn ln các chng trình này tng đi ngn, thng ít hn 100 dòng.
Khi kh nĕng ca máy tính tĕng lên thì kh nĕng đ trin khai các chng trình phc t
p hn cũng tĕng
lên. Các ngôn ng lp trình ngày trc không còn thích hp đi vi vic lp trình đòi hi cao hn. Các
phng tin cn thit đ s dng li các phn mã chng trình đã vit hu nh không có trong ngôn ng lp
trình tuyn tính. Tht ra, mt đon lnh thng phi đc chép lp li mi khi chúng ta dùng trong nhiu
chng trình do đó chng trình dài dòng, logic ca chng trình khó hi
u. Chng trình đc điu khin
đ nhy đn nhiu ch mà thng không có s gii thích rõ ràng, làm th nào đ chng trình đn ch cn
thit hoc ti sao nh vy.
Ngôn ng lp trình tuyn tính không có kh nĕng kim soát phm vi nhìn thy ca các d liu. Mi d
liu trong chng trình đu là d liu toàn cc nghƿa là chúng có th b sa đi
bt k phn nào ca
chng trình. Vic dò tìm các thay đi không mong mun đó ca các phn t d liu trong mt dãy mã lnh
dài và vòng vèo đã tng làm cho các lp trình viên rt mt thi gian.
I.2. Lp trình cu trúc
Rõ ràng là các ngôn ng mi vi các tính nĕng mi cn phi đc phát trin đ có th to ra các ng
dng tinh vi hn. Vào cui các nĕm trong 1960 và 1970, ngôn ng lp trình có cu trúc ra đi. Các chng
trình có cu trúc đc t chc theo các công vic mà chúng thc hin.
V bn cht, chng trình chia nh thành các chng trình con riêng r (còn gi là hàm hay th tc)
thc hin các công vic ri rc trong quá trình ln hn, phc tp h
n. Các hàm này đc gi càng đc lp
vi nhau càng nhiu càng tt, mi hàm có d liu và logic riêng.Thông tin đc chuyn giao gia các hàm
thông qua các tham s, các hàm có th có các bin cc b mà không mt ai nm bên ngoài phm vi ca hàm
li có th truy xut đc chúng. Nh vy, các hàm có th đc xem là các chng trình con đc đt chung
vi nhau đ xây dng nên mt ng dng.
Mc tiêu là làm sao cho vic trin khai các phn mm d dàng hn đi v
i các lp trình viên mà vn ci
thin đc tính tin cy và d bo qun chng trình. Mt chng trình có cu trúc đc hình thành bng
cách b gãy các chc nĕng c bn ca chng trình thành các mnh nh mà sau đó tr thành các hàm. Bng
cách cô lp các công vic vào trong các hàm, chng trình có cu trúc có th làm gim kh nĕng ca mt
hàm này nh hng đn mt hàm khác. Vic này cũng làm cho vic tách các vn đ tr nên d
dàng hn. S
gói gn này cho phép chúng ta có th vit các chng trình sáng sa hn và gi đc điu khin trên tng
hàm. Các bin toàn cc không còn na và đc thay th bng các tham s và bin cc b có phm vi nh
hn và d kim soát hn. Cách t chc tt hn này nói lên rng chúng ta có kh nĕng qun lý logic ca cu
trúc chng trình, làm cho vic trin khai và bo dng chng trình nhanh hn và hu hi
n hn và hiu qu
hn.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
6
Mt khái nim ln đã đc đa ra trong lp trình có cu trúc là s tru tng hóa (Abstraction). S
tru tng hóa có th xem nh kh nĕng quan sát mt s vic mà không cn xem xét đn các chi tit bên
trong ca nó. Trong mt chng trình có cu trúc, chúng ta ch cn bit mt hàm đã cho có th làm đc mt
công vic c th gì là đ. Còn làm th nào mà công vic đó li thc hin đ
c là không quan trng, chng
nào hàm còn tin cy đc thì còn có th dùng nó mà không cn phi bit nó thc hin đúng đn chc nĕng
ca mình nh th nào. Điu này gi là s tru tng hóa theo chc nĕng (Functional abstraction) và là
nn tng ca lp trình có cu trúc.
Ngày nay, các k thut thit k và lp trình có cu trúc đc s rng rãi. Gn nh mi ngôn ng lp
trình đu có các ph
ng tin cn thit đ cho phép lp trình có cu trúc. Chng trình có cu trúc d vit, d
bo dng hn các chng trình không cu trúc.
S nâng cp nh vy cho các kiu d liu trong các ng dng mà các lp trình viên đang vit cũng đang
tip tc din ra. Khi đ phc tp ca mt chng trình tĕng lên, s ph thuc ca nó vào các kiu d liu c
b
n mà nó x lý cũng tĕng theo. Vn đ tr rõ ràng là cu trúc d liu trong chng trình quan trng chng
kém gì các phép toán thc hin trên chúng. Điu này càng tr rõ ràng hn khi kích thc ca chng trình
càng tĕng. Các kiu d liu đc x lý trong nhiu hàm khác nhau bên trong mt chng trình có cu trúc.
Khi có s thay đi trong các d liu này thì cũng cn phi thc hin c các thay đi mi ni có các thao tác
tác đng trên chúng. Đây có th
là mt công vic tn thi gian và kém hiu qu đi vi các chng trình có
hàng ngàn dòng lnh và hàng trĕm hàm tr lên.
Mt yu đim na ca vic lp trình có cu trúc là khi có nhiu lp trình viên làm vic theo nhóm cùng
mt ng dng nào đó. Trong mt chng trình có cu trúc, các lp trình viên đc phân công vit mt tp
hp các hàm và các kiu d liu. Vì có nhiu lp trình viên khác nhau qun lý các hàm riêng, có liên quan
đn các kiu d liu dùng chung nên các thay đi mà l
p trình viên to ra trên mt phn t d liu s làm nh
hng đn công vic ca tt c các ngi còn li trong nhóm. Mc dù trong bi cnh làm vic theo nhóm,
vic vit các chng trình có cu trúc thì d dàng hn nhng sai sót trong vic trao đi thông tin gia các
thành viên trong nhóm có th dn ti hu qu là mt rt nhiu thi gian đ sa cha chơng trình.
I.3. S tru tng hóa d liu
S tru tng hóa d liu (Data abstraction) tác đng trên các d liu cũng tng t nh s tru
tng hóa theo chc nĕng. Khi có tru tng hóa d liu, các cu trúc d liu và các phn t có th đc s
dng mà không cn bn tâm đn các chi tit c th. Chng hn nh các s du chm đng đã đc tru
tng hóa trong t
t c các ngôn ng lp trình, Chúng ta không cn quan tâm cách biu din nh phân chính
xác nào cho s du chm đng khi gán mt giá tr, cũng không cn bit tính bt thng ca phép nhân nh
phân khi nhân các giá tr du chm đng. Điu quan trng là các s du chm đng hot đng đúng đn và
hiu đc.
S tru tng hóa d liu giúp chúng ta không phi bn tâm v các chi tit không cn thi
t. Nu lp
trình viên phi hiu bit v tt c các khía cnh ca vn đ, mi lúc và v tt c các hàm ca chng trình
thì ch ít hàm mi đc vit ra, may mn thay tru tng hóa theo d liu đã tn ti sn trong mi ngôn ng
lp trình đi vi các d liu phc tp nh s du chm đng. Tuy nhiên ch mi g
n đây, ngi ta mi phát
trin các ngôn ng cho phép chúng ta đnh nghƿa các kiu d liu tru tng riêng.
I.4. Lp trình hng đi tng
Khái nim hng đi tng đc xây dng trên nn tng ca khái nim lp trình có cu trúc và s tru
tng hóa d liu. S thay đi cĕn bn ch, mt chng trình hng đi tng đc thit k xoay quanh
d liu mà chúng ta có th làm vic trên đó, hn là theo bn thân chc nĕng ca chng trình. Điu này hoàn
toàn t nhiên mt khi chúng ta hiu rng m
c tiêu ca chng trình là x lý d liu. Suy cho cùng, công vic
mà máy tính thc hin vn thng đc gi là x lý d liu. D liu và thao tác liên kt vi nhau mt mc
c bn (còn có th gi là mc thp), mi th đu đòi hi th kia có mc tiêu c th, các chng trình
hng đi tng làm tng minh mi quan h này.
Lp trình hng đi t
ng (Object Oriented Programming - gi tt là OOP) hay chi tit hn là Lp trình
định hướng đối tượng, chính là phng pháp lp trình ly đi tng làm nn tng đ xây dng thut gii, xây
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
7
dng chng trình. Thc cht đây không phi là mt phng pháp mi mà là mt cách nhìn mi trong vic
lp trình. Đ phân bit, vi phng pháp lp trình theo kiu cu trúc mà chúng ta quen thuc trc đây, hay
còn gi là phng pháp lp trình hng th tc (Procedure-Oriented Programming), ngi lp trình phân
tích mt nhim v ln thành nhiu công vic nh hn, sau đó dn dn chi tit, c th hoá đ đc các vn đ
đn gin, đ tìm ra cách gii quyt vn đ di dng nhng thut gii c th rõ ràng qua đó d dàng minh
ho bng ngôn ng gii thut (hay còn gi các thut gii này là các chng trình con). Cách thc phân tích
và thit k nh vy chúng ta gi là nguyên lý lp trình t trên xung (top-down), đ th hin quá trình suy
din t cái chung cho đn cái c th.
Các chng trình con là nhng chc nĕng đc l
p, s ghép ni chúng li vi nhau cho chúng ta mt h
thng chng trình đ gii quyt vn đ đt ra. Chính vì vy, cách thc phân tích mt h thng ly chng
trình con làm nn tng, chng trình con đóng vai trò trung tâm ca vic lp trình, đc hiu nh phng
pháp lp trình hg v th tc. Tuy nhiên, khi phân tích đ thit k mt h thng không nht thit phi luôn
luôn suy nghƿ theo h
ng “làm thế nào để gii quyết công vic”, chúng ta có th đnh hng t duy theo
phong cách “vi mt s đối tượng đã có, phi làm gì để gii quyết được công vic đặt ra” hoc phong phú
hn, “làm cái gì vi mt s đối tượng đã có đó”, t đó cũng có th gii quyt đc nhng công vic c th.
Vi phng pháp phân tích trong đó đ
i tng đóng vai trò trùng tâm ca vic lp trình nh vy, ngi ta
gi là nguyên lý lp trình t di lên (Bôttm-up).
Lp trình hng đi tng liên kt cu trúc d liu vi các thao tác, theo cách mà tt c thng nghƿ v
th gii quanh mình. Chúng ta thng gn mt s các hot đng c th vi mt loi hot đng nào đó và đt
các gi thit ca mình trên các quan h
đó.
Ví d1.1
: Đ d hình dùng hn, chúng ta th nhìn qua các công trình xây dng hin đi, nh sân vn
đng có mái che hình vòng cung, nhng kin trúc thm mƿ vi đng nét hình cong. Tt c nhng sn phm
đó xut hin cùng vi nhng vt liu xây dng. Ngày nay, không ch chng lên nhau nhng viên gch,
nhng tng đá đ to nên nhng qun th kin trúc (nh Tháp Chàm Nha Trang, Kim T Tháp,...), mà có th
vi bêtông, st thép và không nhiu lm nh
ng viên gch, ngi xây dng cũng có th thit k nhng công
trình kin trúc tuyt m, nhng toà nhà hin đi. Chính các cht liu xây dng đã làm nh hng phng
pháp xây dng, cht liu xây dng và nguyên lý kt dính caá cht liu đó li vi nhau cho chúng ta mt đi
tng đ kho sát, Cht liu xây dng và nguyên lý kt dính các cht liu li vi nhau đc hiu theo nghƿa
d
liu và chng trình con tác đng trên d liu đó.
Ví d1.2
: Chúng ta bit rng mt chic xe có các bánh xe, di chuyn đc và có th đi hng ca nó
bng cách quo tay lái. Tng t nh th, mt cái cây là mt loi thc vt có thân g và lá. Mt chic xe
không phi là mt cái cây, mà cái cây không phi là mt chic xe, chúng ta có th gi thit rng cái mà
chúng ta có th làm đc vi mt chic xe thì không th làm đc vi mt cái cây. Chng hn, tht là vô
nghƿa khi mun lái mt cái cây, còn chi
c xe thì li chng ln thêm đc khi chúng ta ti nc cho nó.
Lp trình hng đi tng cho phép chúng ta s dng các quá trình suy nghƿ nh vy vi các khái nim
tru tng đc s dng trong các chng trình máy tính. Mt mu tin (record) nhân s có th đc đc ra,
thay đi và lu tr li; còn s phc thì có th đc dùng trong các tính toán. Tuy vy không th nào li vit
mt s phc vào tp tin làm mu tin nhân s và ng
c li hai mu tin nhân s li không th cng vi nhau
đc. Mt chng trình hng đi tng s xác đnh đc đim và hành vi c th ca các kiu d liu, điu
đó cho phép chúng ta bit mt cách chính xác rng chúng ta có thđc nhng gì các kiu d liu khác
nhau.
Chúng ta còn có th to ra các quan h gia các kiu d liu tng t nhng khác nhau trong mt
ch
ng trình hng đi tng. Ngi ta thng t nhiên phân loi ra mi th, thng đt mi liên h gia
các khái nim mi vi các khái nim đã có, và thng có th thc hin suy din gia chúng trên các quan h
đó. Hãy quan nim th gii theo kiu cu trúc cây, vi các mc xây dng chi tit hn k tip nhau cho các
th h sau so vi các th h trc. Đây là phng pháp hiu qu
đ t chc th gii quanh chúng ta. Các
chng trình hng đi tng cũng làm vic theo mt phng thc tng t, trong đó chúng cho phép xây
dng các các c cu d liu và thao tác mi da trên các c cu có sn, mang theo các tính nĕng ca các c
cu nn mà chúng da trên đó, trong khi vn thêm vào các tính nĕng mi.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
8
Lp trình hng đi tng cho phép chúng ta t chc d liu trong chng trình theo mt cách tng t
nh các nhà sinh hc t chc các loi thc vt khác nhau. Theo cách nói lp trình đi tng, xe hi, cây ci,
các s phc, các quyn sách đu đc gi là các lp (Class).
Mt lp là mt bn mu mô t các thông tin cu trúc d liu, ln các thao tác hp l ca các phn t d
liu. Khi mt phn t d liu đc khai báo là phn t ca mt lp thì nó đc gi là mt đi tng
(Object). Các hàm đc đnh nghƿa hp l trong mt lp đc gi là các phng thc (Method) và chúng
là các hàm duy nht có th x lý d liu ca các đi tng ca lp đó. Mt thc th (Instance) là mt v
t
th có thc bên trong b nh, thc cht đó là mt đi tng (nghƿa là mt đi tng đc cp phát vùng
nh).
Mi mt đi tng có riêng cho mình mt bn sao các phn t d liu ca lp còn gi là các bin thc
th (Instance variable). Các phng thc đnh nghƿa trong mt lp có th đc gi bi các đi tng ca
l
p đó. Điu này đc gi là gi mt thông đip (Message) cho đi tng. Các thông đip này ph thuc
vào đi tng, ch đi tng nào nhn thông đip mi phi làm vic theo thông đip đó. Các đi tng đu
đc lp vi nhau vì vy các thay đi trên các bin th hin ca đi tng này không nh hng gì trên các
bin th
hin ca các đi tng khác và vic gi thông đip cho mt đi tng này không nh hng gì đn
các đi tng khác.
Nh vy, đi tng đc hiu theo nghƿa là mt thc th mà trong đó caá d liu và th tc tác
đng lên d liu đã đc đóng gói li vi nhau. Hay “đối tượng được đặc trưng bi mt s thao tác
(operation) và các thông tin (information) ghi nhơ s tác động ca caá thao tác này.
Ví d 1.3:
Khi nghiên c v ngĕn xp (stack), ngoài các d liu vùng cha ngĕn xp, đnh ca
ngĕn xp, chúng ta phi cài đt kèm theo các thao tác nh khi to (creat) ngĕn xp, kim tra ngĕn
xp rng (empty), đy (push) mt phn t vào ngĕn xp, ly (pop) mt phn t ra khi ngĕn xp.
Trên quan đim ly đi tng làm nn tng, rõ ràng d liu và các thao tác trên d liu luôn gn bó
vi nhau, s kt dính chúng chính là đi tng chúng ta cn kho sát.
Các thao tác trong đi tng đc gi là các phng thc hay hành vi ca đi tng đó.
Phng thc và d liu ca đi tng luôn tác đng ln nhau và có vai trò ngang nhau trong đi
tng, Phng thc ca đi tng đc qui đnh bi d liu và ngc li, d liu ca đi tng
đc đt trng bi các phng thc ca đi tng. Chính nh s gn bó đó, chúng ta có th gi
cùng mt thông đip đn nhng đi tng khác nhau. Điu này giúp ngi lp trình không phi x
lý trong chng trình ca mình mt dãy các cu trúc điu khin tu theo thông đip nhn vào, mà
chng trình đc x lý vào thi đim thc hin.
Tóm li, so sánh lp trình cu trúc vi chng trình con làm nn tng:
Chng trình = Cu trúc d liu + Thut gii
Trong lp trình hng đi tng chúng ta có:
Đi tng = Phng thc + D liu
Đây chính là 2 quan đim lp trình đang tn ti và phát trin trong th gii ngày nay.
II. MT S KHÁI NIM MI TRONG LP TRÌNH HNG ĐI TNG
Trong phn này, chúng ta tìm hiu các khái nim nh s đóng gói, tính k tha và tính đa hình. Đây
các khái nim cĕn bn, là nn tng t tng ca lp trình hng đi tng. Hiu đc khái nim này, chúng
ta bc đu tip cn vi phong cách lp trình mi, phong cách lp trình da vào đi tng làm nn tng mà
trong đó quan đim che du thông tin thông qua s đóng gói là quan đim trung tâm ca vn đ
.
II.1. S đóng gói (Encapsulation)
S đóng gói là c ch ràng buc d liu và thao tác trên d liu đó thành mt th thng nht, tránh đc
các tác đng bt ng t bên ngoài. Th thng nht này gi là đi tng.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
9
Trong Objetc Oriented Software Engineering ca Ivar Jacibson, tt c các thông tin ca mt h thng
đnh hng đi tng đc lu tr bên trong đi tng ca nó và ch có th hành đng khi các đi tng đó
đc ra lnh thc hin các thao tác. Nh vt, s đóng gói không ch đn thun là s gom chung d liu và
chng trình vào trong mt khi, chúng còn đc hiu theo nghƿa là s đng nht gia d
liu và các thao
tác tác đng lên d liu đó.
Trong mt đi tng, d liu hay thao tác hay c hai có thriêng (private) hoc chung (public) ca
đi tng đó. Thao tác hay d liu riêng là thuc v đi tng đó ch đc truy cp bi các thành phn ca
đi tng, điu này nghƿa là thao tác hay d liu riêng không th truy cp bi các phn khác ca chng
trình tn t
i ngoài đi tng. Khi thao tác hay d liu là chung, các phn khác ca chng trình có th truy
cp nó mc dù nó đc đnh nghƿa trong mt đi tng. Các thành phn chung ca mt đi tng dùng đ
cung cp mt giao din có điu khin cho các thành thành riêng ca đi tng.
C ch đóng gói là phng thc tt đ thc hin c ch che du thông tin so vi các ngôn ng lp trình
cu trúc.
II.2. Tính k tha (Inheritance)
Chúng ta có th xây dng các lp mi t các lp cũ thông qua s k tha. Mt lp mi còn gi là lp
dn xut (derived class), có th tha hng d liu và các phng thc ca lp c s (base class) ban đu.
Trong lp này, có th b sung các thành phn d liu và các phng thc mi vào nhng thành phn d liu
và các phng thc mà nó th
a hng t lp c s. Mi lp (k c lp dn xut) có th có mt s lng bt
k các lp dn xut. Qua c cu k tha này, dng hình cây ca các lp đc hình thành. Dng cây ca các
lp trông ging nh các cây gia ph vì th các lp c s còn đc gi là lp cha (parent class) và các lp
dn xut đc g
i là lp con (child class).
Ví d 1.2
: Chúng ta s xây dng mt tp các lp mô t cho th vin các n phm. Có hai kiu n phm:
tp chí và sách. Chúng ta có th to mt n phm tng quát bng cách đnh nghƿa các thành phn d liu
tng ng vi s trang, mã s tra cu, ngày tháng xut bn, bn quyn và nhà xut bn. Các n phm có th
đc ly ra, ct đi và đc. Đó là các phng thc th
c hin trên mt n phm. Tip đó chúng ta đnh nghƿa
hai lp dn xut tên là tp chí và sách. Tp chí có tên, s ký phát hành và cha nhiu bài ca các tác gi khác
nhau . Các thành phn d liu tng ng vi các yu t này đc đt vào đnh nghƿa ca lp tp chí. Tp chí
cũng cn có mt phng thc na đó là đt mua. Các thành phn d liu xác đnh cho sách s bao gm tên
ca (các) tác gi, loi bìa (cng hay mm) và s hiu ISBN ca nó. Nh vy chúng ta có th thy, sách và tp
chí có chung các đc trng n phm, trong khi vn có các thuc tính riêng ca chúng.
Hình 1.1: Lp n phm và các
lp dn xut ca nó.
Vi tính k tha, chúng ta
không phi mt công xây dng li t
đu các lp mi, ch cn b sung đ
đc trong các lp dn xut các
đc trng cn thit.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
10
II.3. Tính đa hình (Polymorphism)
Đó là kh nĕng đ cho mt thông đip có th thay đi cách thc hin ca nó theo lp c th ca đi
tng nhn thông đip. Khi mt lp dn xut đc to ra, nó có th thay đi cách thc hin các phng thc
nào đó mà nó tha hng t lp c s ca nó. Mt thông đip khi đc gi đn mt đi t
ng ca lp c s,
s dùng phng thc đã đnh nghƿa cho nó trong lp c s. Nu mt lp dn xut đnh nghƿa li mt phng
thc tha hng t lp c s ca nó thì mt thông đip có cùng tên vi phng thc này, khi đc gi ti
mt đi tng ca lp dn xut s g
i phng thc đã đnh nghƿa cho lp dn xut.
Nh vy đa hình là kh nĕng cho phép gi cùng mt thông đip đn nhng đi tng khác nhau có cùng
chung mt đc đim, nói cách khác thông đip đc gi đi không cn bit thc th nhn thuc lp nào, ch
bit rng tp hp các thc th nhn có chung mt tính cht nào đó. Ch
ng hn, thông đip “v hìnhđc
gi đn c hai đi tng hình hp và hình tròn. Trong hai đi tng này đu có chung phng thc v hình,
tuy nhiên tu theo thi đim mà đi tng nhn thông đip, hình tng ng s đc v lên.
Trong các ngôn ng lp trình OOP, tính đa hình th hin qua kh nĕng cho phép mô t nhng phng
thc có tên ging nhau trong các lp khác nhau. Đc đim này giúp ng
i lp trình không phi vit nhng
cu trúc điu khin rm rà trong chng trình, các kh nĕng khác nhau ca thông đip ch thc s đòi hi
khi chng trình thc hin.
Ví d 1.3
: Xét li ví d 1.2, chúng ta thy rng c tp chí và và sách đu phi có kh nĕng ly ra. Tuy
nhiên phng pháp ly ra cho tp chí có khác so vi phng pháp ly ra cho sách, mc dù kt qu cui cùng
ging nhau. Khi phi ly ra tp chí, thì phi s dng phng pháp ly ra riêng cho tp chí (da trên mt bn
tra cu) nhng khi ly ra sách thì li phi s dng phng pháp ly ra riêng cho sách (da trên h thng
phiu lu tr
). Tính đa hình cho phép chúng ta xác đnh mt phng thc đ ly ra mt tp chí hay mt cun
sách. Khi ly ra mt tp chí nó s dùng phng thc ly ra dành riêng cho tp chí, còn khi ly ra mt cun
sách thì nó s dng phng thc ly ra tng ng vi sách. Kt qu là ch cn mt tên phng thc duy nht
đc dùng cho c hai công vic tin hành trên hai lp dn xut có liên quan, mc dù vic thc hi
n ca
phng thc đó thay đi tùy theo tng lp.
Tính đa hình da trên s ni kt (Binding), đó là quá trình gn mt phng thc vi mt hàm thc s.
Khi các phng thc kiu đa hình đc s dng thì trình biên dch cha th xác đnh hàm nào tng ng vi
phng thc nào s đc gi. Hàm c th đc gi s tu thuc vào vic ph
n t nhn thông đip lúc đó là
thuc lp nào, do đó hàm đc gi ch xác đnh đc vào lúc chng trình chy. Điu này gi là s kt ni
mun (Late binding) hay kt ni lúc chy
(Runtime binding) vì nó xy ra khi
chng trình đang thc hin.
Hình 1.2: Minh ha tính đa hình đi vi
lp n phm và các lp dn xut ca nó.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
11
III. CÁC NGÔN NG VÀ VÀI NG DNG CA OOP
Xut phát t t tng ca ngôn ng SIMULA67, trung tâm nghiên cu Palo Alto (PARC) ca hãng
XEROR đã tp trung 10 nĕm nghiên cu đ hoàn thin ngôn ng OOP đu tiên vi tên gi là Smalltalk. Sau
đó các ngôn ng OOP ln lt ra đi nh Eiffel, Clos, Loops, Flavors, Object Pascal, Object C, C++, Delphi,
Java…
Chính XEROR trên c s ngôn ng OOP đã đ ra t tng giao din biu tng trên màn hình (icon
base screen interface), k t đó Apple Macintosh cũng nh Microsoft Windows phát trin giao din đ ha
nh ngày nay. Trong Microsoft Windows, t tng OOP đc th
hin mt cách rõ nét nht đó là "chúng ta
click vào đi tng", mi đi tng có thcontrol menu, control menu box, menu bar, scroll bar, button,
minimize box, maximize box, … s đáp ng công vic tùy theo đc tính ca đi tng. Turbo Vision ca
hãng Borland là mt ng dng OOP tuyt vi, giúp lp trình viên không quan tâm đn chi tit ca chng
trình gia din mà ch cn thc hin các ni dung chính ca vn đ.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
12
CHƯƠNG 2
CÁC M RNG CA C++
I. LCH S CA C++
Vào nhng nĕm đu thp niên 1980, ngi dùng bit C++ vi tên gi "C with Classes" đc mô t trong
hai bài báo ca Bjarne Stroustrup (thuc AT&T Bell Laboratories) vi nhan đ "Classes: An Abstract Data
Type Facility for the C Language" và "Adding Classes to C : AnExercise in Language Evolution". Trong
công trình này, tác gi đã đ xut khái nim lp, b sung vic kim tra kiu tham s ca hàm, các chuyn đi
kiu và mt s m rng khác vào ngôn ng C. Bjarne Stroustrup nghiên cu m rng ngôn ng C nhm đt
đn mt ngôn ng mô phng (simulation language) vi nhng tính nĕng h
ng đi tng.
Trong nĕm 1983, 1984, ngôn ng "C with Classes" đc thit k li, m rng hn ri mt trình biên
dch ra đi. Và chính t đó, xut hin tên gi "C++". Bjarne Stroustrup mô t ngôn ng C++ ln đu tiên
trong bài báo có nhan đ "Data Abstraction in C". Sau mt vài hiu chnh C++ đc công b rng rãi trong
quyn "The C++ Programming Language" ca Bjarne Stroustrup xut hin đánh du s hin din thc s
ca C++, ngi lp tình chuyên nghip t đ
ây đã có mt ngôn ng đ mnh cho các d án thc tin ca
mình.
V thc cht C++ ging nh C nhng b sung thêm mt s m rng quan trng, đc bit là ý tng v
đi tng, lp trình đnh hng đi tng.Tht ra các ý tng v cu trúc trong C++ đã xut phát vào các
nĕm 1970 t Simula 70 và Algol 68. Các ngôn ng này đã đa ra các khái nim v lp và đn th. Ada là
m
t ngôn ng phát trin t đó, nhng C++ đã khng đnh vai trò thc s ca mình.
II. CÁC M RNG CA C++
II.1. Các t khóa mi ca C++
Đ b sung các tính nĕng mi vào C, mt s t khóa (keyword) mi đã đc đa vào C++ ngoài các t
khóa có trong C. Các chng trình bng C nào s dng các tên trùng vi các t khóa cn phi thay đi trc
khi chng trình đc dch li bng C++. Các t khóa mi này là :
asm catch class delete friend inline
new operator private protected public template
this throw try virtual
II.2. Cách ghi chú thích
C++ chp nhn hai kiu chú thích. Các lp trình viên bng C đã quen vi cách chú thích bng /*…*/.
Trình biên dch s b qua mi th nm gia /*…*/.
Ví d 2.1
: Trong chng trình sau :
#include <iostream.h>
int main()
{
int I;
for(I = 0; I < 10 ; ++ I) // 0 - 9
cout<<I<<"\n"; // In ra
return 0;
}
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
13
Mi th nm gia /*…*/ t dòng 1 đn dòng 3 đu đc chng trình b qua. Chng trình này còn
minh ha cách chú thích th hai. Đó là cách chú thích bt đu bng // dòng 8 và dòng 9. Chúng ta chy ví
d 2.1, kt qu hình 2.1.
Hình 2.1: Kt qu ca ví d 2.1
Nói chung, kiu chú thích /*…*/ đc dùng cho các khi chú thích ln gm nhiu dòng, còn kiu //
đc dùng cho các chú thích mt dòng.
II.3. Dòng nhp/xut chun
Trong chng trình C, chúng ta thng s dng các hàm nhp/xut d liu là printf() và scanf(). Trong
C++ chúng ta có th dùng dòng nhp/xut chun (standard input/output stream) đ nhp/xut d liu thông
qua hai bin đi tng ca dòng (stream object) là cout cin.
Ví d 2.2:
Chng trình nhp vào hai s. Tính tng và hiu ca hai s va nhp.
//Chuong trinh 2.2
#include <iostream.h>
int main()
{
int X, Y;
cout<< "Nhap vao mot so X:";
cin>>X;
cout<< "Nhap vao mot so Y:";
cin>>Y;
cout<<"Tong cua chung:"<<X+Y<<"\n";
cout<<"Hieu cua chung:"<<X-Y<<"\n";
return 0;
}
Đ thc hin dòng xut chúng ta s dng bin cout (console output) kt hp vi toán t chèn (insertion
operator) << nh các dòng 5, 7, 9 và 10. Còn dòng nhp chúng ta s dng bin cin (console input) kt hp
vi toán t trích (extraction operator) >> nh các dòng 6 và 8. Khi s dng cout hay cin, chúng ta phi kéo
file iostream.h nh dòng 1. Chúng ta s tìm hiu k v dòng nhp/xut chng 8. Chúng ta chy ví d 2.2
,
kt qu hình 2.2.
Hình 2.2: Kt qu ca ví d 2.2
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
14
Hình 2.3: Dòng nhp/xut d liu
II.4. Cách chuyn đi kiu d liu
Hình thc chuyn đi kiu trong C tng đi ti nghƿa, vì vy C++ trang b thêm mt cách chuyn đi
kiu ging nh mt lnh gi hàm.
Ví d 2.3:
#include <iostream.h>
int main()
{
int X = 200;
long Y = (long) X; //Chuyen doi kieu theo cach cua C
long Z = long(X); //Chuyen doi kieu theo cach moi cua C++
cout<< "X = "<<X<<"\n";
cout<< "Y = "<<Y<<"\n";
cout<< "Z = "<<Z<<"\n";
return 0;
}
Chúng ta chy ví d 2.3
, kt qu hình 2.4.
Hình 2.4: Kt qu ca ví d 2.3
II.5. V trí khai báo bin
Trong chng trình C đòi hi tt c các khai báo bên trong mt phm vi cho trc phi đc đt ngay
đu ca phm vi đó. Điu này có nghƿa là tt c các khai báo toàn cc phi đt trc tt c các hàm và các
khai báo cc b phi đc tin hành trc tt c các lnh thc hin. Ngc li C++ cho phép chúng ta khai
báo linh hot bt k v trí nào trong mt phm vi cho trc (không nht thit ph
i ngay đu ca phm vi),
chúng ta xen k vic khai báo d liu vi các câu lnh thc hin.
Ví d 2.4:
Chng trình mô phng mt máy tính đn gin
1: #include <iostream.h>
2: int main()
3: {
4: int X;
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
15
5: cout<< "Nhap vao so thu nhat:";
6: cin>>X;
7: int Y;
8: cout<< "Nhap vao so thu hai:";
9: cin>>Y;
10: char Op;
11: cout<<"Nhap vao toan tu (+-*/):";
12: cin>>Op;
13: switch(Op)
14: {
15: case ‘+’:
16: cout<<"Ket qua:"<<X+Y<<"\n";
17: break;
18: case ‘-’:
19: cout<<"Ket qua:"<<X-Y<<"\n";
20: break;
21: case ‘*’:
22: cout<<"Ket qua:"<<long(X)*Y<<"\n";
23: break;
24: case ‘/’:
25: if (Y)
26: cout<<"Ket qua:"<<float(X)/Y<<"\n";
27: else
28: cout<<"Khong the chia duoc!" <<"\n"; 9; 9;
29: break;
30: default :
31: cout<<"Khong hieu toan tu nay!"<<"\n";
32: }
33: return 0;
34: }
Trong chng trình chúng ta xen k khai báo bin vi lnh thc hin dòng 4 đn dòng 12. Chúng ta
chy ví d 2.4, kt qu hình 2.5.
Hình 2.5: Kt qu ca ví d 2.4
Khi khai báo mt bin trong chng trình, bin đó s có hiu lc trong phm vi ca chng trình đó k
t v trí nó xut hin. Vì vy chúng ta không th s dng mt bin đc khai báo bên di nó.
II.6. Các bin const
Trong ANSI C, mun đnh nghƿa mt hng có kiu nht đnh thì chúng ta dùng bin const (vì nu dùng
#define thì to ra các hng không có cha thông tin v kiu). Trong C++, các bin const linh hot hn mt
cách đáng k:
C++ xem const cũng nh #define nu nh chúng ta mun dùng hng có tên trong chng trình. Chính
vì vy chúng ta có th dùng const đ quy đnh kích thc ca mt mng nh đon mã sau:
const int ArraySize = 100;
int X[ArraySize];
Khi khai báo mt bin const trong C++ thì chúng ta ph
i khi to mt giá tr ban đu nhng đi vi
ANSI C thì không nht thit phi làm nh vy (vì trình biên dch ANSI C t đng gán tr zero cho bin const
nu chúng ta không khi to giá tr ban đu cho nó).
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
16
Phm vi ca các bin const gia ANSI C và C++ khác nhau. Trong ANSI C, các bin const đc khai
báo bên ngoài mi hàm thì chúng có phm vi toàn cc, điu này nghƿa là chúng có th nhìn thy c bên
ngoài file mà chúng đc đnh nghƿa, tr khi chúng đc khai báo là static. Nhng trong C++, các bin
const đc hiu mc đnh là static.
II.7. V struct, union và enum
Trong C++, các structunion thc s các các kiu class. Tuy nhiên có s thay đi đi vi C++. Đó là
tên ca structunion đc xem luôn là tên kiu ging nh khai báo bng lnh typedef vy.
Trong C, chúng ta có thđon mã sau :
struct Complex
{
float Real;
float Imaginary;
};
…………………..
struct Complex C;
Trong C++, vn đ tr nên đn gin hn:
struct Complex
{
float Real;
float Imaginary;
};
…………………..
Complex C;
Quy đnh này cũng áp dng cho c union enum. Tuy nhiên đ tng thích vi C, C++ vn chp nhn
cú pháp cũ.
Mt kiu union đc bit đc thêm vào C++ gi là union nc danh (anonymous union). Nó ch khai báo
mt lot các trng(field) dùng chung mt vùng đa ch b nh. Mt union nc danh không có tên tag, các
trng có th đc truy xut trc tip bng tên ca chúng. Chng hn nh đon mã sau:
union
{
int Num;
float Value;
};
C hai Num và Value
đu dùng chung mt v trí và không gian b nh. Tuy nhiên không ging nh kiu
union có tên, các trng ca union nc danh thì đc truy xut trc tip, chng hn nh sau:
Num = 12;
Value = 30.56;
II.8. Toán t đnh phm vi
Toán t đnh phm vi (scope resolution operator) ký hiu là ::, nó đc dùng truy xut mt phn t b
che bi phm vi hin thi.
Ví d 2.5 :
1: #include <iostream.h>
2: int X = 5;
3: int main()
4: {
5: int X = 16;
6: cout<< "Bien X ben trong = "<<X<<"\n";
7: cout<< "Bien X ben ngoai = "<<::X<<"\n";
8: return 0;
9: }
Chúng ta chy ví d 2.5
, kt qu hình 2.6
Hình 2.6: Kt qu ca ví d 2.5
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
17
Toán t đnh phm vi còn đc dùng trong các đnh nghƿa hàm ca các phng thc trong các lp, đ
khai báo lp ch ca các phng thc đang đc đnh nghƿa đó. Toán t đnh phm vi còn có th đc dùng
đ phân bit các thành phn trùng tên ca các lp c s khác nhau.
II.9. Toán t new và delete
Trong các chng trình C, tt c các cp phát đng b nh đu đc x lý thông qua các hàm th vin
nh malloc(), calloc()free(). C++ đnh nghƿa mt phng thc mi đ thc hin vic cp phát đng b
nh bng cách dùng hai toán t new delete. S dng hai toán t này s linh hot hn rt nhiu so vi các
hàm th vin ca C.
Đon ch
ng trình sau dùng đ cp phát vùng
nh đng theo li c đin ca C.
int *P;
P = malloc(sizeof(int));
if (P==NULL)
printf("Khong con du bo nho de cap phat\n");
else
{
*P = 290;
printf("%d\n", *P);
free(P);
}
Trong C++, chúng ta có th vit li đon chng
trình trên nh sau:
int *P;
P = new int;
if (P==NULL)
cout<<"Khong con du bo nho de cap phat\n";
else
{
*P = 290;
cout<<*P<<"\n";
delete P;
}
Chúng ta nhn thy rng, cách vit ca C++ sáng sa và d s dng hn nhiu. Toán t new thay th
cho hàm malloc() hay calloc() ca C có cú pháp nh sau :
new type_name
new ( type_name )
new type_name initializer
new ( type_name ) initializer
Trong đó :
type_name: Mô t kiu d liu đc cp phát. Nu kiu d liu mô t phc tp, nó có th đc đt bên
trong các du ngoc.
initializer: Giá tr khi đng ca vùng nh đc cp phát.
Nu toán t new cp phát không thành công thì nó s tr v giá tr NULL.
Còn toán t delete thay th hàm free() ca C, nó có cú pháp nh sau :
delete pointer
delete [] pointer
Chúng ta có th va cp phát va khi đng nh sau :
int *P;
P = new int(100);
if (P!=NULL)
{
cout<<*P<<"\n";
delete P;
}
else
cout<<"Khong con du bo nho de cap phat\n";
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
18
Đ cp phát mt mng, chúng ta làm nh sau :
int *P;
P = new int[10]; //Cp phát mng 10 s nguyên
if (P!=NULL)
{
for(int I = 0;I<10;++)
P[I]= I;
for(I = 0;I<10;++)
cout<<P[I]<<"\n";
delete []P;
}else cout<<"Khong con du bo nho de cap phat\n";
Chú ý
: Đi vi vic cp phát mng chúng ta không th va cp phát va khi đng giá tr cho chúng,
chng hn đon chng trình sau là sai :
int *P;
P = new (int[10])(3); //Sai !!!
Ví d 2.6:
Chng trình to mt mng đng, khi đng mng này vi các giá tr ngu nhiên và sp xp
chúng.
1: #include <iostream.h>
2: #include <time.h>
3: #include <stdlib.h>
4: int main()
5: {
6: int N;
7: cout<<"Nhap vao so phan tu cua mang:";
8: cin>>N;
9: int *P=new int[N];
10: if (P==NULL)
11: {
12: cout<<"Khong con bo nho de cap phat\n";
13: return 1;
14: }
15: srand((unsigned)time(NULL));
16: for(int I=0;I<N;++I)
17: P[I]=rand()%100; //To các s ngu nhiên t 0 đến 99
18: cout<<"Mang truoc khi sap xep\n";
19: for(I=0;I<N;++I)
20: cout<<P[I]<<" ";
21: for(I=0;I<N-1;++I)
22: for(int J=I+1;J<N;++J)
23: if (P[I]>P[J])
24: {
25: int Temp=P[I];
26: P[I]=P[J];
27: P[J]=Temp;
28: }
29: cout<<"\nMang sau khi sap xep\n";
30: for(I=0;I<N;++I)
31: cout<<P[I]<<" ";
32: delete []P;
33: return 0;
34: }
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
19
Chúng ta chy ví d 2.6
, kt qu hình 2.7
Hình 2.7: Kt qu ca ví d 2.6
Ví d 2.7:
Chng trình cng hai ma trn trong đó mi ma trn đc cp phát đng.
Chúng ta có th xem mng hai chiu nh mng mt chiu nh hình 2.8
Hình 2.8: Mng hai chiu có th xem nh mng mt chiu.
Gi X là mng hai chiu có kích thc m dòng và n ct.
A là mng mt chiu tng ng.
Nu X[i][j] chính là A[k] thì k = i*n + j
Chúng ta có chng trình nh sau :
1: #include <iostream.h>
2: #include <conio.h>
3: //prototype
4: void AddMatrix(int * A,int *B,int*C,int M,int N);
5: int AllocMatrix(int **A,int M,int N);
6: void FreeMatrix(int *A);
7: void InputMatrix(int *A,int M,int N,char Symbol);
8: void DisplayMatrix(int *A,int M,int N);
9:
10: int main()
11: {
12: int M,N;
13: int *A = NULL,*B = NULL,*C = NULL;
14:
15: clrscr();
16: cout<<"Nhap so dong cua ma tran:";
17: cin>>M;
18: cout<<"Nhap so cot cua ma tran:";
19: cin>>N;
20: //Cp phát vùng nh cho ma trn A
21: if (!AllocMatrix(&A,M,N))
22: { //endl: Xut ra kí t xung dòng (‘\n’)
23: cout<<"Khong con du bo nho!"<<endl;
24: return 1;
25: }
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
20
26: //Cp phát vùng nh cho ma trn B
27: if (!AllocMatrix(&B,M,N))
28: {
29: cout<<"Khong con du bo nho!"<<endl;
30: FreeMatrix(A);//Gii phóng vùng nh A
31: return 1;
32: }
33: //Cp phát vùng nh cho ma trn C
34: if (!AllocMatrix(&C,M,N))
35: {
36: cout<<"Khong con du bo nho!"<<endl;
37: FreeMatrix(A);//Gii phóng vùng nh A
38: FreeMatrix(B);//Gii phóng vùng nh B
39: return 1;
40: }
41: cout<<"Nhap ma tran thu 1"<<endl;
42: InputMatrix(A,M,N,'A');
43: cout<<"Nhap ma tran thu 2"<<endl;
44: InputMatrix(B,M,N,'B');
45: clrscr();
46: cout<<"Ma tran thu 1"<<endl;
47: DisplayMatrix(A,M,N);
48: cout<<"Ma tran thu 2"<<endl;
49: DisplayMatrix(B,M,N);
50: AddMatrix(A,B,C,M,N);
51: cout<<"Tong hai ma tran"<<endl;
52: DisplayMatrix(C,M,N);
53: FreeMatrix(A);//Gii phóng vùng nh A
54: FreeMatrix(B);//Gii phóng vùng nh B
55: FreeMatrix(C);//Gii phóng vùng nh C
56: return 0;
57: }
68: //Cng hai ma trn
69: void AddMatrix(int *A,int *B,int*C,int M,int N)
70: {
71: for(int I=0;I<M*N;++I)
72: C[I] = A[I] + B[I];
73: }
74: //Cp phát vùng nh cho ma trn
75: int AllocMatrix(int **A,int M,int N)
76: {
77: *A = new int [M*N];
78: if (*A == NULL)
79: return 0;
80: return 1;
81: }
82: //Gii phóng vùng nh
83: void FreeMatrix(int *A)
84: {
85: if (A!=NULL)
86: delete [] A;
87: }
88: //Nhp các giá tr ca ma trn
89: void InputMatrix(int *A,int M,int N,char Symbol)
90: {
91: for(int I=0;I<M;++I)
92: for(int J=0;J<N;++J)
93 {
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
21
94: cout<<Symbol<<"["<<I<<"]["<<J<<"]=";
95: cin>>A[I*N+J];
96: }
97: }
100: //Hin th ma trn
101: void DisplayMatrix(int *A,int M,int N)
102: {
103: for(int I=0;I<M;++I)
104: {
105: for(int J=0;J<N;++J)
106: {
107: out.width(7);//canh le phai voi chieu dai 7 ky tu
108: cout<<A[I*N+J];
109: }
110: cout<<endl;
111: }
112: }
Chúng ta chy ví du 2.7
, kt qu hình 2.9
Hình 2.9: Kt qu ca ví d 2.7
Mt cách khác đ cp phát mng hai chiu A gm M dòng và N ct nh sau:
int ** A = new int *[M];
int * Tmp = new int[M*N];
for(int I=0;I<M;++I)
{
A[I]=Tmp;
Tmp+=N;
}
//Thao tác trên mng hai chiu A
…………………..
delete [] *A;
delete [] A;
Toán t new còn có mt thun li khác, đó là tt c các li cp phát đng đu có th bt đc bng mt
hàm x lý li do ngi dùng t đnh nghƿa. C++ có đnh nghƿa mt con tr (pointer) tr đn hàm đc bit.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
22
Khi toán t new đc s dng đ cp phát đng và mt li xy ra do cp phát, C++ t gi đn hàm đc ch
bi con tr này. Đnh nghƿa ca con tr này nh sau:
typedef void (*pvf)();
pvf _new_handler(pvf p);
Điu này có nghƿa là con tr _new_handler là con tr tr đn hàm không có tham s và không tr v giá
tr. Sau khi chúng ta đnh nghƿa hàm nh vy và gán đa ch ca nó cho _new_handler chúng ta có th bt
đc tt c các li do cp phát đng.
Ví d 2.8:
1: #include <iostream.h>
2: #include <stdlib.h>
3: #include <new.h>
4:
5: void MyHandler();
6:
7: unsigned long I = 0; 9;
8: void main()
9: {
10: int *A;
11: _new_handler = MyHandler;
12: for( ; ; ++I)
13: A = new int;
14:
15: }
16:
17: void MyHandler()
18: {
19: cout<<"Lan cap phat thu "<<I<<endl;
20: cout<<"Khong con du bo nho!"<<endl;
21: exit(1);
22: }
S dng con tr _new_handler chúng ta phi include file new.h nh dòng 3. Chúng ta chy ví d 2.8
,
kt qu hình 2.10.
Hình 2.10: Kt qu ca ví d 2.8
Th vin cũng còn có mt hàm đc đnh nghƿa trong new.h là hàm có prototype sau :
void ( * set_new_handler(void (* my_handler)() ))();
Hàm set_new_handler() dùng đ gán mt hàm cho _new_handler.
Ví d 2.9:
1: #include <iostream.h>
2: #include <new.h>
3: #include <stdlib.h>
4:
5: void MyHandler();
6:
7: int main(void)
8: {
9:
10: char *Ptr;
11:
12: set_new_handler(MyHandler);
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
23
13: Ptr = new char[64000u];
14: set_new_handler(0); //Thiết lp li giá tr mc định
15: return 0;
16: }
17:
18: void MyHandler()
19: {
20: cout <<endl<<"Khong con du bo nho";
21: exit(1);
22 }
Chúng ta chy ví d 2.9
, kt qu hình 2.11
Hình 2.11: Kt qu ca ví d 2.9
II.10. Hàm inline
Mt chng trình có cu trúc tt s dng các hàm đ chia chng trình thành các đn v đc lp có logic
riêng. Tuy nhiên, các hàm thng phi cha mt lot các xđim vào (entry point): tham s phi đc
đy vào stack, mt lnh gi phi đc thc hin và sau đó vic quay tr v cũng phi đc thc hin bng
cách gii phóng các tham s ra khi stack. Khi các xđim vào chm chp th
ng các lp trình viên C
phi s dng cách chép lp li các đon chng trình nu mun tĕng hiu qu.
Đ tránh khi phi xđim vào, C++ trang b thêm t khóa inline đ loi vic gi hàm. Khi đó trình
biên dch s không biên dch hàm này nh mt đon chng trình riêng bit mà nó s đc chèn thng vào
các ch mà hàm này đc gi. Điu này làm gim vic xđ
im vào mà vn cho phép mt chng trình
đc t chc di dng có cu trúc. Cú pháp ca hàm inline nh sau :
inline data_type function_name ( parameters )
{
……………………………..
}
Trong đó: data_type: Kiu tr v ca hàm.
Function_name:Tên ca hàm.
Parameters: Các tham s ca hàm.
Ví d 2.10:
Tính th tích ca hình lp phng
1: #include <iostream.h>
2: inline float Cube(float S)
3: {
4: return S*S*S;
5: }
6:
7: int main()
8: {
9: cout<<"Nhap vao chieu dai canh cua hinh lap phuong:";
10: float Side;
11: cin>>Side;
12: cout<<"The tich cua hinh lap phuong = "<<Cube(Side);
13: return 0;
14: }
Chúng ta chy ví d 2.10, kt qu hình 2.12
Hình 2.12: Kt qu ca ví d 2.10
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
24
Chú ý:
S dng hàm inline s làm cho chng trình ln lên vì trình biên dch chèn đon chng trình vào các
ch mà hàm này đc gi. Do đó thng các hàm inline thng là các hàm nh, ít phc tp.
Các hàm inline phi đc đnh nghƿa trc khi s dng. ví d 2.10 chúng ta sa li nh sau thì
chng trình s b báo li:
#include <iostream.h>
float Cube(float S);
int main()
{
cout<<"Nhap vao chieu dai canh cua hinh lap phuong:";
float Side;
cin>>Side;
cout<<"The tich cua hinh lap phuong = "<<Cube(Side);
return 0;
}
inline float Cube(float S)
{
return S*S*S;
}
Các hàm đ quy không đc là hàm inline.
II.11. Các giá tr tham s mc đnh
Mt trong các đc tính ni bt nht ca C++ là kh nĕng đnh nghƿa các giá tr tham s mc đnh cho các
hàm. Bình thng khi gi mt hàm, chúng ta cn gi mt giá tr cho mi tham s đã đc đnh nghƿa trong
hàm đó, chng hn chúng ta có đon chng trình sau:
void MyDelay(long Loops); //prototype
………………………………..
void MyDelay(long Loops)
{
for(int I = 0; I < Loops; ++I)
;
}
Mi khi hàm MyDelay() đc gi chúng ta phi gi cho nó mt giá tr cho tham s Loops. Tuy nhiên,
trong nhiu trng hp chúng ta có th nh
n thy rng chúng ta luôn luôn gi hàm MyDelay() vi cùng mt
giá tr Loops nào đó. Mun vy chúng ta s dùng giá tr mc đnh cho tham s Loops, gi s chúng ta mun
giá tr mc đnh cho tham s Loops là 1000. Khi đó đon mã trên đc vit li nh sau :
void MyDelay(long Loops = 1000); //prototype
………………………………..
void MyDelay(long Loops)
{
for(int I = 0; I < Loops; ++I)
;
}
Mi khi gi hàm MyDelay() mà không gi mt tham s tng ng thì trình biên dch s t đng gán cho
tham s Loops giá tr 1000.
MyDelay(); // Loops có giá tr
là 1000
MyDelay(5000); // Loops có giá tr là 5000
Giá tr mc đnh cho tham s có th là mt hng, mt hàm, mt bin hay mt biu thc.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
25
Ví d 2.11:
Tính th tích ca hình hp
1: #include <iostream.h>
2: int BoxVolume(int Length = 1, int Width = 1, int Height = 1);
3:
4: int main()
5: {
6: cout << "The tich hinh hop mac dinh: "
7: << BoxVolume() << endl << endl
8: << "The tich hinh hop voi chieu dai=10,do rong=1,chieu cao=1:"
9: << BoxVolume(10) << endl << endl
10: << "The tich hinh hop voi chieu dai=10,do rong=5,chieu cao=1:"
11: << BoxVolume(10, 5) << endl << endl
12: << "The tich hinh hop voi chieu dai=10,do rong=5,chieu cao=2:"
13: << BoxVolume(10, 5, 2)<< endl;
14: return 0;
15: }
16: //Tính th tích ca hình hp
17: int BoxVolume(int Length, int Width, int Height)
18: {
19: return Length * Width * Height;
20: }
Chúng ta chy ví d 2.11
, kt qu hình 2.13
Hình 2.13: Kt qu ca ví d 2.11
Chú ý:
Các tham s có giá tr mc đnh ch đc cho trong prototype ca hàm và không đc lp li trong
đnh nghƿa hàm (Vì trình biên dch s dùng các thông tin trong prototype ch không phi trong đnh nghƿa
hàm đ to mt lnh gi).
Mt hàm có th có nhiu tham s có giá tr mc đnh. Các tham s có giá tr mc đnh cn phi đc
nhóm li vào các tham s cui cùng (hoc duy nht) ca mt hàm. Khi gi hàm có nhiu tham s có giá tr
mc đnh, chúng ta ch có th b bt các tham s theo th t t phi sang trái và phi b liên tip nhau,
chng hn chúng ta có đon chng trình nh sau:
int MyFunc(int a= 1, int b , int c = 3, int d = 4); //prototype sai!!!
int MyFunc(int a, int b = 2 , int c = 3, int d = 4); //prototype đúng
………………………..
MyFunc(); // Li do tham s
a không có giá tr mc đnh
MyFunc(1);// OK, các tham s b, c và d ly giá tr mc đnh
MyFunc(5, 7); // OK, các tham s c và d ly giá tr mc đnh
MyFunc(5, 7, , 8); // Li do các tham s b b phi liên tip nhau
II.12. Phép tham chiu
Trong C, hàm nhn tham s là con tr đòi hi chúng ta phi thn trng khi gi hàm. Chúng ta cn vit
hàm hoán đi giá tr gia hai s nh sau:
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
26
void Swap(int *X, int *Y);
{
int Temp = *X;
*X = *Y;
*Y = *Temp;
}
Đ hoán đi giá tr hai bin A B thì chúng ta gi hàm nh sau:
Swap(&A, &B);
Rõ ràng cách vit này không đc thun tin lm. Trong trng hp này, C++ đa ra mt kiu bin rt
đc bit gi là bin tham chiu (reference variable). Mt bin tham chiu ging nh là mt bí danh ca bin
khác. Bin tham chiu s làm cho các hàm có thay đi ni dung các tham s ca nó đc vit mt cách thanh
thoát hn. Khi đó hàm Swap() đc vit nh sau:
void Swap(int &X, int &Y);
{
int Temp = X;
X = Y;
Y = Temp ;
}
Chúng ta gi hàm nh sau :
Swap(A, B);
Vi cách gi hàm này, C++ t gi đa ch ca A B làm tham s cho hàm Swap(). Cách dùng bin
tham chiu cho tham s ca C++ tng t nh các tham s đc khai báo là Var trong ngôn ng Pascal.
Tham s này đc gi là tham s kiu tham chiu (reference parameter). Nh vy bin tham chiu có cú
pháp nh sau :
data_type & variable_name;
Trong đó:
data_type: Kiu d liu ca bin.
variable_name: Tên ca bin
Khi dùng bi
n tham chiu cho tham s chđa ch ca nó đc gi đi ch không phi là toàn b cu
trúc hay đi tng đó nh hình 2.14, điu này rt hu dng khi chúng ta gi cu trúc và đi tng ln cho
mt hàm.
Hình 2.14: Mt tham s kiu tham chiu nhn mt tham chiu
ti mt bin đc chuyn cho tham s ca hàm.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
27
Ví d 2.12:
Chng trình hoán đi giá tr ca hai bin.
#include <iostream.h>
//prototype
void Swap(int &X,int &Y);
int main()
{
int X = 10, Y = 5;
cout<<"Truoc khi hoan doi: X = "<<X<<",Y = "<<Y<<endl;
Swap(X,Y);
cout<<"Sau khi hoan doi: X = "<<X<<",Y = "<<Y<<endl;
return 0;
}
void Swap(int &X,int &Y)
{
int Temp=X;
X=Y;
Y=Temp;
}
Chúng ta chy ví d 2.12
, kt qu hình 2.15
Hình 2.15: Kt qu ca ví d 2.12
Đôi khi chúng ta mun gi mt tham s nào đó bng bin tham chiu cho hiu qu, mc dù chúng ta
không mun giá tr ca nó b thay đi thì chúng ta dùng thêm t khóa const nh sau :
int MyFunc(const int & X);
Hàm MyFunc() s chp nhn mt tham s X gi bng tham chiu nhng const xác đnh rng X không
th b thay đi.
Bin tham chiu có th s dng nh mt bí danh ca bin khác (bí danh đn gin nh mt tên khác ca
bin gc), chng hn nh đon mã sau :
int Count = 1;
int & Ref = Count; //To bin Ref nh là mt bí danh ca bin Count
++Ref; //Tĕng bin Count lên 1 (s dng bí danh ca bin Count)
Các bin tham chiu phi đc khi đng trong phn khai báo ca chúng và chúng ta không th gán li
mt bí danh ca bin khác cho chúng. Chng hn đon mã sau là sai:
int X = 1;
int & Y; //Li: Y phi đc khi đng.
Khi mt tham chiu đc khai báo nh mt bí danh ca bin khác, mi thao tác thc hin trên bí danh
chính là thc hin trên bin gc ca nó. Chúng ta có th ly đa ch ca bin tham chiu và có th so sánh các
bin tham chiu vi nhau (phi tng thích v kiu tham chiu).
Ví d 2.13:
Mi thao tác trên trên bí danh chính là thao tác trên bin gc ca nó.
#include <iostream.h>
int main()
{
int X = 3;
int &Y = X; //Y la bí danh ca X
int Z = 100;
cout<<"X="<<X<<endl<<"Y="<<Y<<endl;
Y *= 3;
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
28
cout<<"X="<<X<<endl<<"Y="<<Y<<endl;
Y = Z;
cout<<"X="<<X<<endl<<"Y="<<Y<<endl;
return 0;
}
Chúng ta chy ví d 2.13, kt qu hình 2.16
Hình 2.16: Kt qu ca ví d 2.13
Ví d 2.14:
Ly đa ch ca bin tham chiu
#include <iostream.h>
int main()
{
int X = 3;
int &Y = X; //Y la bí danh ca X
cout<<"Dia chi cua X = "<<&X<<endl;
cout<<"Dia chi cua bi danh Y= "<<&Y<<endl;
return 0;
}
Chúng ta chy ví d 2.14
, kt qu hình 2.17
Hình 2.17: Kt qu ca ví d 2.14
Chúng ta có th to ra bin tham chiu vi vic khi đng là mt hng, chng hn nh đon mã sau :
int & Ref = 45;
Trong trng hp này, trình biên dch to ra mt bin tm thi cha tr hng và bin tham chiu chính là
bí danh ca bin tm thi này. Điu này gi là tham chiu đc lp (independent reference).
Các hàm có th tr v mt tham chiu, nhng điu này rt nguy him. Khi hàm tr v mt tham chiu ti
mt bin cc b ca hàm thì bin này phi đc khai báo là static, ngc li tham chiu ti nó thì khi hàm
kt thúc bin cc b này s b b qua. Chng hn nh đon chng trình sau:
int & MyFunc()
{
static int X = 200; //Nu không khai báo là static thì điu này rt nguy him.
return X;
}
Khi mt hàm tr v mt tham chiu, chúng ta có th gi hàm phía bên trái ca mt phép gán.
Ví d 2.15:
1: #include <iostream.h>
2:
3: int X = 4;
4:
//prototype
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
29
5: int & MyFunc();
6:
7: int main()
8: {
9: cout<<"X="<<X<<endl;
10: cout<<"X="<<MyFunc()<<endl;
11: MyFunc() = 20;
//Nghĩa là X = 20
12: cout<<"X="<<X<<endl;
13: return 0;
14: }
15:
16: int & MyFunc()
17: {
18: return X;
19: }
Chúng ta chy ví d 2.15
, kt qu hình 2.18
Hình 2.18: Kt qu ca ví d 2.15
Chú ý:
Mc dù bin tham chiu trông ging nh là bin con tr nhng chúng không th là bin con tr do đó
chúng không th đc dùng cp phát đng.
Chúng ta không th khai báo mt bin tham chiu ch đn bin tham chiu hoc bin con tr ch đn
bin tham chiu. Tuy nhiên chúng ta có th khai báo mt bin tham chiu v bin con tr nh đon mã sau:
int X;
int *P = &X;
int * & Ref = P;
II.13. Phép đa nĕng hóa (Overloading)
Vi ngôn ng C++, chúng ta có th đa nĕng hóa các hàm và các toán t (operator). Đa nĕng hóa là
phng pháp cung cp nhiu hn mt đnh nghƿa cho tên hàm đã cho trong cùng mt phm vi. Trình biên
dch s la chn phiên bn thích hp ca hàm hay toán t da trên các tham s mà nó đc gi.
II.13.1. Đa nĕng hóa các hàm (Functions overloading)
Trong ngôn ng C cũng nh mi ngôn ng máy tính khác, mi hàm đu phi có mt tên phân bit. Đôi
khi đây là mt điu phin toái. Chng hn nh trong ngôn ng C, có rt nhiu hàm tr v tr tuyt đi ca
mt tham s là s, vì cn thit phi có tên phân bit nên C phi có hàm riêng cho mi kiu d liu s, do vy
chúng ta có ti ba hàm khác nhau đ tr v tr tuyt đ
i ca mt tham s:
int abs(int i);
long labs(long l);
double fabs(double d);
Tt c các hàm này đu cùng thc hin mt cha nĕng nên chúng ta thy điu này nghch lý khi phi có
ba tên khác nhau. C++ gii quyt điu này bng cách cho phép chúng ta to ra các hàm khác nhau có cùng
mt tên. Đây chính là đa nĕng hóa hàm. Do đó trong C++ chúng ta có th đnh nghƿa li các hàm tr v tr
tuyt đi đ thay th các hàm trên nh sau :
int abs(int i);
long abs(long l);
double abs(double d);
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
30
Ví d 2.16:
1: #include <iostream.h>
2: #include <math.h>
3:
4: int MyAbs(int X);
5: long MyAbs(long X);
6: double MyAbs(double X);
7:
8: int main()
9: {
10: int X = -7;
11: long Y = 200000l;
12: double Z = -35.678;
13: cout<<"Tri tuyet doi cua so nguyen (int) "<<X<<" la "
14: <<MyAbs(X)<<endl;
15: cout<<"Tri tuyet doi cua so nguyen (long int) "<<Y<<" la "
16: <<MyAbs(Y)<<endl;
17: cout<<"Tri tuyet doi cua so thuc "<<Z<<" la "
18: <<MyAbs(Z)<<endl;
19: return 0;
20: }
21:
22: int MyAbs(int X)
23: {
24: return abs(X);
25: }
26:
27: long MyAbs(long X)
28: {
29: return labs(X);
30: }
31:
32: double MyAbs(double X)
33: {
34: return fabs(X);
35: }
Chúng ta chy ví d 2.16
, kt qu hình 2.19
Hình 2.19: Kt qu ca ví d 2.16
Trình biên dch da vào s khác nhau v s các tham s, kiu ca các tham s đ có th xác đnh chính
xác phiên bn cài đt nào ca hàm MyAbs() thích hp vi mt lnh gi hàm đc cho, chng hn nh:
MyAbs(-7); //Gi hàm int MyAbs(int)
MyAbs(-7l); //Gi hàm long MyAbs(long)
MyAbs(-7.5); //Gi hàm double MyAbs(double)
Quá trình tìm đc hàm đc đa nĕng hóa cũng là quá trình đc dùng đ gii quyt các trng hp
nhp nhng ca C++. Chng hn nh nu tìm thy mt phiên bn đnh nghƿa nào đó ca mt hàm đc đa
nĕng hóa mà có kiu d liu các tham s ca nó trùng vi kiu các tham s đã gi ti trong lnh gi hàm thì
phiên bn hàm đó s đc gi. Nu không trình biên dch C++ s gi đn phiên bn nào cho phép chuyn
kiu d dàng nht.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
31
MyAbs(‘c’); //Gi int MyAbs(int)
MyAbs(2.34f); //Gi double MyAbs(double)
Các phép chuyn kiu có sn s đc u tiên hn các phép chuyn kiu mà chúng ta to ra (chúng ta s
xem xét các phép chuyn kiu t to chng 3).
Chúng ta cũng có th ly đa ch ca mt hàm đã đc đa nĕng hóa sao cho bng mt cách nào đó chúng
ta có th làm cho trình biên dch C++ bit đc chúng ta cn ly đa ch ca phiên bn hàm nào có trong đnh
nghƿa. Chng hn nh
:
int (*pf1)(int);
long (*pf2)(long);
int (*pf3)(double);
pf1 = MyAbs; //Tr đn hàm int MyAbs(int)
pf2 = MyAbs; //Tr đn hàm long MyAbs(long)
pf3 = MyAbs; //Li!!! (không có phiên bn hàm nào đ đi sánh)
Các gii hn ca vic đa nĕng hóa các hàm:
Bt k hai hàm nào trong tp các hàm đã đa nĕng phi có các tham s khác nhau.
Các hàm đa nĕng hóa vi danh sách các tham s cùng kiu ch da trên kiu tr v ca hàm thì
trình biên dch báo li. Chng hn nh, các khai báo sau là không hp l:
void Print(int X);
int Print(int X);
Không có cách nào đ trình biên dch nhn bit phiên bn nào đc gi nu giá tr tr v b b qua. Nh
vy các phiên bn trong vic đa nĕng hóa phi có s khác nhau ít nht v kiu hoc s tham s mà chúng
nhn đc.
Các khai báo bng lnh typedef không đnh nghƿa kiu mi. Chúng ch thay đi tên gi ca kiu
đã có. Chúng không nh hng ti c ch đa nĕng hóa hàm. Chúng ta hãy xem xét đon mã sau:
typedef char * PSTR;
void Print(char * Mess);
void Print(PSTR Mess);
Hai hàm này có cùng danh sách các tham s, do đó đon mã trên s phát sinh li.
Đi vi kiu mng và con tr đc xem nh đng nht đi v
i s phân bit khác nhau gia các
phiên bn hàm trong vic đa nĕng hóa hàm. Chng hn nh đon mã sau se phát sinh li:
void Print(char * Mess);
void Print(char Mess[]);
Tuy nhiên, đi vi mng nhiu chiu thì có s phân bit gia các phiên bn hàm trong vic đa nĕng hóa
hàm, chng hn nh đon mã sau hp l:
void Print(char Mess[]);
void Print(char Mess[][7]);
void Print(char Mess[][9][42]);
const và các con tr (hay các tham chiu) có th dùng đ phân bit, chng hn nh đon mã sau
hp l:
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
32
void Print(char *Mess);
void Print(const char *Mess);
II.13.2. Đa nĕng hóa các toán t (Operators overloading) :
Trong ngôn ng C, khi chúng ta t to ra mt kiu d liu mi, chúng ta thc hin các thao tác liên quan
đn kiu d liu đó thng thông qua các hàm, điu này tr nên không thoi mái.
Ví d 2.17:
Chng trình cài đt các phép toán cng và tr s phc
1: #include <stdio.h>
2:
/* Định nghĩa s phc */
3: typedef struct
4: {
5: double Real;
6: double Imaginary;
7: }Complex;
8:
9: Complex SetComplex(double R,double I);
10: Complex AddComplex(Complex C1,Complex C2);
11: Complex SubComplex(Complex C1,Complex C2);
12: void DisplayComplex(Complex C);
13:
14: int main(void)
15: {
16: Complex C1,C2,C3,C4;
17:
18: C1 = SetComplex(1.0,2.0);
19: C2 = SetComplex(-3.0,4.0);
20: printf("\nSo phuc thu nhat:");
21: DisplayComplex(C1);
22: printf("\nSo phuc thu hai:");
23: DisplayComplex(C2);
24: C3 = AddComplex(C1,C2);
//Hơi bt tin !!!
25: C4 = SubComplex(C1,C2);
26: printf("\nTong hai so phuc nay:");
27: DisplayComplex(C3);
28: printf("\nHieu hai so phuc nay:");
29: DisplayComplex(C4);
30: return 0;
31: }
32:
33:
/* Đặt giá tr cho mt s phc */
34: Complex SetComplex(double R,double I)
35: {
36: Complex Tmp;
37:
38: Tmp.Real = R;
39: Tmp.Imaginary = I;
40: return Tmp;
41: }
42:
/* Cng hai s phc */
43: Complex AddComplex(Complex C1,Complex C2)
44: {
45: Complex Tmp;
46:
47: Tmp.Real = C1.Real+C2.Real;
48: Tmp.Imaginary = C1.Imaginary+C2.Imaginary;
49: return Tmp;
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
33
50: }
51:
52: /* Tr hai s phc */
53: Complex SubComplex(Complex C1,Complex C2)
54: {
55: Complex Tmp;
56:
57: Tmp.Real = C1.Real-C2.Real;
58: Tmp.Imaginary = C1.Imaginary-C2.Imaginary;
59: return Tmp;
60: }
61:
62:
/* Hin th s phc */
63: void DisplayComplex(Complex C)
64: {
65: printf("(%.1lf,%.1lf)",C.Real,C.Imaginary);
66: }
Chúng ta chy ví d 2.17
, kt qu hình 2.20
Hình 2.20: Kt qu ca ví d 2.17
Trong chng trình ví d 2.17, chúng ta nhn thy vi các hàm va cài đt dùng đ cng và tr hai s
phc 1+2i và –3+4i; ngi lp trình hoàn toàn không thoi mái khi s dng bi vì thc cht thao tác cng và
tr là các toán t ch không phi là hàm. Đ khc phc yu đim này, trong C++ cho phép chúng ta có th
đnh nghƿa li chc nĕng ca các toán t đã có sn mt cách tin l
i và t nhiên hn rt nhiu. Điu này gi
đa nĕng hóa toán t. Khi đó chng trình ví d 2.17 đc vit nh sau:
Ví d 2.18:
1: #include <iostream.h>
2: // Định nghĩa s phc
3: typedef struct
4: {
5: double Real;
6: double Imaginary;
7: }Complex;
8:
9: Complex SetComplex(double R,double I);
10: void DisplayComplex(Complex C);
11: Complex operator + (Complex C1,Complex C2);
12: Complex operator - (Complex C1,Complex C2);
13:
14: int main(void)
15: {
16: Complex C1,C2,C3,C4;
17:
18: C1 = SetComplex(1.0,2.0);
19: C2 = SetComplex(-3.0,4.0);
20: cout<<"\nSo phuc thu nhat:";
21: DisplayComplex(C1);
22: cout<<"\nSo phuc thu hai:";
23: DisplayComplex(C2);
24: C3 = C1 + C2;
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
34
25: C4 = C1 - C2;
26: cout<<"\nTong hai so phuc nay:";
27: DisplayComplex(C3);
28: cout<<"\nHieu hai so phuc nay:";
29: DisplayComplex(C4);
30: return 0;
31: }
32:
33: //Đặt giá tr cho mt s phc
34: Complex SetComplex(double R,double I)
35: {
36: Complex Tmp;
37:
38: Tmp.Real = R;
39: Tmp.Imaginary = I;
40: return Tmp;
41: }
42:
43: //Cng hai s phc
44: Complex operator + (Complex C1,Complex C2)
45: {
46: Complex Tmp;
47:
48: Tmp.Real = C1.Real+C2.Real;
49: Tmp.Imaginary = C1.Imaginary+C2.Imaginary;
50: return Tmp;
51: }
52:
53: //Tr hai s phc
54: Complex operator - (Complex C1,Complex C2)
55: {
56: Complex Tmp;
57:
58: Tmp.Real = C1.Real-C2.Real;
59: Tmp.Imaginary = C1.Imaginary-C2.Imaginary;
60: return Tmp;
61: }
62:
63: //Hin th s phc
64: void DisplayComplex(Complex C)
65: {
66: cout<<"("<<C.Real<<","<<C.Imaginary<<")";
67: }
Chúng ta chy ví d 2.18
, kt qu hình 2.21
Hình 2.21: Kt qu ca ví d 2.18
Nh vy trong C++, các phép toán trên các giá tr kiu s phc đc thc hin bng các toán t toán hc
chun ch không phi bng các tên hàm nh trong C. Chng hn chúng ta có lnh sau:
C4 = AddComplex(C3, SubComplex(C1,C2));
thì trong C++, chúng ta có lnh tng ng nh sau:
C4 = C3 + C1 - C2;
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
35
Chúng ta nhn thy rng c hai lnh đu cho cùng kt qu nhng lnh ca C++ thì d hiu hn. C++ làm
đc điu này bng cách to ra các hàm đnh nghƿa cách thc hin ca mt toán t cho các kiu d liu t
đnh nghƿa. Mt hàm đnh nghƿa mt toán t có cú pháp sau:
data_type operator operator_symbol ( parameters )
{
………………………………
}
Trong đó: data_type: Kiu tr v.
operator_symbol: Ký hiu c
a toán t.
parameters: Các tham s (nu có).
Trong chng trình ví d 2.18, toán t + là toán t gm hai toán hng (gi là toán t hai ngôi; toán t
mt ngôi là toán t ch có mt toán hng) và trình biên dch bit tham s đu tiên là bên trái toán t, còn
tham s th hai thì bên phi ca toán t. Trong trng hp lp trình viên quen thuc vi cách gi hàm,
C++ vn cho phép bng cách vit nh sau:
C3 = operator + (C1,C2);
C4 = operator - (C1,C2);
Các toán t đc đa nĕng hóa s đc l
a chn bi trình biên dch cũng theo cách thc tng t nh
vic chn la gia các hàm đc đa nĕng hóa là khi gp mt toán t làm vic trên các kiu không phi là
kiu có sn, trình biên dch s tìm mt hàm đnh nghƿa ca toán t nào đó có các tham s đi sánh vi các
toán hng đ dùng. Chúng ta s tìm hiu k v vic đa nĕng hóa các toán t trong chng 4.
Các gii hn ca
đa nĕng hóa toán t:
Chúng ta không th đnh nghƿa các toán t mi.
Hu ht các toán t ca C++ đu có th đc đa nĕng hóa. Các toán t sau không đc đa nĕng
hóa là :
Toán t Ý nghƿa
::
Toán t đnh phm vi.
.*
Truy cp đn con tr là trng ca struct hay thành viên ca class.
.
Truy cp đn trng ca struct hay thành viên ca class.
?:
Toán t điu kin
sizeof
và chúng ta cũng không th đa nĕng hóa bt k ký hiu tin x lý nào.
Chúng ta không th thay đi th t u tiên ca mt toán t hay không th thay đi s các toán
hng ca nó.
Chúng ta không th thay đi ý nghƿa ca các toán t khi áp dng cho các kiu có sn.
Đa nĕng hóa các toán t không th có các tham s có giá tr mc đnh.
Các toán t có th đa nĕng hoá:
+ - * / % ^
! = < > += -=
^= &= |= << >> <<=
<= >= && || ++ --
() [] new delete & |
~ *= /= %= >>= ==
!= , -> ->*
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
36
Các toán t đc phân loi nh sau :
Các toán t mt ngôi : * & ~ ! ++ -- sizeof (data_type)
Các toán t này đc đnh nghƿa ch có mt tham s và phi tr v mt giá tr cùng kiu vi tham s ca
chúng. Đi vi toán t sizeof phi tr v mt giá tr kiu size_t (đnh nghƿa trong stddef.h)
Toán t (data_type) đc dùng đ chuyn đi kiu, nó phi tr v mt giá tr có kiu là data_type.
Các toán t hai ngôi: * / % + - >> << > <
>= <= == != & | ^ && ||
Các toán t này đc đnh nghƿa có hai tham s.
Các phép gán: = += -= *= /= %= >>= <<= ^= |=
Các toán t gán đc đnh nghƿa ch có mt tham s. Không có gii hn v kiu ca tham s và kiu tr
v ca phép gán.
Toán t ly thành viên : ->
Toán t ly phn t theo ch s: []
Toán t gi hàm: ()
BÀI TP
Bài 1: Hãy vit li chng trình sau bng cách s dng li các dòng nhp/xut trong C++.
/* Chng trình tìm mu chung nh nht */
#include <stdio.h>
int main()
{
int a,b,i,min;
printf("Nhap vao hai so:");
scanf("%d%d",&a,&b);
min=a>b?b:a;
for(i = 2;i<min;++i)
if (((a%i)==0)&&((b%i)==0)) break;
if(i==min) {
printf("Khong co mau chung nho nhat");
return 0;
}
printf("Mau chung nho nhat la %d\n",i);
return 0;
}
Bài 2: Vit chng trình nhp vào s nguyên dng h (2<h<23), sau đó in ra các tam giác có
chiu cao là h nh các hình sau:
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
37
Bài 3: Mt tam giác vuông có th có tt c các cnh là các s nguyên. Tp ca ba s nguyên ca
các cnh ca mt tam giác vuông đc gi là b ba Pitago. Đó là tng bình phng ca hai cnh
bng bình phng ca cnh huyn, chng hn b ba Pitago (3, 4, 5). Vit chng trình tìm tt c
các b ba Pitago nh th sao cho tt c các cnh không quá 500.
Bài 4: Vit chng trình in bng ca các s t 1 đn 256 di dng nh phân, bát phân và thp lc
phân tng ng.
Bài 5: Vit chng trình nhp vào mt s nguyên dng n. Kim tra xem s nguyên n có thuc
dãy Fibonacci không?
Bài 6: Vit chng trình nhân hai ma trân Amxn
và Bnxp. Mi ma trn đc cp phát đng và
các giá tr ca chúng phát sinh ngu nhiên (Vi m, n và p nhp t bàn phím).
Bài 7: Vit chng trình to mt mng mt chiu đng có kích thc là n (n nhp t bàn phím).
Các giá tr ca mng này đc phát sinh ngu nhiên trên đon [a, b] vi a và b đu nhp t bàn
phím. Hãy tìm s dng nh nht và s âm ln nht trong mng; nu không có s dng nh nht
hoc s âm ln nht thì xut thông báo "không có s dng nh nht" hoc "không có s âm ln
nht".
Bài 8: Anh (ch) hãy vit mt hàm tính bình phng ca mt s. Hàm s tr v giá tr bình
phng ca tham s và có kiu cùng kiu vi tham s.
Bài 9: Trong ngôn ng C, chúng ta có hàm chuyn đi mt chui sang s, tùy thuc vào dng ca
chui chúng ta có các hàm chuyn đi sau :
int atoi(const char *s);
Chuyn đi mt chui s thành s nguyên kiu int.
long atol(const char *s);
Chuyn đi mt chui s thành s nguyên kiu long.
double atof(const char *s);
Chuyn đi mt chui s thành s thc kiu double.
Anh (ch) hãy vit mt hàm có tên là aton (ascii to number) đ chuyn đi chui sang các
dng s tng ng.
Bài 10: Anh ch hãy vit các hàm sau:
Hàm ComputeCircle() đ tính din tích s và chu vi c ca mt đng tròn bán kính
r. Hàm này có prototype nh sau:
void ComputeCircle(float & s, float &c, float r = 1.0);
Hàm ComputeRectangle() đ tính din tích s và chu vi p ca mt hình ch nht có
chiu cao h và chiu rng w. Hàm này có prototype nh sau:
void ComputeRectangle(float & s, float &p, float h = 1.0, float w = 1.0);
Hàm ComputeTriangle() đ tính din tích s và chu vi p ca mt tam giác có ba
cnh a,b và c. Hàm này có prototype nh sau:
void ComputeTriangle(float & s, float &p, float a = 1.0, float b = 1.0, float c
= 1.0);
Hàm ComputeSphere() đ tính th tích v và din tích b mt s ca mt hình cu có
bán kính r. Hàm này có prototype nh sau:
void ComputeSphere(float & v, float &s, float r = 1.0);
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
38
Hàm ComputeCylinder() đ tính th tích v và din tích b mt s ca mt hình tr
có bán kính r và chiu cao h. Hàm này có prototype nh sau:
void ComputeCylinder(float & v, float &s, float r = 1.0 , float h = 1.0);
Bài 11: Anh (ch) hãy vit thêm hai toán t nhân và chia hai s phc ví d 2.18 ca chng 2.
Bài 12: Mt cu trúc Date cha ngày, tháng và nĕm nh sau:
struct Date
{
int Day; //Có giá tr t 1 31
int Month; //Có giá tr t 1 12
int Year; //Biu din bng 4 ch s.
};
Anh (ch) hãy vit các hàm đnh nghƿa các toán t : + - > >= < <= == != trên cu trúc Date này.
Bài 13: Mt cu trúc Point3D biu din ta đ ca mt đim trong không gian ba chiu nh sau:
struct Point3D
{
float X;
float Y;
float Z;
};
Anh (ch) hãy vit các hàm đnh nghƿa các toán t : + - == != trên cu trúc Point3D này.
Bài 14: Mt cu trúc Fraction dùng đ cha mt phân s nh sau:
struct Fraction
{
int Numerator; //T s
int Denominator; //Mu s
};
Anh (ch) hãy vit các hàm đnh nghƿa các toán t :
+ - * / > >= < <= == !=
trên cu trúc Fraction này.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
39
CHƯƠNG 3
LPĐI TNG
I. DN NHP
Bây gi chúng ta bt đu tìm hiu v lp trình hng đi tng trong C++. Trong các phn sau, chúng ta
cũng tìm hiu v các k thut ca thit k hng đi tng (Object-Oriented Design OOD): Chúng ta phân
tích mt vn đ c th, xác đnh các đi tng nào cn đ cài đt h thng, xác đnh các thuc tính nào mà
đi tng phi có, xác đnh hành vi nào mà đi tng cn đa ra, và ch rõ làm th nào các đi tng cn
tng tác vi đi tng khác đ thc hin các mc tiêu tng th ca h thng.
Chúng ta nhc li các khái nim và thut ng chính ca đnh hng đi tng. OOP đóng gói d liu
(các thuc tính) và các hàm (hành vi) thành gói gi là các đối tượng. D liu và các hàm ca đi tng có s
liên h mt thit vi nhau. Các đi tng có các đc tính ca vic che du thông tin. Đi
u này nghƿa là mc
dù các đi tng có th bit làm th nào liên lc vi đi tng khác thông qua các giao din hoàn toàn xác
đnh, bình thng các đi tng không đc phép bit làm th nào các đi tng khác đc thc thi, các chi
tit ca s thi hành đc du bên trong các đi tng.
Trong C và các ngôn ng lp trình th tc, lp trình có khuynh hng đnh hng hành đng, trong khi
ý tng trong lp trình C++ là đnh hng đi tng. Trong C, đn v c
a lp trình là hàm; trong C++, đn
v ca lp trình là lp (class) .
Các lp trình viên C tp trung vào vit các hàm. Các nhóm ca các hành đng mà thc hin vài công
vic đc to thành các hàm, và các hàm đc nhóm thành các chng trình. D liu thì rt quan trng trong
C, nhng quan đim là d liu tn ti chính trong vic h tr các hành đng mà hàm thc hin. Các đng t
trong mt h thng giúp cho lp trình viên C xác đnh tp các hàm mà s hot đng cùng v
i vic thc thi h
thng.
Các lp trình viên C++ tp trung vào vic to ra "các kiu do ngi dùng đnh nghƿa" (user-defined
types) gi là các lp. Các lp cũng đc tham chiu nh "các kiu do lp trình viên đnh nghƿa"
(programmer-defined types). Mi lp cha d liu cũng nh tp các hàm mà x lý d liu. Các thành phn
d liu ca mt lp đc gi là "các thành viên d liu" (data members). Các thành phn hàm ca mt l
p
đc gi là "các hàm thành viên" (member functions). Ging nh thc th ca kiu có sn nh int đc gi
là mt bin, mt thc th ca kiu do ngi dùng đnh nghƿa (nghƿa là mt lp) đc gi là mt đi tng.
Các danh t trong mt h thng giúp cho lp trình viên C++ xác đnh tp các lp. Các lp này đc s dng
đ to các đi tng mà s s ho
t đng cùng vi vic thc thi h thng.
Các lp trong C++ đc tin hóa t nhiên ca khái nim struct trong C. Trc khi tin hành vic trình
bày các lp trong C++, chúng ta tìm hiu v cu trúc, và chúng ta xây dng mt kiu do ngi dùng đnh
nghƿa da trên mt cu trúc.
II. CÀI ĐT MT KIU DO NGI DÙNG ĐNH NGHƾA VI MT struct
Ví d 3.1:
Chúng ta xây dng kiu cu trúc Time vi ba thành viên s nguyên: Hour, Minutesecond.
Chng trình đnh nghƿa mt cu trúc Time gi là DinnerTime. Chng trình in thi gian di dng gi quân
đi và dng chun.
#include <iostream.h>
struct Time
{
int Hour; // 0-23
int Minute; // 0-59
int Second; // 0-59
};
void PrintMilitary(const Time &); //prototype
void PrintStandard(const Time &); //prototype
int main()
{
Time DinnerTime;
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
40
//Thiet lap cac thanh vien voi gia tri hop le
DinnerTime.Hour = 18;
DinnerTime.Minute = 30;
DinnerTime.Second = 0;
cout << "Dinner will be held at ";
PrintMilitary(DinnerTime);
cout << " military time," << endl << "which is ";
PrintStandard(DinnerTime);
cout << " standard time." << endl;
//Thiet lap cac thanh vien voi gia tri khong hop le
DinnerTime.Hour = 29;
DinnerTime.Minute = 73;
DinnerTime.Second = 103;
cout << endl << "Time with invalid values: ";
PrintMilitary(DinnerTime);
cout << endl;
return 0;
}
//In thoi gian duoi dang gio quan doi
void PrintMilitary(const Time &T)
{
cout << (T.Hour < 10 ? "0" : "") << T.Hour << ":"
<< (T.Minute < 10 ? "0" : "") << T.Minute << ":"
<< (T.Second < 10 ? "0" : "") << T.Second;
}
//In thoi gian duoi dang chuan
void PrintStandard(const Time &T)
{
cout << ((T.Hour == 12) ? 12 : T.Hour % 12)
<< ":" << (T.Minute < 10 ? "0" : "") << T.Minute
<< ":" << (T.Second < 10 ? "0" : "") << T.Second
<< (T.Hour < 12 ? " AM" : " PM");
}
Chúng ta chy ví d 3.1
, kt qu hình 3.1
Hình 3.1: Kt qu ca ví d 3.1
Có mt vài hn ch khi to các kiu d liu mi vi các cu trúc phn trên. Khi vic khi to không
đc yêu cu, có th có d liu cha khi to và các vn đ ny sinh. Ngay c nu d liu đc khi to, nó
có th khi to không chính xác. Các giá tr không hp l có th đc gán cho các thành viên ca mt cu
trúc b
i vì chng trình trc tip truy cp d liu. Chng hn ví d 3.1 dòng 23 đn dòng 25, chng
trình gán các giá tr không hp l cho đi tng DinnerTime. Nu vic cài đt ca struct thay đi, tt c các
chng trình s dng struct phi thay đi. Điu này do lp trình viên trc tip thao tác kiu d liu. Không
có "giao din" đ bo đm lp trình viên s dng d
liu chính xác và bo đm d liu còn li trng thái
thích hp. Mt khác, cu trúc trong C không th đc in nh mt đn v, chúng đc in khi các thành viên
đc in. Các cu trúc trong C không th so sánh vi nhau, chúng phi đc so sánh thành viên vi thành
viên.
Phn sau cài đt li cu trúc Time ví d 3.1 nh mt lp và chng minh mt s thun li đ vic to ra
cái gi là các kiu d liu tru t
ng (Abstract Data Types – ADT) nh các lp. Chúng ta s thy rng các
lp và các cu trúc có th s dng gn nh ging nhau trong C++. S khác nhau gia chúng là thuc tính
truy cp các thành viên.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
41
III. CÀI ĐT MT KIU D LIU TRU TNG VI MT LP
Các lp cho phép lp trình viên mô hình các đi tng mà có các thuc tính (biu din nh các thành
viên d liu – Data members) và các hành vi hoc các thao tác (biu din nh các hàm thành viên – Member
functions). Các kiu cha các thành viên d liu và các hàm thành viên đc đnh nghƿa thông thng trong
C++ s dng t khóa class, có cú pháp nh sau:
class <class-name>
{
<member-list> //Thân ca lp
};
Trong đó:
class-name: tên lp.
member-list: đc t các thành viên d liu và các hàm thành viên.
Các hàm thành viên đôi khi đc gi là các phng thc (methods) trong các ngôn ng lp trình hng
đi t
ng khác, và đc đa ra trong vic đáp ng các message gi ti mt đi tng. Mt message tng
ng vi vic gi hàm thành viên.
Khi mt lp đc đnh nghƿa, tên lp có th đc s dng đ khai báo đi tng ca lp theo cú pháp
sau:
<class-name> <object-name>;
Chng hn, cu trúc Time s đc đnh nghƿa di dng lp nh sau:
class Time
{
public:
Time();
void SetTime(int, int, int)
void PrintMilitary();
void PrintStandard()
private:
int Hour; // 0 - 23
int Minute; // 0 - 59
int Second; // 0 - 59
};
Trong đnh nghƿa l
p Time cha ba thành viên d liu là Hour, Minute và Second, và cũng trong lp
này, chúng ta thy các nhãn publicprivate đc gi là các thuc tính xác đnh truy cp thành viên
(member access specifiers) gi tt là thuc tính truy cp.
Bt k thành viên d liu hay hàm thành viên khai báo sau public có th đc truy cp bt k ni nào
mà chng trình truy cp đn mt đi tng ca lp. Bt k thành viên d liu hay hàm thành viên khai báo
sau private ch có th đc truy cp bi các hàm thành viên ca l
p. Các thuc tính truy cp luôn luôn kt
thúc vi du hai chm (:) và có th xut hin nhiu ln và theo th t bt k trong đnh nghƿa lp. Mc đnh
thuc tính truy cp là private.
Đnh nghƿa lp cha các prototype ca bn hàm thành viên sau thuc tính truy cp public là Time(),
SetTime(), PrintMilitary() và PrintStandard(). Đó là các hàm thành viên public (public member function)
hoc giao din (interface) ca lp. Các hàm này s đc s dng bi các client (nghƿa là các phn ca mt
ch
ng trình mà là các ngi dùng) ca lp x lý d liu ca lp. Có th nhn thy trong đnh nghƿa lp
Time, hàm thành viên Time() có cùng tên vi tên lp Time, nó đc gi là hàm xây dng (constructor
function) ca lp Time.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
42
Mt constructor là mt hàm thành viên đc bit mà khi đng các thành viên d liu ca mt đi tng
ca lp. Mt constructor ca lp đc gi t đng khi đi tng ca lp đó đc to.
Thông thng, các thành viên d liu đc lit kê trong phn private ca mt lp, còn các hàm thành
viên đc lit kê trong phn public. Nhng có th có các hàm thành viên private và thành viên d liu
public.
Khi l
p đc đnh nghƿa, nó có th s dng nh mt kiu trong phn khai báo nh sau:
Time Sunset, // Đi tng ca lp Time
ArrayTimes[5], // Mng các đi tng ca lp Time
*PTime, // Con tr tr đn mt đi tng ca lp Time
&DinnerTime = Sunset; // Tham chiu đn mt đi tng ca lp Time
Ví d 3.2
: Xây dng li lp Time ví d 3.1
1: #include <iostream.h>
2:
3: class Time
4: {
5: public:
6: Time(); //Constructor
7: void SetTime(int, int, int); //Thiết lp Hour, Minute va Second
8: void PrintMilitary(); //In thi gian dưới dng gi quân đội
9: void PrintStandard(); //In thi gian dưới dng chun
10: private:
11: int Hour; // 0 - 23
12: int Minute; // 0 - 59
13: int Second; // 0 - 59
14: };
15:
16: //Constructor khi to mi thành viên DL vi giá tr zero
17: //Bo đảm tt c các đối tượng bt đầu mt t.thái thích hp
18: Time::Time()
19: {
20: Hour = Minute = Second = 0;
21: }
22:
23: //Thiết lp mt giá tr Time mi s dng gi quânđội
24: //Thc hin vic kim tra tính h
p l trên các giá tr d liu
25: //Thiết lp các giá tr không hp l thành zero
26: void Time::SetTime(int H, int M, int S)
27: {
28: Hour = (H >= 0 && H < 24) ? H : 0;
29: Minute = (M >= 0 && M < 60) ? M : 0;
30: Second = (S >= 0 && S < 60) ? S : 0;
31: }
32:
33: //In thi gian dưới dng gi quân đội
34: void Time::PrintMilitary()
35: {
36: cout << (Hour < 10 ? "0" : "") << Hour << ":"
37: << (Minute < 10 ? "0" : "") << Minute << ":"
38: << (Second < 10 ? "0" : "") << Second;
39: }
40:
41: //In thi gian dưới dng chun
42: void Time::PrintStandard()
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
43
43: {
44: cout << ((Hour == 0 || Hour == 12) ? 12 : Hour % 12)
44: << ":" << (Minute < 10 ? "0" : "") << Minute
45: << ":" << (Second < 10 ? "0" : "") << Second
46: << (Hour < 12 ? " AM" : " PM");
48: }
49:
50: int main()
51: {
52: Time T; //Đối tượng T ca lp Time
53:
54: cout << "The initial military time is ";
55: T.PrintMilitary();
56: cout << endl << "The initial standard time is ";
57: T.PrintStandard();
58:
59: T.SetTime(13, 27, 6);
60: cout << endl << endl << "Military time after SetTime is ";
61: T.PrintMilitary();
62: cout << endl << "Standard time after SetTime is ";
63: T.PrintStandard();
64:
65: T.SetTime(99, 99, 99); //Th thiết lp giá tr không hp l
66: cout << endl << endl << "After attempting invalid settings:"
67: << endl << "Military time: ";
68: T.PrintMilitary();
69: cout << endl << "Standard time: ";
70: T.PrintStandard();
71: cout << endl;
72: return 0;
73: }
Chúng ta chy ví d 3.2
, kt qu hình 3.2
Hình 3.2: Kt qu ca ví d 3.2
Trong ví d 3.2, chng trình thuyt minh mt đi tng ca lp Time gi là T (dòng 52). Khi đó
constructor ca lp Time t đng gi và rõ ràng khi to mi thành viên d liu private là zero. Sau đó thi
gian đc in di dng gi quân đi và dng chun đ xác nhn các thành viên này đc khi to thích hp
(dòng 54 đn 57). K ti thi gian đ
c thit lp bng cách s dng hàm thành viên SetTime() (dòng 59) và
thi gian li đc in hai dng (dòng 60 đn 63). Cui cùng hàm thành viên SetTime() (dòng 65) th thit
lp các thành viên d liu vi các giá tr không hp l, và thi gian li đc in hai dng (dòng 66 đn 70).
Chúng ta nhn thy rng, tt c các thành viên d liu ca mt lp không th khi to ti ni mà chúng
đc khai báo trong thân lp. Các thành viên d liu này ph
i đc khi to bi constructor ca lp hay
chúng có th gán giá tr bi các hàm thit lp.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
44
Khi mt lp đc đnh nghƿa và các hàm thành viên ca nó đc khai báo, các hàm thành viên này phi
đc đnh nghƿa. Mi hàm thành viên ca lp có th đc đnh nghƿa trc tip trong thân lp (hin nhiên bao
gm prototype hàm ca lp), hoc hàm thành viên có th đc đnh nghƿa sau thân lp. Khi mt hàm thành
viên đc đnh nghƿa sau đnh nghƿa lp tng ng, tên hàm đc đt trc bi tên lp và toán t đnh phm
vi (::
). Chng hn nh ví d 3.2 gm các dòng 18, 26, 34 và 42. Bi vì các lp khác nhau có th có các tên
thành viên ging nhau, toán t đnh phm vi "ràng buc" tên thành viên ti tên lp đ nhn dng các hàm
thành viên ca mt lp.
Mc dù mt hàm thành viên khai báo trong đnh nghƿa mt lp có th đnh nghƿa bên ngoài đnh nghƿa
lp này, hàm thành viên đó vn còn bên trong phm vi ca lp, nghƿa là tên ca nó ch đc bit ti các
thành viên khác ca lp ngo
i tr tham chiu thông qua mt đi tng ca lp, mt tham chiu ti mt đi
tng ca lp, hoc mt con tr tr ti mt đi tng ca lp.
Nu mt hàm thành viên đc đnh nghƿa trong đnh nghƿa mt lp, hàm thành viên này chính là hàm
inline. Các hàm thành viên đnh nghƿa bên ngoài đnh nghƿa mt lp có th là hàm inline bng cách s dng
t khóa inline.
Hàm thành viên cùng tên vi tên l
p nhng đt trc là mt ký t ngã (~) đc gi là destructor ca lp
này. Hàm destructor làm "công vic ni tr kt thúc" trên mi đi tng ca lp trc khi vùng nh cho đi
tng đc phc hi bi h thng.
Ví d 3.3
: Ly li ví d 3.2 nhng hai hàm PrintMilitary() và PrintStandard() là các hàm inline.
1: #include <iostream.h>
2:
3: class Time
4: {
5: public:
6: Time(); ;
//Constructor
7: void SetTime(int, int, int); //Thiết lp Hour, Minute va
Second
8: void PrintMilitary() // In thi gian dưới dng gi quânđội
9: {
10: cout << (Hour < 10 ? "0" : "") << Hour << ":"
11: << (Minute < 10 ? "0" : "") << Minute << ":"
12: << (Second < 10 ? "0" : "") << Second;
13: }
14: void PrintStandard();
// In thi gian dưới dng chun
15: private:
16: int Hour;
// 0 - 23
17: int Minute;
// 0 - 59
18: int Second; // 0 - 59
19: };
20: //Constructor khi to mi thành viên d liu vi giá tr zero
21: //Bo đảm t.c các đối tượng bt đầu mt trng thái thích hp
22: Time::Time()
23: {
24: Hour = Minute = Second = 0;
25: }
26:
27: #9;
//Thiết lp mt giá tr Time mi s dng gi quân đội
28: #9; //T.hin vic k.tra tính hp l trên các giá tr DL
29: #9; //Thiết lp các giá tr không hp l thành zero
30: void Time::SetTime(int H, int M, int S)
31: {
32: Hour = (H >= 0 && H < 24) ? H : 0;
33: Minute = (M >= 0 && M < 60) ? M : 0;
34: Second = (S >= 0 && S < 60) ? S : 0;
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
45
35: }
36:
37: #9;
//In thi gian dưới dng chun
38: inline void Time::PrintStandard()
39: {
40: cout << ((Hour == 0 || Hour == 12) ? 12 : Hour % 12)
41: << ":" << (Minute < 10 ? "0" : "") << Minute
42: << ":" << (Second < 10 ? "0" : "") << Second
43: << (Hour < 12 ? " AM" : " PM");
44: }
45:
46: int main()
47: {
48: Time T;
49:
50: cout << "The initial military time is ";
51: T.PrintMilitary();
52: cout << endl << "The initial standard time is ";
53: T.PrintStandard();
54:
55: T.SetTime(13, 27, 6);
56: cout << endl << endl << "Military time after SetTime is ";
57: T.PrintMilitary();
58: cout << endl << "Standard time after SetTime is ";
59: T.PrintStandard();
60:
61: T.SetTime(99, 99, 99);
//Th thiết lp giá tr không hp l
62: cout << endl << endl << "After attempting invalid settings:"
63: << endl << "Military time: ";
64: T.PrintMilitary();
65: cout << endl << "Standard time: ";
66: T.PrintStandard();
67: cout << endl;
68: return 0;
69: }
Chúng ta chy ví d 3.3
, kt qu hình 3.3
Hình 3.3: Kt qu ca ví d 3.3
IV. PHM VI LP VÀ TRUY CP CÁC THÀNH VIÊN LP
Các thành viên d liu ca mt lp (các bin khai báo trong đnh nghƿa lp) và các hàm thành viên (các
hàm khai báo trong đnh nghƿa lp) thuc vào phm vi ca lp.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
46
Trong mt phm vi lp, các thành viên ca lp đc truy cp ngay lp tc bi tt c các hàm thành viên
ca lp đó và có th đc tham chiu mt cách d dàng bi tên. Bên ngoài mt phm vi lp, các thành viên
ca lp đc tham chiu thông qua hoc mt tên đi tng, mt tham chiu đn mt đi tng, hoc mt
con tr ti đi tng.
Các hàm thành viên ca lp có th đc
đa nĕng hóa (overload), nhng ch bi các hàm thành viên khác
ca lp. Đ đa nĕng hóa mt hàm thành viên, đn gin cung cp trong đnh nghƿa lp mt prototype cho mi
phiên bn ca hàm đa nĕng hóa, và cung cp mt đnh nghƿa hàm riêng bit cho mi phiên bn ca hàm.
Các hàm thành viên có phm vi hàm trong mt lp – các bin đnh nghƿa trong mt hàm thành viên ch
đc bit ti hàm đó. Nu mt hàm thành viên đnh nghƿa mt bin cùng tên v
i tên mt bin trong phm vi
lp, bin phm vi lp đc du bi bin phm vi hàm bên trong phm vi hàm. Nh th mt bin b du có
th đc truy cp thông qua toán t đnh phm vi.
Các toán t đc s dng đ truy cp các thành viên ca lp đc đng nht vi các toán t s dng đ
truy cp các thành viên ca cu trúc. Toán t la chn thành viên d
u chm (.) đc kt hp vi mt tên ca
đi tng hay vi mt tham chiu ti mt đi tng đ truy cp các thành viên ca đi tng. Toán t la
chn thành viên mũi tên (->)đc kt hp vi mt con tr tr ti mt truy cp đ truy cp các thành viên ca
đi tng.
Ví d 3.4:
Chng trình sau minh ha vic truy cp các thành viên ca mt lp vi các toán t la chn
thành viên.
1: #include <iostream.h>
2:
3: class Count
4: {
5: public:
6: int X;
7: void Print()
8: {
9: cout << X << endl;
10: }
11: };
12:
13: int main()
14: {
15: Count Counter, //To đối tượng Counter
16: *CounterPtr = &Counter, //Con tr tr ti Counter
17: &CounterRef = Counter; //Tham chiếu ti Counter
18:
19: cout << "Assign7 to X and Print using the object's name: ";
20: Counter.X = 7; //Gán 7 cho thành viên d liu X
21: Counter.Print(); //Gi hàm thành viên Print
22:
23: cout << "Assign 8 to X and Print using a reference: ";
24: CounterRef.X = 8; //Gán 8 cho thành viên d liu X
25: CounterRef.Print(); //Gi hàm thành viên Print
26:
27: cout << "Assign 10 to X and Print using a pointer: ";
28: CounterPtr->X = 10; // Gán 10 cho thành viên d liu X
29: CounterPtr->Print(); //Gi hàm thành viên Print
30: return 0;
31: }
Chúng ta chy ví d 3.4
, kt qu hình 3.4
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
47
Hình 3.4: Kt qu ca ví d 3.4
V. ĐIU KHIN TRUY CP TI CÁC THÀNH VIÊN
Các thuc tính truy cp public private (và protected chúng ta s xem xét sau) đc s dng đ điu
khin truy cp ti các thành viên d liu và các hàm thành viên ca lp. Ch đ truy cp mc đnh đi vi
lp là private vì th tt c các thành viên sau phn header ca lp và trc nhãn đu tiên là private. Sau mi
nhãn, ch đđc kéo theo bi nhãn đó áp dng cho đn khi gp nhãn k tip ho
c cho đn khi gp du
móc phi (}) ca phn đnh nghƿa lp. Các nhãn public, private protected có th đc lp li nhng cách
dùng nh vy thì him có và có th gây khó hiu.
Các thành viên private ch có th đc truy cp bi các hàm thành viên (và các hàm friend) ca lp đó.
Các thành viên public ca lp có th đc truy cp bi bt k hàm nào trong chng trình.
Mc đích chính ca các thành viên public đ bi
u th cho client ca lp mt cái nhìn ca các dch v
(services) mà lp cung cp. Tp hp này ca các dch v hình thành giao din public ca lp. Các client ca
lp không cn quan tâm làm th nào lp hoàn thành các thao tác ca nó. Các thành viên private ca lp
cũng nh các đnh nghƿa ca các hàm thành viên public ca nó thì không phi có th truy cp ti client ca
mt lp. Các thành phn này hình thành s thi hành ca lp.
Ví d 3.5:
Chng trình sau cho thy rng các thành viên private ch có th truy cp thông qua giao
din public s dng các hàm thành viên public.
#include <iostream.h>
class MyClass
{
private:
int X,Y;
public:
void Print();
};
void MyClass::Print()
{
cout <<X<<Y<<endl;
}
int main()
{
MyClass M;
M.X = 3;
M.Y = 4;
M.Print();
return 0;
}
Khi chúng ta biên dch chng trình này, compiler phát sinh ra hai li ti hai dòng 20 và 21
nh sau:
Hình 3.5: Thông báo li ca ví d 3.5
Thuc tính truy cp mc đnh đi vi các thành viên ca lp là private. Thuc tính truy cp các thành
viên ca mt lp có th đc thit lp rõ ràng là public, protected hoc private. Thuc tính truy cp mc
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
48
đnh đi vi các thành viên ca struct public. Thuc tính truy cp các thành viên ca mt struct cũng có
th đc thit lp rõ ràng là public, protected hoc private.
Truy cp đn mt d liu private cn phi đc điu khin cn thn bi vic s dng ca các hàm thành
viên, gi là các hàm truy cp (access functions).
VI. CÁC HÀM TRUY CP VÀ CÁC HÀM TIN ÍCH
Không phi tt c các hàm thành viên đu là public đ phc v nh b phn giao din ca mt lp. Mt
vài hàm còn li là private và phc v nh các hàm tin ích (utility functions) cho các hàm khác ca lp.
Các hàm truy cp có th đc hay hin th d liu. S dng các hàm truy cp đ kim tra tính đúng hoc
sai ca các điu kin – các hàm nh th thng đc gi là các hàm khng đnh (predicate functions). Mt ví
d ca hàm khng đnh là mt hàm IsEmpty() ca lp container - mt lp có kh nĕng gi nhiu đi tng -
ging nh mt danh sách liên kt, mt stack hay mt hàng đi. Mt chng trình s kim tra hàm IsEmpty()
trc khi th đc mc khác t đi tng container.
Mt hàm tin ích không là mt phn ca mt giao din ca lp. Hn na nó là mt hàm thành viên
private
mà h tr các thao tác ca các hàm thành viên public. Các hàm tin ích không d đnh đc s dng
bi các client ca lp.
Ví d 3.6:
Minh ha cho các hàm tin ích.
1: #include <iostream.h>
2: #include <iomanip.h>
3:
4: class SalesPerson
5: {
6: public:
7: SalesPerson(); //constructor
8: void SetSales(int, double);//Ng.dùng cung cp các hình ca
9: #9; #9; //nhng hàng bán ca mt tháng
10: void PrintAnnualSales();
11:
12: private:
13: double Sales[12]; //12 hình ca nhng hàng bán hng tháng
14: double TotalAnnualSales(); //Hàm tin ích
15: };
16:
17: //Hàm constructor khi to mng
18: SalesPerson::SalesPerson()
19: {
20: for (int I = 0; I < 12; I++)
21: Sales[I] = 0.0;
22: }
23:
24://Hàm th.lp mt trong 12 hình ca nhng hàng bán hng tháng
25: void SalesPerson::SetSales(int Month, double Amount)
26: {
27: if (Month >= 1 && Month <= 12 && Amount > 0)
28: Sales[Month - 1] = Amount;
29: else
30: cout << "Invalid month or sales figure" << endl;
31: }
32:
33: //Hàm tin íchđ tính tng hàng bán hng năm
34: double SalesPerson::TotalAnnualSales()
35: {
36: double Total = 0.0;
37:
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
49
38: for (int I = 0; I < 12; I++)
39: Total += Sales[I];
40: return Total;
41: }
42:
43: //In tng hàng bán hng năm
44: void SalesPerson::PrintAnnualSales()
45: {
46: cout << setprecision(2)
47: << setiosflags(ios::fixed | ios::showpoint)
48: << endl << "The total annual sales are: $"
49: << TotalAnnualSales() << endl;
50: }
51:
52: int main()
53: {
54: SalesPerson S;
55: double salesFigure;
56:
57: for (int I = 1; I <= 12; I++)
58: {
59: cout << "Enter sales amount for month "<< I << ": ";
60: cin >> salesFigure;
61: S.SetSales(I, salesFigure);
62: }
63: S.PrintAnnualSales();
64: return 0;
65: }
Chúng ta chy ví d 3.6
, kt qu hình 3.6
Hình 3.6: Kt qu ca ví d 3.6
VII. KHI ĐNG CÁC ĐI TNG CA LP : CONSTRUCTOR
Khi mt đi tng đc to, các thành viên ca nó có th đc khi to bi mt hàm constructor. Mt
constructor là mt hàm thành viên vi tên ging nh tên ca lp. Lp trình viên cung cp constructor mà
đc gi t đng mi khi đi tng ca lp đó đc to. Các thành viên d liu ca mt lp không th đc
khi to trong đnh nghƿa ca lp. Hn na, các thành viên d li
u phi đc khi đng hoc trong mt
constructor ca lp hoc các giá tr ca chúng có th đc thit lp sau sau khi đi tng đc to. Các
constructor không th mô t các kiu tr v hoc các giá tr tr v. Các constructor có th đc đa nĕng hóa
đ cung cp s đa dng đ khi to các đi tng ca lp.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
50
Constructor có th cha các tham s mc đnh. Bng cách cung cp các tham s mc đnh cho
constructor, ngay c nu không có các giá tr nào đc cung cp trong mt constructor thì đi tng vn
đc bo đm đ trong mt trng thái phù hp vì các tham s mc đnh. Mt constructor ca lp trình viên
cung cp mà hoc tt c các tham s ca nó có giá tr mc đnh hoc không có tham s nào đc gi là
constructor mc đnh (default constructor). Ch có th
có mt constructor mc đnh cho mi lp.
Ví d 3.7:
Constructor vi các tham s mc đnh
#include <iostream.H>
class Time
{
public:
Time(int = 0, int = 0, int = 0); //Constructor mac dinh
void SetTime(int, int, int);
void PrintMilitary();
void PrintStandard();
private:
int Hour;
int Minute;
int Second;
};
//Ham constructor de khoi dong du lieu private
//Cac gia tri mac dinh la 0
Time::Time(int Hr, int Min, int Sec)
{
SetTime(Hr, Min, Sec);
}
//Thiet lap cac gia tri cua Hour, Minute va Second
//Gia tri khong hop le duoc thiet lap la 0
void Time::SetTime(int H, int M, int S)
{
Hour = (H >= 0 && H < 24) ? H : 0;
Minute = (M >= 0 && M < 60) ? M : 0;
Second = (S >= 0 && S < 60) ? S : 0;
}
//Hien thi thoi gian theo dang gio quan doi: HH:MM:SS
void Time::PrintMilitary()
{
cout << (Hour < 10 ? "0" : "") << Hour << ":"
<< (Minute < 10 ? "0" : "") << Minute << ":"
<< (Second < 10 ? "0" : "") << Second;
}
//Hien thi thoi gian theo dang chuan: HH:MM:SS AM (hoac PM)
void Time::PrintStandard()
{
cout << ((Hour == 0 || Hour == 12) ? 12 : Hour % 12)
<< ":" << (Minute < 10 ? "0" : "") << Minute
<< ":" << (Second < 10 ? "0" : "") << Second
<< (Hour < 12 ? " AM" : " PM");
}
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
51
int main()
{
Time T1,T2(2),T3(21,34),T4(12,25,42),T5(27,74,99);
cout << "Constructed with:" << endl << "all arguments defaulted:" << endl << " ";
T1.PrintMilitary(); cout << endl << " ";
T1.PrintStandard();
cout << endl << "Hour specified; Minute and Second defaulted:" << endl << " ";
T2.PrintMilitary(); cout << endl << " ";
T2.PrintStandard();
cout << endl << "Hour and Minute specified; Second defaulted:" << endl << " ";
T3.PrintMilitary(); cout << endl << " ";
T3.PrintStandard(); cout << endl << "Hour, Minute, and Second specified:"<<endl<<" ";
T4.PrintMilitary(); cout << endl << " ";
T4.PrintStandard(); cout << endl << "all invalid values specified:" << endl << " ";
T5.PrintMilitary(); cout << endl << " ";
T5.PrintStandard(); cout << endl;
return 0;
}
Chng trình ví d 3.7 khi to nĕm đi tng ca lp Time ( dòng 52). Đi tng T1 vi ba tham s
ly giá tr mc đnh, đi tng T2 vi mt tham s đc mô t, đi tng T3 vi hai tham s đc mô t, đi
tng T4 vi ba tham s đc mô tđi tng T5 vi các tham s có giá tr không hp l.
Chúng ta chy ví d 3.7
, kt qu hình 3.7
Hình 3.7: Kt qu ca ví d 3.7
Nu không có constructor nào đc đnh nghƿa trong mt lp thì trình biên dch to mt constructor mc
đnh. Constructor này không thc hin bt k s khi to nào, vì vy khi đi tng đc to, nó không bo
đm đ trong mt trng thái phù hp.
VIII. S DNG DESTRUCTOR
Mt destructor là mt hàm thành viên đc bit ca mt lp. Tên ca destructor đi vi mt lp là ký t
ngã (~) theo sau bi tên lp.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
52
Destructor ca mt lp đc gi khi đi tng đc hy b nghƿa là khi s thc hin chng trình ri
khi phm vi mà trong đó đi tng ca lp đó đc khi to. Destructor không thc s hy b đi tng –
nó thc hin "công vic ni tr kt thúc" trc khi h thng phc hi không gian b nh ca đi tng
đ
có th đc s dng gi các đi tng mi.
Mt destructor không nhn các tham s và không tr v giá tr. Mt lp ch có duy nht mt destructor –
đa nĕng hóa destructor là không cho phép.
Nu trong mt lp không có đnh nghƿa mt destructor thì trình biên dch s to mt destructor mc đnh
không làm gì c.
Ví d 3.8:
Lp có hàm destructor
#include <iostream.h>
class Simple
{private:
int *X;
public:
Simple(); //Constructor
~Simple(); //Destructor
void SetValue(int V);
int GetValue();
};
Simple::Simple()
{ X = new int; //Cp phát vùng nh cho X
}
Simple::~Simple()
{
delete X; //Gii phóng vùng nh khi đối tượng b hy b.
}
void Simple::SetValue(int V)
{
*X = V;
}
int Simple::GetValue()
{
return *X;
}
int main()
{
Simple S;
int X;
cout<<"Enter a number:";
cin>>X;
S.SetValue(X);
cout<<"The value of this number:"<<S.GetValue();
return 0;
}
Chúng ta chy ví d 3.8
, kt qu hình 3.8
Hình 3.8: Kt qu ca ví d 3.8
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
53
IX. KHI NÀO CÁC CONSTRUTOR VÀ DESTRUCTOR ĐC GI ?
Các constructor và destructor đc gi mt cách t đng. Th t các hàm này đc gi ph thuc vào
th t trong đó s thc hin vào và ri khi phm vi mà các đi tng đc khi to. Mt cách tng quát,
các destructor đc gi theo th t ngc vi th t ca các constructor đc gi.
Các constructor đc gi ca các đi tng khai báo trong phm vi toàn cc trc bt k hàm nào (bao
g
m hàm main()) trong file mà bt đu thc hin. Các destructor tng ng đc gi khi hàm main() kt
thúc hoc hàm exit() đc gi.
Các constructor ca các đi tng cc b t đng đc gi khi s thc hin đn đim mà các đi tng
đc khai báo. Các destructor tng ng đc gi khi các đi tng ri khi phm vi (nghƿa là khi mà
trong đó chúng đc khai báo). Các constructor và destructor đi vi các
đi tng cc b t đng đc gi
mi khi các đi tng vào và ri khi phm vi.
Các constructor đc gi ca các đi tng cc b tƿnh (static) khi s thc hin đn đim mà các đi
tng đc khai báo ln đu tiên. Các destructor tng ng đc gi khi hàm main() kt thúc hoc hàm
exit() đc gi.
Ví d 3.9:
Chng trình sau minh ha th t các constructor và destructor đc gi.
#include <iostream.h>
class CreateAndDestroy
{
public:
CreateAndDestroy(int); //Constructor
~CreateAndDestroy(); //Destructor
private:
int Data;
};
CreateAndDestroy::CreateAndDestroy(int Value)
{
Data = Value;
cout << "Object " << Data << " constructor";
}
CreateAndDestroy::~CreateAndDestroy()
{
cout << "Object " << Data << " destructor " << endl;
}
void Create(void); //Prototype
CreateAndDestroy First(1); //Doi tuong toan cuc
int main()
{
cout << " (global created before main)" << endl;
CreateAndDestroy Second(2); //Doi tuong cuc bo
cout << " (local automatic in main)" << endl;
static CreateAndDestroy Third(3); //Doi tuong cuc bo
cout << " (local static in main)" << endl;
Create(); //Goi ham de tao cac doi tuong
CreateAndDestroy Fourth(4); //Doi tuong cuc bo
cout << " (local automatic in main)" << endl;
return 0;
}
//Ham tao cac doi tuong
void Create(void)
{
CreateAndDestroy Fifth(5);
cout << " (local automatic in create)" << endl;
static CreateAndDestroy Sixth(6);
cout << " (local static in create)" << endl;
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
54
CreateAndDestroy Seventh(7);
cout << " (local automatic in create)" << endl;
}
Chng trình khai báo First phm vi toàn cc. Constructor ca nó đc gi khi chng trình bt đu
thc hin và destructor ca nó đc gi lúc chng trình kt thúc sau tt c các đi tng khác đc hy b.
Hàm main() khai báo ba đi tng. Các đi tng Second Fourth là các đi tng cc b t đng và đi
tng Third là mt đi tng cc b tƿnh. Các constructor ca các đi tng này đc gi khi chng trình
thc hin đn đim mà mi đi tng đc khai báo. Các destructor ca các đi tng Fourth Second
đc gi theo th t này khi kt thúc ca main() đt đn. Vì đi tng Third là tƿnh, nó tn ti cho đn khi
chng trình kt thúc. Destructor ca đi tng Third đc gi trc destructor ca First nhng sau tt c
các đi tng khác
đc hy b.
Hàm Create() khai báo ba đi tng – Fifth Seventh là các đi tng cc b t đng và Sixth là mt
đi tng cc b tƿnh. Các destructor ca các đi tng Seventh và Fifth đc gi theo th t này khi kt
thúc ca create() đt đn. Vì đi tng Sixth là tƿnh, nó tn ti cho đn khi chng trình kt thúc. Destructor
ca đi tng Sixth đc gi trc các destructor c
a Third First nhng sau tt c các đi tng khác
đc hy b.
Chúng ta chy ví d 3.9
, kt qu hình 3.9
Hình 3.9: Kt qu ca ví d 3.9
X. S DNG CÁC THÀNH VIÊN D LIU VÀ CÁC HÀM THÀNH VIÊN
Các thành viên d liu private ch có th đc x lý bi các hàm thành viên (hay hàm friend) ca lp.
Các lp thng cung cp các hàm thành viên public đ cho phép các client ca lp đ thit lp (set) (nghƿa là
"ghi") hoc ly (get) (nghƿa là "đc") các giá tr ca các thành viên d liu private. Các hàm này thng
không cn phi đc gi "set" hay "get", nhng chúng thng đt tên nh vy. Chng hn, mt lp có thành
viên d liu private có tên InterestRate
, hàm thành viên thit lp giá tr có tên là SetInterestRate() và hàm
thành viên ly giá tr có tên là GetInterestRate(). Các hàm "Get" cũng thng đc gi là các hàm cht vn
(query functions).
Nu mt thành viên d liu là public thì thành viên d liu có th đc đc hoc ghi ti bt k hàm nào
trong chng trình. Nu mt thành viên d liu là private, mt hàm "get" public nht đnh cho phép các hàm
khác đ đc d liu nhng hàm get có th điu khin s đnh d
ng và hin th ca d liu. Mt hàm "set"
public có th s xem xét cn thn bt k c gng nào đ thay đi giá tr ca thành viên d liu. Điu này s
bo đm rng giá tr mi thì tng thích đi vi mc d liu. Chng hn, mt s c gng thit lp ngày ca
tháng là 37 s b loi tr.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
55
Các li ích ca s toàn vn d liu thì không t đng đn gin bi vì các thành viên d liu đc to là
private – lp trình viên phi cung cp s kim tra hp l. Tuy nhiên C++ cung cp mt khung làm vic trong
đó các lp trình viên có th thit k các chng trình tt hn.
Client ca lp phi đc thông báo khi mt s c gng đc to ra đ gán mt giá tr không hp l cho
m
t thành viên d liu. Chính vì lý do này, các hàm "set" ca lp thng đc vit tr v các giá tr cho bit
rng mt s c gng đã to ra đ gán mt d liu không hp l cho mt đi tng ca lp. Điu này cho
phép các client ca lp kim tra các giá tr tr v đ xác đnh nu đi tng mà chúng thao tác là mt đi
tng hp lđ b
t gi hot đng thích hp nu đi tng mà chúng thao tác thì không phi hp l.
Ví d 3.10:
Chng trình m rng lp Time ví d 3.2 bao gm hàm get và set đi vi các thành viên
d liu private là hour, minute second.
1: #include <iostream.h>
2:
3: class Time
4: {
5: public:
6: Time(int = 0, int = 0, int = 0); //Constructor
7: //Các hàm set
8: void SetTime(int, int, int); //Thiết lp Hour, Minute, Second
9: void SetHour(int); //Thiết lp Hour
10: void SetMinute(int); //Thiết lp Minute
11: void SetSecond(int); //Thiết lp Second
12: //Các hàm get
13: int GetHour(); //Tr v Hour
14: int GetMinute(); //Tr v Minute
15: int GetSecond(); //Tr v Second
16:
17: void PrintMilitary(); //Xut thi gian theo dng gi quânđội
18: void PrintStandard(); //Xut thi gian theo dng chun
19:
20: private:
21: int Hour; //0 - 23
22: int Minute; //0 - 59
23: int Second; //0 – 59
24: };
25:
26: //Constructor khi
động d liu private
27: //Gi hàm thành viên SetTime() đ thiết lp các biến
24: //Các giá tr mc định là 0
25: Time::Time(int Hr, int Min, int Sec)
26: {
27: SetTime(Hr, Min, Sec);
28: }
29:
30: //Thiết lp các giá tr ca Hour, Minute, và Second
31: void Time::SetTime(int H, int M, int S)
32: {
33: Hour = (H >= 0 && H < 24) ? H : 0;
34: Minute = (M >= 0 && M < 60) ? M : 0;
35: Second = (S >= 0 && S < 60) ? S : 0;
36: }
37:
38: //Thiết lp giá tr ca Hour
39: void Time::SetHour(int H)
40: {
41: Hour = (H >= 0 && H < 24) ? H : 0;
42: }
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
56
43:
44: //Thiết lp giá tr ca Minute
45: void Time::SetMinute(int M)
46: {
47: Minute = (M >= 0 && M < 60) ? M : 0;
48: }
49:
50: //Thiết lp giá tr ca Second
51: void Time::SetSecond(int S)
52: {
53: Second = (S >= 0 && S < 60) ? S : 0;
54: }
55:
56: //Ly giá tr ca Hour
57: int Time::GetHour()
58: {
59: return Hour;
60: }
61:
62: //Ly giá tr ca Minute
63: int Time::GetMinute()
64: {
65: return Minute;
66: }
67:
68: //Ly giá tr ca Second
69: int Time::GetSecond()
70: {
71: return Second;
72: }
73:
74: //Hin th thi gian dng gi quânđội: HH:MM:SS
75: void Time::PrintMilitary()
76: {
77: cout << (Hour < 10 ? "0" : "") << Hour << ":"
78: << (Minute < 10 ? "0" : "") << Minute << ":"
79: << (Second < 10 ? "0" : "") << Second;
80: }
81:
83: //Hin th thi gian dng chun: HH:MM:SS AM (hay PM)
84: void Time::PrintStandard()
85: {
86: cout << ((Hour == 0 || Hour == 12) ? 12 : Hour % 12) << ":"
87: << (Minute < 10 ? "0" : "") << Minute << ":"
88: << (Second < 10 ? "0" : "") << Second
89: << (Hour < 12 ? " AM" : " PM");
90: }
91:
92: void IncrementMinutes(Time &, const int); //prototype
93:
94: int main()
95: {
96: Time T;
97:
99: T.SetHour(17);
100: T.SetMinute(34);
101: T.SetSecond(25);
102 cout << "Result of setting all valid values:" << endl
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
57
103: << " Hour: " << T.GetHour()
104: << " Minute: " << T.GetMinute()
105: << " Second: " << T.GetSecond() << endl << endl;
106: T.SetHour(234); //Hour không hp lệđược thiết lp bng 0
107: T.SetMinute(43);
108: T.SetSecond(6373); //Second không hp lệđược thiết lp bng 0
109: cout << "Result of attempting to set invalid Hour and"
110: << " Second:" << endl << " Hour: " << T.GetHour()
111: << " Minute: " << T.GetMinute()
112: << " Second: " << T.GetSecond() << endl << endl;
113: T.SetTime(11, 58, 0);
114: IncrementMinutes(T, 3);
115: return 0;
116: }
117:
118: void IncrementMinutes(Time &TT, const int Count)
119: {
120: cout << "Incrementing Minute " << Count
121: << " times:" << endl << "Start time: ";
122: TT.PrintStandard();
123: for (int I = 1; I <= Count; I++)
124: {
125: TT.SetMinute((TT.GetMinute() + 1) % 60);
126: if (TT.GetMinute() == 0)
127: TT.SetHour((TT.GetHour() + 1) % 24);
128: cout << endl << "Minute + 1: ";
129: TT.PrintStandard();
130: }
131: cout << endl;
132: }
Trong ví d trên chúng ta có hàm IncrementMinutes() là hàm dùng đ tĕng Minite. Đây là hàm không
thành viên mà s dng các hàm thành viên get và set đ tĕng thành viên Minite.
Chúng ta chy ví d .10
, kt qu hình 3.10
Hình 3.10: Kt qu ca ví d 3.10
XI. TR V MT THAM CHIU TI MT THÀNH VIÊN D LIU PRIVATE
Mt tham chiu ti mt đi tng là mt bí danh ca chính đi tng đó và do đó có th đc s dng
v trái ca phép gán. Trong khung cnh đó, tham chiu to mt lvalue đc chp nhn hoàn toàn mà có th
nhn mt giá tr. Mt cách đ s dng kh nĕng này (tht không may!) là có mt hàm thành viên public ca
lp tr v mt tham chiu không const ti m
t thành viên d liu private ca lp đó.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
58
Ví d 3.11:
Chng trình sau s dng mt phiên bn đn gin ca lp Time đ minh ha tr v mt
tham chiu ti mt d liu private.
1: #include <iostream.h>
2:
3: class Time
4: {
5: public:
6: Time(int = 0, int = 0, int = 0);
7: void SetTime(int, int, int);
8: int GetHour();
9: int &BadSetHour(int); //Nguy him tr v tham chiếu !!!
10: private:
11: int Hour;
12: int Minute;
13: int Second;
14: };
15:
16: //Constructor khiđộng d liu private
17: //Gi hàm thành viên SetTime()đ thiết lp các biến
18: //Các giá tr mcđịnh là 0
19: Time::Time(int Hr, int Min, int Sec)
20: {
21: SetTime(Hr, Min, Sec);
22: }
23: //Thiết lp các giá tr ca Hour, Minute, và Second
24: void Time::SetTime(int H, int M, int S)
25: {
26: Hour = (H >= 0 && H < 24) ? H : 0;
27: Minute = (M >= 0 && M < 60) ? M : 0;
28: Second = (S >= 0 && S < 60) ? S : 0;
29: }
30:
31: //Ly giá tr ca Hour
32: int Time::GetHour()
33: {
34: return Hour;
35: }
36:
37: //KHÔNG NÊN LP TRÌNH THEO KIU NÀY !!!
38: //Tr v mt tham chiếu ti mt thành viên d liu private
39: int &Time::BadSetHour(int HH)
40: {
41: Hour = (HH >= 0 && HH < 24) ? HH : 0;
42: return Hour; //Nguy him tr v tham chiếu !!!
43: }
44:
45: int main()
46: {
47: Time T;
48: int &HourRef = T.BadSetHour(20);
49:
50: cout << "Hour before modification: " << HourRef << endl;
51: HourRef = 30; //Thayđổi vi giá tr không hp l
52: cout << "Hour after modification: " << T.GetHour() << endl;
53: // Nguy him: Hàm tr v mt tham chiếu
54: //có thđược s dng như mt lvalue
55: T.BadSetHour(12) = 74;
56: cout << endl << "*********************************" << endl
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
59
57: << "BAD PROGRAMMING PRACTICE!!!!!!!!!" << endl
58: << "BadSetHour as an lvalue, Hour: "
59: << T.GetHour()
60: << endl << "*********************************" << endl;
61: return 0;
62: }
Trong chng trình hàm BadSetHour() tr v mt tham chiu ti thành viên d liu Hour.
Chúng ta chy ví d 3.11
, kt qu hình 3.11
Hình 3.11: Kt qu ca ví d 3.11
XII. PHÉP GÁN BI TOÁN T SAO CHÉP THÀNH VIÊN MC ĐNH
Toán t gán (=) đc s dng đ gán mt đi tng cho mt đi tng khác ca cùng mt kiu. Toán t
gán nh th bình thng đc thc hin bi toán t sao chép thành viên (Memberwise copy) – Mi thành
viên ca mt đi tng đc sao chép riêng r ti cùng thành viên đi tng khác (Chú ý rng sao chép
thành viên có th phát sinh các vn đ nghiêm trng khi s dng vi mt lp mà thành viên d liu cha
vùng nh
cp phát đng).
Các đi tng có th đc truyn cho các tham s ca hàm và có th đc tr v t các hàm. Nh th
vic truyn và tr v đc thc hin theo truyn giá tr – mt sao chép ca đi tng đc truyn hay tr v.:
Ví d 3.12:
Chng trình sau minh ha toán t sao chép thành viên mc đnh
2: #include <iostream.h>
3: //Lp Date đơn gin
4: class Date
5: {
6: public:
7: Date(int = 1, int = 1, int = 1990); //Constructor mc định
8: void Print();
9: private:
10: int Month;
11: int Day;
12: int Year;
13: };
14:
15: //Constructor Date đơn gin vi vic không kim tra min
16: Date::Date(int m, int d, int y)
17: {
18: Month = m;
19: Day = d;
20: Year = y;
21: }
22:
23: //In Date theo dng mm-dd-yyyy
24: void Date::Print()
25: {
26: cout << Month << '-' << Day << '-' << Year;
27: }
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
60
28:
29: int main()
30: {
31: Date Date1(7, 4, 1993), Date2; //Date2 mc định là 1/1/90
32: cout << "Date1 = ";
33: Date1.Print();
34: cout << endl << "Date2 = ";
35: Date2.Print();
36: Date2 = Date1; //Gán bi toán t sao chép thành viên mc định
37: cout << endl << endl
38: << "After default memberwise copy, Date2 = ";
39: Date2.Print();
40: cout << endl;
41: return 0;
42: }
Chúng ta chy ví d 3.12
, kt qu hình 3.12
Hình 3.12: Kt qu ca ví d 3.12
XIII. CÁC ĐI TNG HNG VÀ CÁC HÀM THÀNH VIÊN CONST
Mt vài đi tng cn đc thay đi và mt vài đi tng thì không. Lp trình viên có th s dng t
khóa const đ cho bit đi tng không th thay đi đc, và nu có c gng thay đi đi tng thì xy ra
li. Chng hn:
const Time Noon(12,0,0); //Khai báo mt đi tng const
Các trình biên dch C++ lu ý đn các khai báo const vì th các trình biên dch cm hoàn toàn bt k
hàm thành viên nào gi các đi tng
const (Mt vài trình biên dch ch cung cp mt cnh báo). Điu này
thì khc nghit bi vì các client ca đi tng hu nh chc chn s mun s dng các hàm thành viên "get"
khác nhau vi đi tng, và tt nhiên không th thay đi đi tng. Đ cung cp cho điu này, lp trình viên
có th khai báo các hàm thành viên const; điu này ch có th thao tác trên các đi tng const. Dƿ nhiên các
hàm thành viên const không th thay đ
i đi tng - trình biên dch cm điu này.
Mt hàm đc mô t nh const khi c hai trong phn khai báo và trong phn đnh nghƿa ca nó đc
chèn thêm t khóa const sau danh sách các tham s ca hàm, và trong trng hp ca đnh nghƿa hàm trc
du ngoc móc trái ({) mà bt đu thân hàm. Chng hn, hàm thành viên ca lp A nào đó:
int A::GetValue() const
{
return PrivateDataMember;
}
Nu mt hàm thành viên const đc đnh nghƿa bên ngoài đnh nghƿa ca lp thì khai báo hàm và đnh
nghƿa hàm phi bao gm const mi phn.
Mt vn đ ny sinh đây đi vi các constructor và destructor, mi hàm thng cn thay đi đi
tng. Khai báo const không yêu cu đi vi các constructor và destructor ca các đi tng const. Mt
constructor phi đc phép thay đi mt đi tng mà đi tng có th đc khi to thích hp. Mt
destructor phi có kh n
ĕng thc hin vai trò "công vic kt thúc ni tr" trc khi đi tng đc hy.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
61
Ví d 3.13:
Chng trình sau s dng mt lp Time vi các đi tng const và các hàm thành viên
const.
2: #include <iostream.h>
3: class Time
4: {
5: public:
6: Time(int = 0, int = 0, int = 0); //Constructor mc định
7: //Các hàm set
8: void SetTime(int, int, int); //Thiết lp thi gian
9: void SetHour(int); //Thiết lp Hour
10: void SetMinute(int); //Thiết lp Minute
11: void SetSecond(int); //Thiết lp Second
12: //Các hàm get
13: int GetHour() const; //Tr v Hour
14: int GetMinute() const; //Tr v Minute
15: int GetSecond() const; //Tr v Second
16: //Các hàm in
17: void PrintMilitary() const; //In t.gian theo dng gi quân đội
18: void PrintStandard() const; //In thi gian theo dng gi chun
19: private:
20: int Hour; //0 - 23
21: int Minute; //0 - 59
22: int Second; //0 – 59
23: };
24:
25: //Constructor khi động d liu private
26: //Các giá tr
mc định là 0
27: Time::Time(int hr, int min, int sec)
28: {
29: SetTime(hr, min, sec);
30: }
31:
32: //Thiết lp các giá tr ca Hour, Minute, và Second
33: void Time::SetTime(int h, int m, int s)
34: {
35: Hour = (h >= 0 && h < 24) ? h : 0;
36: Minute = (m >= 0 && m < 60) ? m : 0;
37: Second = (s >= 0 && s < 60) ? s : 0;
38: }
39:
40: //Thiết lp giá tr ca Hour
41: void Time::SetHour(int h)
42: {
43: Hour = (h >= 0 && h < 24) ? h : 0;
44: }
45:
46: //Thiết lp giá tr ca Minute
47: void Time::SetMinute(int m)
48: {
49: Minute = (m >= 0 && m < 60) ? m : 0;
50: }
51:
52: //Thiết lp giá tr ca Second
53: void Time::SetSecond(int s)
54: {
55: Second = (s >= 0 && s < 60) ? s : 0;
56: }
57:
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
62
58: //Ly giá tr ca Hour
59: int Time::GetHour() const
60: {
61: return Hour;
62: }
63:
64: //Ly giá tr ca Minute
65: int Time::GetMinute() const
66: {
67: return Minute;
68: }
69:
70: //Ly giá tr ca Second
71: int Time::GetSecond() const
72: {
73: return Second;
74: }
75:
76: //Hin th thi gian dng gi quân đội: HH:MM:SS
77: void Time::PrintMilitary() const
78: {
79: cout << (Hour < 10 ? "0" : "") << Hour << ":"
80: << (Minute < 10 ? "0" : "") << Minute << ":"
81: << (Second < 10 ? "0" : "") << Second;
82: }
83:
84: //Hin th thi gian dng chun: HH:MM:SS AM (hay PM)
85: void Time::PrintStandard() const
86: {
87: cout << ((Hour == 12) ? 12 : Hour % 12) << ":"
88: << (Minute < 10 ? "0" : "") << Minute << ":"
89: << (Second < 10 ? "0" : "") << Second
90: << (Hour < 12 ? " AM" : " PM");
91: }
92:
93: int main()
94: {
95: const Time T(19, 33, 52); //Đối tượng hng
96: T.SetHour(12); //ERROR: non-const member function
97: T.SetMinute(20); //ERROR: non-const member function
98: T.SetSecond(39); //ERROR: non-const member function
99: return 0;
100: }
Chng trình này khai báo mt đi tng hng ca lp Time và c gng sa đi đ
i tng vi các hàm
thành viên không hng SetHour(), SetMinute() và SetSecond(). Các li cnh báo đc phát sinh bi trình
biên dch (Borland C++) nh hình 3.13.
Hình 3.13: Các cnh báo ca chng trình ví d 3.13
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
63
Lu ý
: Hàm thành viên const có th đc đa nĕng hóa vi mt phiên bn non-const. Vic la chn hàm
thành viên đa nĕng hóa nào đ s dng đc to mt cách t đng bi trình biên dch da vào ni mà đi
tng đc khai báo const hay không.
Mt đi tng const không th đc thay đi bi phép gán vì th nó phi đc khi đng. Khi mt
thành viên d liu ca mt lp
đc khai báo const, mt b khi to thành viên (member initializer) phi
đc s dng đ cung cp cho constructor vi giá tr ban đu ca thành viên d liu đi vi mt đi tng
ca lp.
Ví d 3.14:
C.trình sau s dng mt b khi to thành viên đ khi to mt hng ca kiu d liu có
sn.
2: #include <iostream.h>
3: class IncrementClass
4: {
5: public:
6: IncrementClass (int C = 0, int I = 1);
7: void AddIncrement()
8: {
9: Count += Increment;
10: }
11: void Print() const;
12: private:
13: int Count;
14: const int Increment; //Thành viên d liu const
15: };
16:
17: //Constructor ca lp IncrementClass
18: //B khi to vi thành viên const
19: IncrementClass::IncrementClass (int C, int I) : Increment(I)
20: {
21: Count = C;
22: }
23:
24: //In d liu
25: void IncrementClass::Print() const
26: {
27: cout << "Count = " << Count
28: # # << ", Increment = " << Increment << endl;
30: }
31:
32: int main()
33: {
34: IncrementClass Value(10, 5);
35:
36: cout << "Before incrementing: ";
37: Value.Print();
38: for (int J = 1; J <= 3; J++)
40: {
41: Value.AddIncrement();
42: cout << "After increment " << J << ": ";
43: Value.Print();
44: }
45: return 0;
46: }
Chng trình này s dng cú pháp b khi to thành viên đ khi t
o thành viên d liu const
Increment ca lp IncrementClass dòng 19.
Chúng ta chy ví d 3.14
, kt qu hình 3.14
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
64
Hình 3.14: Kt qu ca ví d 3.14
Ký hiu : Increment(I) ( dòng 19 ca ví d 3.14) sinh ra Increment đc khi đng vi giá trI. Nu
nhiu b khi to thành viên đc cn, đn gin bao gm chúng trong danh sách phân cách du phy sau du
hai chm. Tt c các thành viên d liu có th đc khi to s dng cú pháp b khi to thành viên.
Nu trong ví d 3.14
chúng ta c gng khi to Increment vi mt lnh gán hn là vi mt b khi to
thành viên nh sau:
IncrementClass::IncrementClass (int C, int I)
{ Count = C;
Increment = I;
}
Khi đó trình biên dch (Borland C++) s có thông báo li nh sau:
Hình 3.15: Thông báo li khi c gng khi to mt thành viên d liu const bng phép gán
XIV. LP NH LÀ CÁC THÀNH VIÊN CA CÁC LP KHÁC
Mt lp có th có các đi tng ca các lp khác nh các thành viên. Khi mt đi tng đi vào phm vi,
constructor ca nó đc gi mt cách t đng, vì th chúng ta cn mô t các tham s đc truyn nh th
nào ti các constructor ca đi tng thành viên. Các đi tng thành viên đc xây dng theo th t
trong đó chúng đc khai báo (không theo th t mà chúng đc lit kê trong danh sách b khi to thành
viên ca constructor) và trc các
đi tng ca lp cha đựng chúng đc xây dng.
Ví d 3.15:
Chng trình sau minh ha các đi tng nh các thành viên ca các đi tng khác.
1: #include <iostream.h>
2: #include <string.h>
3:
4: class Date
5: {
6: public:
7: Date(int = 1, int = 1, int = 1900); //Constructor mc định
8: void Print() const; //In ngày theo dng Month/Day/Year
9: private:
10: int Month; //1-12
11: int Day; //1-31
12: int Year; //Năm bt k
13://Hàm tin ích đ kim tra Day tương thích đối vi Month và Year
14: int CheckDay(int);
15: };
16:
17: class Employee
18: {
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
65
19: public:
20: Employee(char *, char *, int, int, int, int, int, int);
21: void Print() const;
22: private:
23: char LastName[25];
24: char FirstName[25];
25: Date BirthDate;
26: Date HireDate;
27: };
28:
29: //Constructor: xác nhn giá tr tương thích ca Month
30: //Gi hàm CheckDay() đ xác nhn giá tr tương thích ca Day
31: Date::Date(int Mn, int Dy, int Yr)
32: {
33: if (Mn > 0 && Mn <= 12)
34: Month = Mn;
35: else
36: {
37: Month = 1;
38: cout << "Month " << Mn << " invalid. Set to Month 1."
39: << endl;
40: }
41: Year = Yr;
42: Day = CheckDay(Dy);
43: cout << "Date object constructor for date ";
44: Print();
45: cout << endl;
46: }
47:
48: //Hàm xác nhn giá tr Day tương thích đưa vào Month và Year
49: int Date::CheckDay(int TestDay)
50: {
51: static int DaysPerMonth[13] = {0, 31, 28, 31, 30, 31,
52: 9; 9; 9; 9; 9; 9; # # # # 30, 31, 31, 30,31, 30, 31};
53:
54: if (TestDay > 0 && TestDay <= DaysPerMonth[Month])
55: return TestDay;
56: if (Month == 2 && TestDay == 29 &&
57: ; ; (Year % 400 == 0 || (Year % 4 == 0 && Year % 100 != 0)))
58: return TestDay;
59: cout << "Day " << TestDay << "invalid. Set to Day 1." << endl;
60: return 1;
61: }
62:
63: //In đối tượng Date dng Month/Day/Year
64: void Date::Print() const
65: {
66: cout << Month << '/' << Day << '/' << Year;
67: }
68:
69: Employee::Employee(char *FName, char *LName,
70: int BMonth, int BDay, int BYear,
71: int HMonth, int HDay, int HYear)
72: :BirthDate(BMonth, BDay, BYear), HireDate(HMonth, HDay, HYear)
73: {
74://Sao chép FName vào FirstName và phi chc chn rng nó phù hp
75: int Length = strlen(FName);
76:
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
66
77: Length = Length < 25 ? Length : 24;
78: strncpy(FirstName, FName, Length);
79: FirstName[Length] = '\0';
80: //Sao chép LName vào LastName và phi chc chn rng nó phù hp
81: Length = strlen(LName);
82: Length = Length < 25 ? Length : 24;
83: strncpy(LastName, LName, 24);
84: LastName[Length] = '\0';
85: cout << "Employee object constructor: "
86: << FirstName << ' ' << LastName << endl;
87: }
88:
89: void Employee::Print() const
90: {
91: cout << LastName << ", " << FirstName << endl << "Hired: ";
92: HireDate.Print();
93: cout << " Birthday: ";
94: BirthDate.Print();
95: cout << endl;
96: }
97:
98: int main()
99: {
100: Employee E("Bob", "Jones", 7, 24, 49, 3, 12, 88);
101:
102 cout << endl;
103: E.Print();
104: cout << endl << "Test Date constructor with invalid values:"
105: << endl;
106: Date D(14, 35, 94); //Các giá tr Date không hp l
107: return 0;
108: }
Chng trình gm lp Employee cha các thành viên d liu private LastName, FirstName, BirthDate
HireDate. Các thành viên BirthDateHireDate là các đi tng ca lp Date mà cha các thành viên
d liu private Month, Day Year. Chng trình khi to mt đ
i tng Employee, và các khi to và các
hin th các thành viên d liu ca nó. Chú ý v cú pháp ca phn đu trong đnh nghƿa constructor ca lp
Employee:
Employee::Employee(char *FName, char *LName, int BMonth, int BDay, int BYear,
int HMonth, int HDay, int HYear)
:BirthDate(BMonth, BDay, BYear), HireDate(HMonth, HDay, HYear)
Constructor ly tám tham s (FName, LName, BMonth, BDay, BYear, HMonth, HDay, và HYear). Du
hai chm trong phn đu phân tách các b khi to t danh sách các tham s. Các b khi to đnh rõ các
tham s truyn chon constructor ca các đi tng thành viên. Vì th BMonth,
BDay BYear đc truyn
cho constructor ca đi tng BirthDate, và HMonth, HDay, và HYear đc truyn cho constructor ca đi
tng HireDate. Nhiu b khi to đc phân tách bi du phy.
Chúng ta chy ví d 3.15
, kt qu hình 3.16
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
67
Hình 3.16: Kt qu ca ví d 3.15
Mt đi tng thành viên không cn đc khi to thông qua mt b khi to thành viên. Nu mt b
khi to thành viên không đc cung cp, constructor mc đnh ca đi tng thành viên s đc gi mt
cách t đng. Các giá tr nu có thit lp bi constructor mc đnh thì có th đc ghi đè bi các hàm set.
XV. CÁC HÀM VÀ CÁC LP friend
Mt hàm friend ca mt lp đc đnh nghƿa bên ngoài phm vi ca lp đó, lúc này có quyn truy cp
đn các thành viên private hoc protected ca mt lp. Mt hàm hay toàn b lp có th đc khai báo là
mt friend ca lp khác.
Đ khai báo mt hàm là mt friend ca mt lp, đng trc prototype ca hàm trong đnh nghƿa lp vi
t khóa friend. nh sau:
friend <function-declarator>;
Đ khai báo mt lp là friend ca lp khác nh sau:
friend <class-name>;
Ví d 3.16:
Chng trình sau minh ha khai báo và s dng hàm friend.
1: #include <iostream.h>
2:
3: class Count
4: {
5: friend void SetX(Count &, int); //Khai báo friend
6: public:
7: Count()//Constructor
8: {
9: X = 0;
10: }
11: void Print() const //Xut
12: {
13: cout << X << endl;
14: }
15: private:
16: int X;
17: };
18:
19: //Có th thay đổi d liu private ca lp Count vì
20: //SetX() khai báo là mt hàm friend ca lp Count
21: void SetX(Count &C, int Val)
22: {
23: C.X = Val; //Hp l: SetX() là mt hàm friend ca lp Count
24: }
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
68
25:
26: int main()
27: {
28: Count Object;
29:
30: cout << "Object.X after instantiation: ";
31: Object.Print();
32: cout << "Object.X after call to SetX friend function: ";
33: SetX(Object, 8); //Thiết lp X vi mt friend
34: Object.Print();
35: return 0;
36: }
Chúng ta chy ví d 3.16
, kt qu hình 3.17
Hình 3.17: Kt qu ca ví d 3.16
Có th ch đnh các hàm đc đa nĕng hóa là các friend ca lp. Mi hàm đc đa nĕng hóa phi đc
khai báo tng minh trong đnh nghƿa lp nh là mt friend ca lp.
XVI. CON TR THIS
Khi mt hàm thành viên tham chiu thành viên khác ca lp cho đi tng c th ca lp đó, làm th
nào C++ bo đm rng đi tng thích hp đc tham chiu? Câu tr li là mi đi tng duy trì mt con
tr tr ti chính nó – gi là con tr this Đó là mt tham s n trong tt c các tham chiu ti các thành viên
bên trong đi tng đó. Con tr this cũng có th đc s
dng tng minh. Mi đi tng có th xác đnh
đa ch ca chính mình bng cách s dng t khóa this.
Con tr this đc s dng đ tham chiu c các thành viên d liu và hàm thành viên ca mt đi
tng. Kiu ca con tr this ph thuc vào kiu ca đi tng và trong hàm thành viên con tr this đc s
dng là khai báo const. Chng hn, mt hàm thành viên không hng c
a lp Employee con tr this có kiu
là:
Employee * const //Con tr hng tr ti đi tng Employee
Đi vi mt hàm thành viên hng ca lp Employee con tr this có kiu là:
const Employee * const //Con tr hng tr ti đi tng Employee mà là mt hng
Ví d 3.17:
Chng trình sau minh ha s dng tng minh ca con tr this đ cho phép mt hàm thành
viên ca lp Test in d liu X ca mt đi tng Test.
1:
#include <iostream.h>
2:
3: class Test
4: {
5: public:
6: Test(int = 0);
// Constructor mc định
7: void Print() const;
8: private:
9: int X;
10: };
11:
12: Test::Test(int A)
13: {
14: X = A;
15: }
16:
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
69
17: void Test::Print() const
18: {
19: cout << " X = " << X << endl
20: << " this->X = " << this->X << endl
21: << "(*this).X = " << (*this).X << endl;
22: }
23:
24: int main()
25: {
26: Test A(12);
27:
28: A.Print();
29: return 0;
30: }
Chúng ta chy ví d 3.17
, kt qu hình 3.18
Hình 3.18: Kt qu ca ví d 3.17
Mt cách khác s dng con tr this là cho phép móc vào nhau các li gi hàm thành viên.
Ví d 3.18:
Chng trình sau minh ha tr v mt tham chiu ti mt đi tng Time đ cho phép các
li gi hàm thành viên ca lp Time đc móc ni vào nhau.
1: #include <iostream.h>
2:
3: class Time
4: {
5: public:
6: Time(int = 0, int = 0, int = 0); // Constructor mc định
7: // Các hàm set
8: Time &SetTime(int, int, int); // Thiết lp Hour, Minute va
Second
9: Time &SetHour(int); // Thiết lp Hour
10: Time &SetMinute(int); // Thiết lp Minute
11: Time &SetSecond(int); // Thiết lp Second
12: // Các hàm get
13: int GetHour() const; // Tr v Hour
14: int GetMinute() const; // Tr v Minute
15: int GetSecond() const; // Tr v Second
16: // Các hàm in
17: void PrintMilitary() const; // In t.gian theo dng gi quân đội
18: void PrintStandard() const; // In thi gian theo dng gi chun
19: private:
20: int Hour; // 0 - 23
21: int Minute; // 0 - 59
22: int Second; // 0 - 59
23: };
24:
25: // Constructor khi động d liu private
26: // Gi hàm thành viên SetTime() đ thiết lp các biến
27: // Các giá tr mc định là 0
28: Time::Time(int Hr, int Min, int Sec)
29: {
30: SetTime(Hr, Min, Sec);
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
70
31: }
32:
33: // Thiết lp các giá tr ca Hour, Minute, và Second
34: Time &Time::SetTime(int H, int M, int S)
35: {
36: Hour = (H >= 0 && H < 24) ? H : 0;
37: Minute = (M >= 0 && M < 60) ? M : 0;
38: Second = (S >= 0 && S < 60) ? S : 0;
39: return *this; // Cho phép móc ni
40: }
41:
42: // Thiết lp giá tr ca Hour
43: Time &Time::SetHour(int H)
44: {
45: Hour = (H >= 0 && H < 24) ? H : 0;
46: return *this; // Cho phép móc ni
47: }
48:
49: // Thiết lp giá tr ca Minute
50: Time &Time::SetMinute(int M)
51: {
52: Minute = (M >= 0 && M < 60) ? M : 0;
53: return *this; // Cho phép móc ni
54: }
55:
56: // Thiết lp giá tr ca Second
57: Time &Time::SetSecond(int S)
58: {
59: Second = (S >= 0 && S < 60) ? S : 0;
60: return *this; // Cho phép móc ni
61: }
62:
63: // Ly giá tr ca Hour
64: int Time::GetHour() const
65: {
66: return Hour;
67: }
68:
69: // Ly giá tr ca Minute
70: int Time::GetMinute() const
71: {
72: return Minute;
73: }
74:
75: // Ly giá tr ca Second
76: int Time::GetSecond() const
77: {
78: return Second;
79: }
80:
81: // Hin th th
i gian dng gi quân đội: HH:MM:SS
82: void Time::PrintMilitary() const
83: {
84: cout << (Hour < 10 ? "0" : "") << Hour << ":"
85: << (Minute < 10 ? "0" : "") << Minute << ":"
86: << (Second < 10 ? "0" : "") << Second;
87: }
88:
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
71
89: // Hin th thi gian dng chun: HH:MM:SS AM (hay PM)
90: void Time::PrintStandard() const
91: {
92: cout << ((Hour == 0 || Hour == 12) ? 12 : Hour % 12) << ":"
93: << (Minute < 10 ? "0" : "") << Minute << ":"
94: << (Second < 10 ? "0" : "") << Second
95: << (Hour < 12 ? " AM" : " PM");
96: }
97:
100: int main()
101: {
102: Time T;
103:
104: // Các li gi móc ni vào nhau
105: T.SetHour(18).SetMinute(30).SetSecond(22);
106: cout << "Military time: ";
107: T.PrintMilitary();
108: cout << endl << "Standard time: ";
109: T.PrintStandard();
110: cout << endl << endl << "New standard time: ";
111: // Các li gi móc ni vào nhau
112: T.SetTime(20, 20, 20).PrintStandard();
113: cout << endl;
114: return 0;
115: }
Các hàm thành viên SetTime(), SetHour(), SetMinute() và SetSecond() mi hàm đu tr v *this vi kiu
tr vTime &. Toán t chm liên kt t trái sang phi, vì vy biu thc:
T.SetHour(18).SetMinute(30).SetSecond(22);
Đu tiên gi T.SetHour(18) thì tr v mt tham chiu t
i đi tng T là giá tr ca li gi hàm này. Phn
còn li ca biu thc đc hiu nh sau:
T.SetMinute(30).SetSecond(22);
T.SetMinute(30) gi thc hin và tr v tng đng ca T. Phn còn ca biu thc là:
T.SetSecond(22);
Chúng ta chy ví d 3.18
, kt qu hình 3.19
Hình 3.19: Kt qu ca ví d 3.18
XVII. CÁC ĐI TNG ĐC CP PHÁT ĐNG
Các đi tng có th đc cp phát đng ging nh các d liu khác bng toán t new delete. Chng
hn:
Time *TimePtr = new Time(1,20,26);
……………..
delete TimePtr;
Toán t new t đng gi hàm constructor ,và toán t delete t đng gi destructor.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
72
XVIII. CÁC THÀNH VIÊN TƾNH CA LP
Bình thng, mi đi tng ca mt lp có bn sao chép ca chính nó ca tt c các thành viên d liu
ca lp. Trong các trng hp nht đnh ch có duy nht mt bn chép thành viên d liu đc bit cn phi
dùng chung bi tt c các đi tng ca mt lp. Mt thành viên d liu tƿnh đc s dng cho nhng điu
đó và các lý do khác. M
t thành viên d liu tƿnh biu din thông tin toàn lp (class-wide). Khai báo mt
thành viên tƿnh bt đu vi t khóa static.
Mc dù các thành viên d liu tƿnh có th ging nh các bin toàn cc, các thành viên d liu tƿnh có
phm vi lp. Các thành viên tƿnh có thpublic, private hoc protected. Các thành viên d liu tƿnh phi
đc khi to mt ln (và ch mt ln) ti phm vi file. Các thành viên lp t
ƿnh public có th đc truy cp
thông qua bt k đi tng nào ca lp đó, hoc chúng có th đc truy cp thông qua tên lp s dng toán
t đnh phm vi. Các thành viên lp tƿnh private protected phi đc truy cp thông qua các hàm thành
viên public ca lp hoc thông qua các friend ca lp. Các thành viên lp tƿnh tn ti ngay c khi đi tng
ca lp đó không tn ti. Đ
truy cp mt thành viên lp tƿnh public khi các đi tng ca lp không tn ti,
đn gin thêm vào đu tên lp và toán t đnh phm vi cho thành viên d liu. Đ truy cp mt thành viên
lp tƿnh private hoc protected khi các đi tng ca lp không tn ti, mt hàm thành viên public phi
đc cung cp và hàm phi đc gi bi thêm vào đu tên ca nó vi tên lp và toán t đnh ph
m vi.
Ví d 3.19:
Chng trình sau minh ha vic s dng thành viên d liu tƿnh private và mt hàm thành
viên tƿnh public.
1: #include <iostream.h>
2: #include <string.h>
3: #include <assert.h>
4:
5: class Employee
6: {
7: public:
8: Employee(const char*, const char*);
// Constructor
9: ~Employee(); // Destructor
10: char *GetFirstName() const; // Tr v first name
11: char *GetLastName() const; // Tr v last name
12: // Hàm thành viên tĩnh
13: static int GetCount(); // Tr v s đối tượng khi to
14: private:
15: char *FirstName;
16: char *LastName;
17:
// static data member
18: static int Count; // S đối tượng khi to
19: };
20:
21:
// Khi to thành viên d liu tĩnh
22: int Employee::Count = 0;
23:
24:
//Định nghĩa hàm thành viên tnh mà tr v s đối tượng khi to
25: int Employee::GetCount()
26: {
27: return Count;
28: }
29:
30:
// Constructor cp phát động cho first name và last name
31: Employee::Employee(const char *First, const char *Last)
32: {
33: FirstName = new char[ strlen(First) + 1 ];
34: assert(FirstName != 0);
// Bo đảm vùng nh được cp phát
35: strcpy(FirstName, First);
36: LastName = new char[ strlen(Last) + 1 ];
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
73
37: assert(LastName != 0); // Bo đảm vùng nh được cp phát
38: strcpy(LastName, Last);
39: ++Count; // Tăng s đối tượng lên 1
40: cout << "Employee constructor for " << FirstName
41: << ' ' << LastName << " called." << endl;
42: }
43:
44:
// Destructor gii phóng vùng nh đã cp phát
45: Employee::~Employee()
46: {
47: cout << "~Employee() called for " << FirstName
48: << ' ' << LastName << endl;
49: delete FirstName;
50: delete LastName;
51: --Count;
// Gim s đối tượng xung 1
52: }
53:
54:
// Tr v first name
55: char *Employee::GetFirstName() const
56: {
57: char *TempPtr = new char[strlen(FirstName) + 1];
58: assert(TempPtr != 0);
// Bo đảm vùng nh được cp phát
59: strcpy(TempPtr, FirstName);
60: return TempPtr;
61: }
62:
63:
// Tr v last name
64: char *Employee::GetLastName() const
65: {
66: char *TempPtr = new char[strlen(LastName) + 1];
67: assert(TempPtr != 0);
// Bo đảm vùng nh được cp phát
68: strcpy(TempPtr, LastName);
69: return TempPtr;
70: }
71:
72: int main()
73: {
74: cout << "Number of employees before instantiation is "
75: << Employee::GetCount() << endl;
// S dng tên lp
76: Employee *E1Ptr = new Employee("Susan", "Baker");
77: Employee *E2Ptr = new Employee("Robert", "Jones");
78: cout << "Number of employees after instantiation is "
79: << E1Ptr->GetCount() << endl;
80: cout << endl << "Employee 1: "
81: << E1Ptr->GetFirstName()
82: << " " << E1Ptr->GetLastName()
83: << endl << "Employee 2: "
84: << E2Ptr->GetFirstName()
85: << " " << E2Ptr->GetLastName() << endl << endl;
86: delete E1Ptr;
87: delete E2Ptr;
88: cout << "Number of employees after deletion is "
89: << Employee::GetCount() << endl;
90: return 0;
91: }
Thành viên d liu Count đc khi to là zero phm vi file vi lnh:
int Employee::Count = 0;
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
74
Thành viên d liu Count duy trì s các đi tng ca lp Employee đã đc khi to. Khi đi tng
ca lp Employee tn ti, thành viên Count có th đc tham chiu thông qua bt k hàm thành viên nào ca
mt đi tng Employee – trong ví d này, Count đc tham chiu bi c constructor ln destructor. Khi các
đi tng ca lp Employee không tn ti, thành viên Count có th vn đc tham chiu nhng ch
thông
qua mt li gi hàm thành viên tƿnh public GetCount() nh sau:
Employee::GetCount()
Hàm GetCount() đc s dng đ xác đnh s các đi tng ca Employee khi to hin hành. Chú ý
rng khi không có các đi tng trong chng trình, li gi hàm Employee::GetCount() đc đa ra. Tuy
nhiên khi có các đi tng khi đng hàm GetCount() có th đc gi thông qua mt trong các đi tng
nh sau:
E1Ptr->GetCount()
Trong chng trình các dòng 34, 37, 58 và 67 s dng hàm assert()
(đnh nghƿa trong assert.h). Hàm
này kim tra giá tr ca biu thc. Nu giá tr ca biu thc là 0 (false), hàm assert() in mt thông báo li và
gi hàm abort() (đnh nghƿa trong stdlib.h) đ kt thúc chng trình thc thi. Nu biu thc có giá tr khác 0
(true) thì chng trình tip tc. Điu này rt có ích cho công c debug đi vi vic kim tra nu mt bin có
giá tr đúng. Chng hn hàm dòng 34 hàm assert() kim tra con tr
FirstName đ xác đnh nu nó không
bng 0 (null). Nu điu kin trong khng đnh (assertion) cho trc là đúng, chng trình tip tc mà không
ngt. Nu điu kin trong khng đnh cho trc là sai, mt thông báo li cha s dòng, điu kin đc kim
tra, và tên file trong đó s khng đnh xut hin đc in, và chng trình kt thúc. Khi đó lp trình viên có
th tp trung vào vùng này ca đo
n mã đ tìm li.
Các khng đnh không phi xóa t chng trình khi debug xong. Khi các khng đnh không còn cn
thit cho mc đích debug trong mt chng trình, dòng sau:
#define NDEBUG
đc thêm vào đu file chng trình. Điu này phát sinh tin x lý b qua tt c các khng đnh thay
th cho lp trình viên xóa mi khng đnh bng tay.
Chúng ta chy ví d 3.19
, kt qu hình 3.20
Hình 3.20: Kt qu ca ví d 3.19
Mt hàm thành viên có th đc khai báo là static nu nó không truy cp đn các thành viên không tƿnh.
Không ging nh các thành viên không tƿnh, mt hàm thành viên tƿnh không có con tr this bi vì các thành
viên d liu tƿnh và các hàm thành viên tƿnh tn ti đc lp vi bt k đi tng nào ca lp.
Chú ý
: Hàm thành viên d liu tƿnh không đc là const.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
75
BÀI TP
Bài 1: Xây dng lp Stack, d liu bao gm đnh stack và vùng nh ca stack. Các thao tác gm:
Khi đng stack.
Kim tra stack có rng không?
Kim tra stack có đy không?
Push và pop.
Bài 2: Xây dng lp hình tr Cylinder, d liu bao gm bán kính và chiu cao ca hình tr. Các thao
tác gm hàm tính din tích toàn phn và th tích ca hình tr đó.
Bài 3: Hãy xây dng mt lp Point cho các đim trong không gian ba chiu (x,y,z). Lp cha mt
constructor mc đnh, mt hàm Negate() đ bin đi đim thành đi lng có du âm, mt hàm Norm() tr
v khong cách t gc và mt hàm Print().
Bài 4: Xây dng mt lp Matrix cho các ma trn bao gm mt constructor mc đnh, hàm xut ma
trn, nhp ma trn t bàn phím, cng hai ma trn, tr hai ma trn và nhân hai ma trn.
Bài 5: Xây dng mt lp Matrix cho các ma trn vuông bao gm mt constructor mc đnh, hàm xut
ma trn, tính đnh thc và tính ma trn nghch đo.
Bài 6: Xây dng lp Person đ qun lý h tên, nĕm sinh, đim chín môn hc ca tt c các hc viên
ca lp hc. Cho bit bao nhiêu hc viên trong lp đc phép làm lun vĕn tt nghip, bao nhiêu hc viên
thi tt nghip, bao nhiêu ngi phi thi li và tên môn thi li. Tiêu chun đ xét:
Làm lun vĕn phi có đim trung bình ln hn 7 trong đó không có môn nào di 5.
Thi tt nghip khi đim trung bình không ln hn 7 và đim các môn không di 5.
Thi li có môn di 5.
Bài 7: Xây dng mt lp String. Mi đi tng ca lp String s đi din mt chui ký t. Các thành
viên d liu là chiu dài chui và chui ký t thc. Ngoài constructor và destructor còn có các phng thc
nh to mt chui vi chiu dài cho trc, to mt chui t mt chui đã có.
Bài 8: Xây dng mt lp Vector đ lu tr vector gm các s thc. Các thành viên d liu gm:
Kích thc vector.
Mt mng đng cha các thành phn ca vector.
Ngoài constructor và destructor, còn có các phng thc tính tích vô hng ca hai vector, tính chun
ca vector (theo chun bt k nào đó).
Bài 9: Xây dng lp Employee gm h tên và chng minh nhân dân. Ngoài constructor còn có
phng thc nhp, xut h tên và chng minh nhân dân ra màn hình.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
76
CHƯƠNG 4
ĐA NĔNG HÓA TOÁN T
I. DN NHP
Trong chng 3, chúng ta đã tìm hiu các điu c bn ca các lp C++ và khái nim kiu d liu tru
tng (ADTs). Các thao tác trên các đi tng ca lp (nghƿa là các thc th ca ADTs) đc thc hin bi
gi các thông đip (di dng các li gi hàm thành viên) ti các đi tng. Ký pháp gi hàm này thì cng
knh cho các loi lp nht đnh, đc bit là các lp toán hc. Đ
i vi các loi lp này sđẹp đ s dng
tp các toán t có sn phong phú ca C++ đ ch rõ các thao tác ca đi tng. Trong chng này tìm hiu
làm th nào cho phép các toán t ca C++ làm vic vi các đi tng ca lp. X lý này đc gi là đa nĕng
hóa toán t (operator overloading).
Toán t << đc s dng nhiu mc đích trong C++ đó là toán t chèn dòng (stream-insertion) và toán
t dch chuyn trái. Đây là m
t ví d ca đa nĕng hóa toán t. Tng t >> cũng đc đa nĕng hóa. Nó đc
s dng va toán t trích dòng (stream-extraction) và toán t dch chuyn phi.
C++ cho phép các lp trình viên đa nĕng hóa hu ht các toán t đ biu th ng cnh mà trong đó chúng
đc s dng. Trình biên dch phát sinh đon mã thích hp da trên kiu mà trong đó toán t đc s dng.
Mt vài toán t đ
c đa nĕng hóa thng xuyên, đc bit là toán t gán và các toán t s hc nh + và -.
Công vic thc hin bi đa nĕng hóa các toán t cũng có th đc thc hin bi các li gi hàm tng minh,
nhng ký pháp thng s dng d dàng đ đc.
II. CÁC NGUYÊN TC C BN CA ĐA NĔNG HÓA TOÁN T
Lp trình viên có th s dng các kiu có sn và có th đnh nghƿa các kiu mi. Các kiu có th đc s
dng vi tp các toán t phong phú. Các toán t cung cp cho các lp trình viên vi ký pháp ngn ngn cho
vic biu th các thao tác ca đi tng ca các kiu có sn.
Các lp trình viên có th s dng các toán t vi các kiu do ngi dùng đnh nghƿa. Mc dù C++ không
cho phép các toán t mi đc t
o, nó cho phép các toán t đã tn ti đc đa nĕng hóa sao cho khi các toán
t này đc s dng vi các đi tng ca lp, các toán t có ý nghƿa thích hp các kiu mi. Đây chính là
mt đc đim mnh ca C++.
Các toán t đc đa nĕng hóa bng cách vit mt đnh nghƿa hàm (bao gm phn đu và thân) nh khi
chúng ta vit mt hàm bình thng, ngoi tr tên hàm bây gi tr
thành t khóa operator theo sau bi ký
hiu ca toán t đc đa nĕng hóa. Prototype ca nó có dng nh sau:
type operator operator_symbol ( parameter_list );
Đ s dng mt toán t mt các đi tng ca lp, toán t phi đc đa nĕng hóa ngoi tr hai điu.
Điu th nht toán t gán có th s dng vi mi lp mà không cn đa nĕng hóa. Cách c x mc đnh ca
toán t gán là mt phép gán thành viên ca các thành viên d liu ca lp. Chúng ta nhn thy rng sao chép
thành viên mc đnh thì nguy him đi vi các lp vi các thành viên mà đc cp phát đng. Chúng ta s đa
nĕng hóa mt cách tng minh toán t gán đi vi các lp nh th. Điu th hai toán t đa ch (&) cũng có
th đc s dng vi các đi tng ca b
t k lp nào mà không cn đa nĕng hóa; Nó tr v đa ch ca đi
tng trong b nh. Toán t đa ch cũng có th đc đa nĕng hóa.
III. CÁC GII HN CA ĐA NĔNG HÓA TOÁN T
Phn ln các toán t ca C++ có th đc đa nĕng hóa. Hình 4.1 cho thy các toán t có th đc đa
nĕng hóa và hình 4.1 là các toán t không th đa nĕng hóa.
Hình 4.1:
Các toán t có th đc đa nĕng hóa
+ - * / % ^ & |
~ ! = < > += -= *=
/= %= ^= &= |= << >> >>=
<<= == != <= >= && || ++
-- ->* , -> [] () new delete
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
77
Hình 4.2: Các toán t không th đa nĕng hóa
Chú ý rng toán t ngoc tròn () trong bng 4.1 là toán t gi hàm. Vì toán t này đng sau tên hàm có
th cha trong nó nhiu tham s do đó toán t ngoc tròn là mt toán t nhiu ngôi.
Th t u tiên ca mt toán t không th đc thay đi bi đa nĕng hóa. Điu này có th dn ti các
tình trng bt tin trong đó mt toán t đc
đa nĕng hóa theo mt cách đi vi mc đ u tiên c đnh ca
nó thì không thích hp. Tuy nhiên, các du ngoc đn có th đc s dng đ đt th t c lng ca các
toán t đã đa nĕng hóa trong mt biu thc.
Tính kt hp ca mt toán t không th đc thay đi bi đa nĕng hóa. Các tham s mc đnh không th
s
dng vi mt toán t đa nĕng hóa.
Không th thay đi s các toán hng mà mt toán t yêu cu: Đa nĕng hóa các toán t mt ngôi vn là
các toán t mt ngôi; đa nĕng hóa các toán t hai ngôi vn là các toán t hai ngôi. Toán t ba ngôi duy nht
(?:) ca C++ không th đa nĕng hóa. Các toán t &, *, + mi toán t có các phiên bn mt và hai ngôi.;
Các phiên bn mt và hai ngôi này có th đc đa nĕng hóa riêng bit.
Ý nghƿa ca làm sao mt toán t làm vic trên các đi tng ca các kiu có sn không th thay đi bi
vic đa nĕng hóa toán t. Chng hn, lp trình viên không th thay đi ý nghƿa ca làm sao toán t (+) cng
hai s nguyên. Vic đa nĕng hóa toán t ch làm vic vi các đi tng ca các kiu do ngi dùng đnh
nghƿa hoc vi mt s pha trn ca m
t đi tng ca kiu do ngi dùng đnh nghƿa và mt đi tng ca
mt kiu có sn.
Đa nĕng hóa mt toán t gán và mt toán t cng đ cho phép các lnh nh là:
object2 = object2 + object1
không bao hàm toán t += cũng đc đa nĕng hóa đ phép các lnh nh là:
object2 += object1
Hành vi nh th có th đc thc hin bi vic đa nĕng hóa rõ ràng toán t += cho lp đó.
IV. CÁC HÀM TOÁN T CÓ TH LÀ CÁC THÀNH VIÊN CA LP HOC
KHÔNG LÀ CÁC THÀNH VIÊN
Các hàm toán t có th là các hàm thành viên hoc hàm không thành viên; hàm không thành viên
thng là các hàm friend. Các hàm thành viên s dng ngm con tr this đ cha mt trong các tham s đi
tng lp ca chúng. Tham s lp đó phi đc lit kê mt cách tng minh trong li gi hàm không thành
viên.
Khi đa nĕng hóa (), [], -> hoc =, hàm đa nĕng hóa toán t phi đc khai báo nh mt thành viên lp.
Đi vi các toán t khác, các hàm đa nĕng hóa toán t
có th là các hàm không thành viên (thng là các
hàm friend).
Liu có phi mt hàm toán t đc cài đt nh mt hàm thành viên hoc nh hàm không thành viên,
toán t vn còn đc s dng cùng cách trong biu thc. Nh vy cách là cách cài đt nào tt nht?
Khi mt hàm toán t đc cài đt nh mt hàm thành viên, toán hng cc trái phi là mt đi tng lp
ca toán t. Nu toán hng bên trái phi là mt đi tng ca l
p khác hoc mt kiu có sn thì hàm toán t
này phi đc cài đt nh hàm không thành viên. Mt hàm toán t cài đt nh hàm không thành viêân cn là
mt friend nu hàm phi truy cp đn các thành viên private hoc protected.
Các hàm thành viên ch đc gi khi toán hng trái ca mt toán t hai ngôi là mt đi tng c th ca
lp đó, hoc khi toán hng đn ca mt toán t mt ngôi là mt đi tng c
a lp đó.
. .* :: ?: sizeof
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
78
Ví d 4.1:
Chúng ta xây dng lp s phc vi tên lp là Complexđa nĕng hóa toán t + trên lp này.
1: #include <iostream.h>
2:
3:
class Complex
4: {
5: private:
6: double Real, Imaginary;
7: public:
8: Complex(double R=0.0,double I=0.0);// Constructor mc định
9: void Print(); // Hin th s phc
10: Complex operator+(Complex Z); // Phép cng gia hai s phc
11: Complex operator+(double R); //cng mt s phc vi mt s thc
12: };
13:
14: Complex::Complex(double R,double I)
15:
{
16: Real = R;
17: Imaginary = I;
18:
}
19:
20: void Complex::Print()
21: {
22: cout<<'('<<Real<<','<<Imaginary<<')';
23:
}
24:
25: Complex Complex::operator + (Complex Z)
26:
{
27: Complex Tmp;
28: Tmp.Real = Real + Z.Real;
29: Tmp.Imaginary = Imaginary + Z.Imaginary;
30:
return Tmp;
31:
}
32:
33: Complex Complex::operator + (double R)
34:
{
35: Complex Tmp;
36: Tmp.Real = Real + R;
37: Tmp.Imaginary = Imaginary;
38:
return Tmp;
39: }
40:
41:
int main()
42: {
43: Complex X,Y(4.3,8.2),Z(3.3,1.1);
44: cout<<"X: ";
45: X.Print();
46: cout<<endl<<"Y: ";
47: Y.Print();
48: cout<<endl<<"Z: ";
49: Z.Print();
50: X = Y + Z;
51: cout<<endl<<endl<<"X = Y + Z:"<<endl;
52: X.Print();
53: cout<<" = ";
54: Y.Print();
55: cout<<" + ";
56: Z.Print();
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
79
57: X = Y + 3.5;
58: cout<<endl<<endl<<"X = Y + 3.5:"<<endl;
59: X.Print();
60: cout<<" = ";
61: Y.Print();
62: cout<<" + 3.5";
63:
return 0;
64: }
Hàm thành viên toán t operator + () (t dòng 25 đn 31 và t dòng 33 đn 39) tr v mt đi tng có
kiu Complex là tng ca hai s phc hoc tng ca mt s phc vi mt s thc. Chú ý rng đi tng tam
thi Tmp đc dùng bên trong hàm operator + () đ gi kt qu, và đó là đi tng đc tr v.
Chúng ta chy ví d 4.1
, kt qu hình 4.3
Hình 4.3: Kt qu ca ví d 4.1
Do đa nĕng hóa toán t + trên lp Complex ví d 4.1, chúng ta có th vit:
X = Y + Z;
Câu lnh này đc trình biên dch hiu:
X = Y.operator + (Z);
Nh vy, trong biu thc Y + Z đi tng bên trái toán t + (là đi tng Y) là đi tng mà qua đó,
hàm thành viên toán t operator + () đc gi. Do đó hàm thành viên toán t + ch nhn mt tham sđi
tng bên phi toán tđi tng bên trái toán tđi tng to li gi cho hàm toán tđc truyn
bi con tr this.
Hàm operator + () tr v mt đi tng Complex. Do vy chúng ta có th vit:
(Y + Z).Print();
đ in trên màn hình s phc ca đi tng đc tr v. Đi tng do Y + Z sinh ra nh vy là mt đi
tng tm thi. Nó s không tn ti khi hàm thành Print() kt thúc.
Hn na khi tr v mt đi tng, toán t + cho phép mt chui phép cng. Nên chúng ta cũng có th
vit:
X = X + Y + Z;
Tuy nhiên chúng ta không th nào vit đc câu lnh sau:
X = 3.5 + Y; // Li !!!
Chính vì lý do này chúng ta chn mt hàm không thành viên đ đa nĕng hóa mt toán t đ cho phép
toán t đc giao hoán. Chú ý rng hàm không thành viên không cn thit phi là hàm friend nu các hàm
set và get thích hp tn ti trong phn giao din public, và đt bit nht nu các hàm set và get là các hàm
inline.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
80
Đ đa nĕng hóa toán t << phi có mt toán hng trái ca kiu ostream & (nhcout trong biu thc
cout<<X), vì th nó phi là hàm không thành viên. Tng t, đa nĕng hóa toán t >> phi có mt toán hng
trái ca kiu istream & (nhcin trong biu thc cin>>X), vì th vì th nó cũng phi là hàm không thành
viên.
Ngoi tr đa nĕng hóa toán t >> << liên quan đn dòng nhp/xut d liu chúng ta có hình 4.4 v
cách
đa nĕng hóa toán t nh sau:
Biu thc Hàm thành viên Hàm không thành viên
a#b a.operator#(b) operator#(a,b)
#a a.operator() operator#(a)
a=b a.operator=(b)
a[b] a.operator[](b)
a(b) a.operator()(b)
a-> a.operator->()
a++ a.operator++(0) operator++(a,0)
a-- a.operator--(0) operator--(a,0)
Hình 4.4: Vic cài đt các hàm toán t
V. ĐA NĔNG HOÁ CÁC TOÁN T HAI NGÔI
Các toán t hai ngôi đc đa nĕng hóa trong hình 4.5 sau:
Toán td Toán td Toán td
+
a+b
+=
a+=b
<<=
a<<=b
-
a-b
-=
a-=b
==
a==b
*
a*b
*=
a*=b
!=
a!=b
/
a/b
/=
a/=b
<=
a<=b
%
a%b
%=
a%=b
>=
a>=b
^
a^b
^=
a^=b
&&
a&&b
&
a&b
&=
a&=b
||
a||b
|
a|b
|=
a|=b
,
a,b
=
a=b
<<
a<<b
[]
a[b]
<
a<b
>>
a>>b
->*
a->*b
>
a>b
>>=
a>>=b
Hình 4.5: Các toán t hai ngôi đc đa nĕng hóa
Mt toán t hai ngôi có th đc đa nĕng hóa nh là hàm thành viên không tƿnh vi mt tham s hoc
nh mt hàm không thành viên vi hai tham s (mt trong các tham s này phi là hoc là mt đi tng lp
hoc là mt tham chiu đn đi tng lp).
Ví d 4.2:
Chúng ta xây dng lp s phc vi tên lp là Complexđa nĕng hóa các toán t tính toán +
- += -= và các toán t so sánh == != > >= < <= vi các hàm toán t là các hàm thành viên.
1: #include <iostream.h>
2: #include <math.h>
3:
4: class Complex
5: {
6: private:
7: double Real, Imaginary;
8:
public:
9: Complex(); // Constructor mc định
10: Complex(double R,double I);
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
81
11: Complex (const Complex & Z); // Constructor sao chép
12: Complex (double R); // Constructor chuyn đổi
13: void Print(); // Hin th s phc
14: // Các toán t tính toán
15: Complex operator + (Complex Z);
16: Complex operator - (Complex Z);
17: Complex operator += (Complex Z);
18: Complex operator -= (Complex Z);
19:
// Các toán t so sánh
20: int operator == (Complex Z);
21: int operator != (Complex Z);
22: int operator > (Complex Z);
23: int operator >= (Complex Z);
24: int operator < (Complex Z);
25: int operator <= (Complex Z);
26: private:
27: double Abs(); // Giá tr tuyt đối ca s phc
28: };
29:
30: Complex::Complex()
31:
{
32: Real = 0.0;
33: Imaginary = 0.0;
34:
}
35:
36: Complex::Complex(double R,double I)
37:
{
38: Real = R;
39: Imaginary = I;
40:
}
41:
42: Complex::Complex(const Complex & Z)
43:
{
44: Real = Z.Real;
45: Imaginary = Z.Imaginary;
46:
}
47:
48: Complex::Complex(double R)
49:
{
50: Real = R;
51: Imaginary = 0.0;
52:
}
53:
54: void Complex::Print()
55: {
56: cout<<'('<<Real<<','<<Imaginary<<')';
57: }
58:
59: Complex Complex::operator + (Complex Z)
60:
{
61: Complex Tmp;
62
63: Tmp.Real = Real + Z.Real;
64: Tmp.Imaginary = Imaginary + Z.Imaginary;
65:
return Tmp;
66: }
67:
68: Complex Complex::operator - (Complex Z)
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
82
69: {
70: Complex Tmp;
71:
72: Tmp.Real = Real - Z.Real;
73: Tmp.Imaginary = Imaginary - Z.Imaginary;
74:
return Tmp;
75: }
76:
77: Complex Complex::operator += (Complex Z)
78:
{
79: Real += Z.Real;
80: Imaginary += Z.Imaginary;
81: return *this;
82: }
83:
84: Complex Complex::operator -= (Complex Z)
85:
{
86: Real -= Z.Real;
87: Imaginary -= Z.Imaginary;
88:
return *this;
89: }
90:
91:
int Complex::operator == (Complex Z)
92: {
93:
return (Real == Z.Real) && (Imaginary == Z.Imaginary);
94: }
95:
96:
int Complex::operator != (Complex Z)
97: {
98: return (Real != Z.Real) || (Imaginary != Z.Imaginary);
99: }
100:
101: int Complex::operator > (Complex Z)
102: {
103: return Abs() > Z.Abs();
104: }
105:
106:
int Complex::operator >= (Complex Z)
107: {
108: return Abs() >= Z.Abs();
109:
}
110:
111: int Complex::operator < (Complex Z)
112: {
113: return Abs() < Z.Abs();
114: }
115:
116:
int Complex::operator <= (Complex Z)
117: {
118: return Abs() <= Z.Abs();
119: }
120:
121: double Complex::Abs()
122:
{
123: return sqrt(Real*Real+Imaginary*Imaginary);
124: }
125:
126: int main()
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
83
127: {
128: Complex X, Y(4.3,8.2), Z(3.3,1.1), T;
129
130: cout<<"X: ";
131: X.Print();
132: cout<<endl<<"Y: ";
133: Y.Print();
134: cout<<endl<<"Z: ";
135: Z.Print();
136: cout<<endl<<"T: ";
137: T.Print();
138: T=5.3;
// Gi constructor chuyn kiu
139: cout<<endl<<endl<<"T = 5.3"<<endl;
140: cout<<"T: ";
141: T.Print();
142: X = Y + Z;
143: cout<<endl<<endl<<"X = Y + Z: ";
144: X.Print();
145: cout<<" = ";
146: Y.Print();
147: cout<<" + ";
148: Z.Print();
149: X = Y - Z;
150: cout<<endl<<"X = Y - Z: ";
151: X.Print();
152: cout<<" = ";
153: Y.Print();
154: cout<<" - ";
155: Z.Print();
156: cout<<endl<<endl<<"Y += T i.e ";
157: Y.Print();
158: cout<<" += ";
159: T.Print();
160: Y += T;
161: cout<<endl<<"Y: ";
162: Y.Print();
163: cout<<endl<<"Z -= T i.e ";
164: Z.Print();
165: cout<<" -= ";
166: T.Print();
167: Z -= T;
168: cout<<endl<<"Z: ";
169: Z.Print();
170: Complex U(X);
// Gi constructor sao chép
171: cout<<endl<<endl<<"U: ";
172: U.Print();
173: cout<<endl<<endl<<"Evaluating: X==U"<<endl;
174: if (X==U)
175: cout<<"They are equal"<<endl;
176: cout<<"Evaluating: Y!=Z"<<endl;
177: if (Y!=Z)
178: cout<<"They are not equal => ";
179: if (Y>Z)
180: cout<<"Y>Z";
181: else
182: cout<<"Y<Z";
183:
return 0;
184: }
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
84
Chúng ta chy ví d 4.2
, kt qu hình 4.6.
Dòng th 10 ca chng trình ví d 4.2: Complex(const Complex &Z);
là mt constructor sao chép (copy constructor). Nó khi đng mt đi tng lp bng cách to mt sao
chép ca mt đi tng lp đó. Constructor sao chép thc hin công vic ging nh toán t sao chép nhng
nó có mt vai trò đc bit. Constructor sao chép ch nhn tham s là mt tham chiu ch đn đi tng thuc
chính lp mà nó đc đnh nghƿ
a. Các constructor sao chép đc dùng mi khi mt s sao chép ca mt đi
tng cn thit nh khi có s truyn tham s bng tr, khi tr v mt đi tng t hàm, hoc khi khi đng
mt đi tng mà đc sao chép t đi tng khác ca cùng lp. Chng hn:
Complex A(3.5, 4.5);
Complex B(A);
// Gi constructor sao chép
Complex C = B; // Gi constructor sao chép
…………………
Complex MyFunc(Complex Z) // Gi constructor sao chép
{ rZ; // Gi constructor sao chép }
Hình 4.6: Kt qu ca ví d 4.2
Chúng ta chú ý rng, du = trong câu lnh trên ng vi constructor sao chép ch không phi là toán t
gán . Nu chúng ta không đnh nghƿa constructor sao chép, trình biên dch to ra mt constructor sao chép
mc đnh s sao chép tng thành viên mt.
dòng 12 ca chng trình ví d 4.2:
Complex(double R);
là mt constructor chuyn đi (conversion constructor). Constructor này ly mt tham s double và khi
to đi tng Complex mà phn thc bng giá tr tham s truy
n vào và phn o bng 0.0 (t dòng 48 đn
52). Bt k mt constructor nào có tham s đn có th đc nghƿ nh mt constructor chuyn đi.
Constructor chuyn đi s đi mt s thc thành mt đi tng Complex ri gán cho đi tng đích
Complex. Chng hn:
T = 3.5;
// Ngm đnh: T = Complex(3.5)
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
85
Trình biên dch t đng dùng constructor chuyn đi đ to mt đi tng tm thi Complex, ri dùng
toán t gán đ gán đi tng tm thi này cho đi tng khác ca Complex. Chng hn câu lnh sau vn
đúng:
X = Y + 3.5;
// Ngm đnh: X = Y + Complex(3.5);
Nh vy mt constructor chuyn đi đc s dng đ thc hin mt s chuyn đi ngm đnh.
Ví d 4.3:
Ly li ví d 4.2 nhng các hàm toán t +, - và các hàm toán t so sánh là hàm không thành
viên.
#include <iostream.h>
#include <math.h>
class Complex
{
private:
double Real,Imaginary;
public:
Complex();//Constructor mac dinh
Complex(double R,double I);
Complex (const Complex & Z);//Constructor sao chep
Complex (double R);//Constructor chuyen doi
void Print();//Hien thi so phuc
//Cac toan tu tinh toan
friend Complex operator + (Complex Z1,Complex Z2);
friend Complex operator - (Complex Z1,Complex Z2);
Complex operator += (Complex Z);
Complex operator -= (Complex Z);
//Cac toan tu so sanh
friend int operator == (Complex Z1,Complex Z2);
friend int operator != (Complex Z1,Complex Z2);
friend int operator > (Complex Z1,Complex Z2);
friend int operator >= (Complex Z1,Complex Z2);
friend int operator < (Complex Z1,Complex Z2);
friend int operator <= (Complex Z1,Complex Z2);
private:
double Abs();//Gia tri tuyet doi cua so phuc
};
Complex::Complex()
{
Real = 0.0;
Imaginary = 0.0;
}
Complex::Complex(double R,double I)
{
Real = R;
Imaginary = I;
}
Complex::Complex(const Complex & Z)
{
Real = Z.Real;
Imaginary = Z.Imaginary;
}
Complex::Complex(double R)
{
Real = R;
Imaginary = 0.0;
}
void Complex::Print()
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
86
{
cout<<'('<<Real<<','<<Imaginary<<')';
}
Complex operator + (Complex Z1,Complex Z2)
{
Complex Tmp;
Tmp.Real = Z1.Real + Z2.Real;
Tmp.Imaginary = Z1.Imaginary + Z2.Imaginary;
return Tmp;
}
Complex operator - (Complex Z1,Complex Z2)
{
Complex Tmp;
Tmp.Real = Z1.Real - Z2.Real;
Tmp.Imaginary = Z1.Imaginary - Z2.Imaginary;
return Tmp;
}
Complex Complex::operator += (Complex Z)
{
Real += Z.Real;
Imaginary += Z.Imaginary;
return *this;
}
Complex Complex::operator -= (Complex Z)
{
Real -= Z.Real;
Imaginary -= Z.Imaginary;
return *this;
}
int operator == (Complex Z1,Complex Z2)
{
return (Z1.Real == Z2.Real) && (Z1.Imaginary == Z2.Imaginary);
}
int operator != (Complex Z1,Complex Z2)
{
return (Z1.Real != Z2.Real) || (Z1.Imaginary != Z2.Imaginary);
}
int operator > (Complex Z1,Complex Z2)
{
return Z1.Abs() > Z2.Abs();
}
int operator >= (Complex Z1,Complex Z2)
{
return Z1.Abs() >= Z2.Abs();
}
int operator < (Complex Z1,Complex Z2)
{
return Z1.Abs() < Z2.Abs();
}
int operator <= (Complex Z1,Complex Z2)
{
return Z1.Abs() <= Z2.Abs();
}
double Complex::Abs()
{
return sqrt(Real*Real+Imaginary*Imaginary);
}
int main()
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
87
{
Complex X,Y(4.3,8.2),Z(3.3,1.1);
cout<<"X: "; X.Print();
cout<<endl<<"Y: "; Y.Print();
cout<<endl<<"Z: "; Z.Print();
X = Y + 3.6;
cout<<endl<<endl<<"X = Y + 3.6: ";
X.Print(); cout<<" = ";
Y.Print(); cout<<" + 3.6 ";
X = 3.6 + Y; cout<<endl<<"X = 3.6 + Y: ";
X.Print(); cout<<" = 3.6 + ";
Y.Print(); X = 3.8 - Z;
cout<<endl<<"X = 3.8 - Z: ";
X.Print(); cout<<" = 3.8 - ";
Z.Print(); X = Z - 3.8;
cout<<endl<<"X = Z - 3.8: ";
X.Print(); cout<<" = ";
Z.Print(); cout<<" - 3.8 ";
return 0;
}
Chúng ta chy ví d 4.3
, kt qu hình 4.7
Hình 4.7: Kt qu ca ví d 4.3
VI. ĐA NĔNG HÓA CÁC TOÁN T MT NGÔI
Các toán t mt ngôi đc đa nĕng hóa trong hình 4.8 sau:
Toán td Toán td
+
+c
~
~c
-
-c
!
!a
*
*c
++
++c, c++
&
&c
--
--c, c--
->
c->
Hình 4.8: Các toán t mt ngôi đc đa nĕng hóa
Mt toán t mt ngôi ca lp đc đa nĕng hóa nh mt hàm thành viên không tƿnh vi không có tham
s hoc nh mt hàm không thành viên vi mt tham s; Tham s đó phi hoc là mt đi tng lp hoc là
mt tham chiu đn đi tng lp.
Ví d 4.4:
Ly li ví d 4.3 và thêm toán t du tr mt ngôi.
1: #include <iostream.h>
2: #include <math.h>
3:
4: class Complex
5: {
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
88
6: private:
7: double Real,Imaginary;
8: public:
9: Complex(); // Constructor mc định
10: Complex(double R,double I);
11: Complex (const Complex & Z);
// Constructor sao chép
12: Complex (double R); // Constructor chuyn đổi
13: void Print(); // Hin th s phc
14: // Các toán t tính toán
15: friend Complex operator + (Complex Z1,Complex Z2);
16: friend Complex operator - (Complex Z1,Complex Z2);
17: Complex operator += (Complex Z);
18: Complex operator -= (Complex Z);
19:
// Toán t tr mt ngôi
20: Complex operator – ();
21: // Các toán t so sánh
22: friend int operator == (Complex Z1,Complex Z2);
23: friend int operator != (Complex Z1,Complex Z2);
24: friend int operator > (Complex Z1,Complex Z2);
25: friend int operator >= (Complex Z1,Complex Z2);
26: friend int operator < (Complex Z1,Complex Z2);
27: friend int operator <= (Complex Z1,Complex Z2);
28: private:
29: double Abs(); // Giá tr tuyt đối ca s phc
30:
};
31:
32: Complex::Complex()
33:
{
34: Real = 0.0;
35: Imaginary = 0.0;
36:
}
37:
38: Complex::Complex(double R,double I)
39: {
40: Real = R;
41: Imaginary = I;
42:
}
43:
44: Complex::Complex(const Complex & Z)
45:
{
46: Real = Z.Real;
47: Imaginary = Z.Imaginary;
48:
}
49:
50: Complex::Complex(double R)
51:
{
52: Real = R;
53: Imaginary = 0.0;
54:
}
55:
56:
void Complex::Print()
57: {
58: cout<<'('<<Real<<','<<Imaginary<<')';
59:
}
60:
61: Complex operator + (Complex Z1,Complex Z2)
62:
{
63: Complex Tmp;
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
89
64:
65: Tmp.Real = Z1.Real + Z2.Real;
66: Tmp.Imaginary = Z1.Imaginary + Z2.Imaginary;
67:
return Tmp;
68: }
69:
70: Complex operator - (Complex Z1,Complex Z2)
71:
{
72: Complex Tmp;
73:
74: Tmp.Real = Z1.Real - Z2.Real;
75: Tmp.Imaginary = Z1.Imaginary - Z2.Imaginary;
76:
return Tmp;
77: }
78:
79: Complex Complex::operator += (Complex Z)
80:
{
81: Real += Z.Real;
82: Imaginary += Z.Imaginary;
83:
return *this;
84: }
85:
86: Complex Complex::operator -= (Complex Z)
87:
{
88: Real -= Z.Real;
89: Imaginary -= Z.Imaginary;
90:
return *this;
91:
}
92:
93: Complex Complex::operator - ()
94:
{
95: Complex Tmp;
96:
97: Tmp.Real = -Real;
98: Tmp.Imaginary = -Imaginary;
99:
return Tmp;
100: }
101
102: int operator == (Complex Z1,Complex Z2)
103: {
104:
return (Z1.Real == Z2.Real) && (Z1.Imaginary == Z2.Imaginary);
105: }
106:
107: int operator != (Complex Z1,Complex Z2)
108: {
109: return (Z1.Real != Z2.Real) || (Z1.Imaginary != Z2.Imaginary);
110: }
111:
112: int operator > (Complex Z1,Complex Z2)
113: {
114: return Z1.Abs() > Z2.Abs();
115: }
116:
117:
int operator >= (Complex Z1,Complex Z2)
118: {
119: return Z1.Abs() >= Z2.Abs();
120: }
121:
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
90
122: int operator < (Complex Z1,Complex Z2)
123: {
124: return Z1.Abs() < Z2.Abs();
125: }
126:
127:
int operator <= (Complex Z1,Complex Z2)
128: {
129: return Z1.Abs() <= Z2.Abs();
130: }
131:
132: double Complex::Abs()
133: {
134: return sqrt(Real*Real+Imaginary*Imaginary);
135: }
136:
137: int main()
138: {
139: Complex X, Y(4.3,8.2), Z(3.3,1.1);
140:
141: cout<<"X: ";
142: X.Print();
143: cout<<endl<<"Y: ";
144: Y.Print();
145: cout<<endl<<"Z: ";
146: Z.Print();
147: X = -Y + 3.6;
148: cout<<endl<<endl<<"X = -Y + 3.6: ";
149: X.Print();
150: cout<<" = ";
151: (-Y).Print();
152: cout<<" + 3.6 ";
153: X = -Y + -Z;
154: cout<<endl<<"X = -Y + -Z: ";
155: X.Print();
156: cout<<" = ";
157: (-Y).Print();
158: cout<<" + ";
159: (-Z).Print();
160:
return 0;
161: }
Chúng ta chy ví d 4.4
, kt qu hình 4.9
Hình 4.9: Kt qu ca ví d 4.4
VII. ĐA NĔNG HÓA MT S TOÁN T ĐC BIT
Trong phn này chúng ta s tìm hiu cách cài đt mt vài toán t đc bit nh () [] ++ -- , = ->
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
91
VII.1. Toán t []
Khi cài đt các lp vector hoc chui ký t, chúng ta cn phi truy cp đn tng phn t ca chúng,
trong ngôn ng C/C++ đã có toán t [] đ truy cp đn mt phn t ca mng. Đây là toán t hai ngôi, có
dng a[b] và khi đa nĕng toán t này thì hàm toán t tng ng phi là thành viên ca mt lp.
Ví d 4.5:
Đa nĕng hóa toán t [] đ truy cp đn mt phn t ca vector.
1: #include <iostream.h>
2:
3:
class Vector
4: {
5: private:
6: int Size;
7: int *Data;
8:
public:
9: Vector(int S=2,int V=0);
10: ~Vector();
11:
void Print() const;
12: int & operator [] (int I);
13: };
14:
15: Vector::Vector(int S,int V)
16: {
17: Size = S;
18: Data=new int[Size];
19: for(
int I=0;I<Size;++I)
20: Data[I]=V;
21:
}
22:
23: Vector::~Vector()
24:
{
25: delete []Data;
26: }
27:
void Vector::Print() const
28: {
29: cout<<"Vector:(";
30: for(int I=0;I<Size-1;++I)
31: cout<<Data[I]<<",";
32: cout<<Data[Size-1]<<")"<<endl;
33:
}
34:
35: int & Vector::operator [](int I)
36:
{
37: return Data[I];
38: }
39:
40:
int main()
41: {
42: Vector V(5,1);
43: V.Print();
44: for(
int I=0;I<5;++I)
45: V[I]*=(I+1);
46: V.Print();
47: V[0]=10;
48: V.Print();
49:
return 0;
50: }
Chúng ta chy ví d 4.5
, kt qu hình 4.10
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
92
Hình 4.10: Kt qu ca ví d 4.5
Trong chng trình ví d 4.5, hàm toán t ca toán t [] lp Vector tr v mt tham chiu vì toán t
này có th dùng v trái ca phép gán.
VII.2. Toán t ()
Toán t () đc dùng đ gi hàm, toán t này gm hai toán hng: toán hng đu tiên là tên hàm, toán
hng th hai là danh sách các tham s ca hàm. Toán t này có dng ging nh toán t [] và khi đa nĕng
toán t này thì hàm toán t tng ng phi là thành viên ca mt lp.
Ví d 4.6:
Ly li ví d 4.5 nhng đa nĕng hóa toán t () đ truy cp đn mt phn t ca vector.
1: #include <iostream.h>
2:
3: class Vector
4: {
5: private:
6: int Size;
7: int *Data;
8: public:
9: Vector(int S=2,int V=0);
10: ~Vector();
11:
void Print() const;
12: int & operator () (int I);
13: };
14:
15: Vector::Vector(
int S,int V)
16: {
17: Size = S;
18: Data=new int[Size];
19: for(
int I=0;I<Size;++I)
20: Data[I]=V;
21:
}
22:
23: Vector::~Vector()
24:
{
25: delete []Data;
26:
}
27: void Vector::Print() const
28: {
29: cout<<"Vector:(";
30: for(
int I=0;I<Size-1;++I)
31: cout<<Data[I]<<",";
32: cout<<Data[Size-1]<<")"<<endl;
33:
}
34:
35: int & Vector::operator ()(int I)
36: {
37: return Data[I];
38: }
39:
40:
int main()
41: {
42: Vector V(5,1);
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
93
43: V.Print();
44: for(int I=0;I<5;++I)
45: V(I)*=(I+1);
46: V.Print();
47: V(0)=10;
48: V.Print();
49:
return 0;
50: }
Chúng ta chy ví d 4.6
, kt qu hình 4.11
Hình 4.11: Kt qu ca ví d 4.6
Ví d 4.7:
Đa nĕng hóa toán t () đ truy cp đn phn t ca ma trn.
1: #include <iostream.h>
2:
3:
class Matrix
4: {
5: private:
6:
int Rows,Cols;
7: int **Data;
8: public:
9: Matrix(
int R=2,int C=2,int V=0);
10: ~Matrix();
11: void Print() const;
12: int & operator () (int R,int C);
13: };
14:
15: Matrix::Matrix(int R,int C,int V)
16: {
17: int I,J;
18: Rows=R;
19: Cols=C;
20: Data = new
int *[Rows];
21: int *Temp=new int[Rows*Cols];
22: for(I=0;I<Rows;++I)
23:
{
24: Data[I]=Temp;
25: Temp+=Cols;
26:
}
27: for(I=0;I<Rows;++I)
28: for(J=0;J<Cols;++J)
29: Data[I][J]=V;
30:
}
31:
32: Matrix::~Matrix()
33:
{
34: delete [] Data[0];
35: delete [] Data;
36:
}
37:
38: void Matrix::Print() const
39: {
40: int I,J;
41: for(I=0;I<Rows;++I)
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
94
42: {
43: for(J=0;J<Cols;++J)
44: {
45: cout.width(5); // Hin th canh l phi vi chiu dài 5 ký t
46: cout<<Data[I][J];
47:
}
48: cout<<endl;
49: }
50: }
51:
52: int & Matrix::operator () (int R,int C)
53: {
54: return Data[R][C];
55: }
56:
57: int main()
58: {
59: int I,J;
60: Matrix M(2,3,1);
61: cout<<"Matrix:"<<endl;
62: M.Print();
63: for(I=0;I<2;++I)
64: for(J=0;J<3;++J)
65: M(I,J)*=(I+J+1);
66: cout<<"Matrix:"<<endl;
67: M.Print();
68:
return 0;
69:
}
Chúng ta chy ví d 4.7
, kt qu hình 4.12
Hình 4.12: Kt qu ca ví d 4.7
VIII. TOÁN T CHUYN ĐI KIU
Phn ln các chng trình x lý thông tin s đa dng ca các kiu. Đôi khi tt c các thao tác "dng li
bên trong mt kiu". Chng hn, mt s nguyên vi mt s nguyên to thành mt s nguyên (min là kt qu
không quá ln đ đc biu din nh mt s nguyên). Nhng tht cn thit đ chuyn đi d liu ca mt
ki
u ti d liu ca kiu khác. Điu này có th xy ra trong các phép gán, các kt qu tính toán, trong vic
chuyn các giá tr ti hàm, và trong vic tr v tr t hàm. Trình biên dch bit làm th nào đ thc hin các
chuyn đi nào đó trong s các kiu có sn. Các lp trình viên có th ép buc các chuyn đi trong s các
kiu có sn bi ép kiu.
Nhng đi vi các kiu do ngi dùng đnh ngh
ƿa thì trình biên dch không th t đng bit làm th nào
chuyn đi trong s các kiu d liu do ngi dùng đnh nghƿa và các kiu có sn. Lp trình viên phi ch
làm sao các chuyn đi nh vy s xut hin. Các chuyn đi nh th có th đc thc hin vi constructor
chuyn đi.
Mt toán t chuyn đi kiu có th đc s dng đ
chuyn đi mt đi tng ca mt lp thành đi
tng ca mt lp khác hoc thành mt đi tng ca mt kiu có sn. Toán t chuyn đi kiu nh th phi
là hàm thành viên không tƿnh và không là hàm friend. Prototype ca hàm thành viên này có cú pháp:
operator <data type> ();
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
95
Ví d 4.14:
Toán t chuyn đi kiu
1: #include <iostream.h>
2:
3:
class Number
4: {
5: private:
6: float Data;
7: public:
8: Number(float F=0.0)
9: {
10: Data=F;
11: }
12: operator float()
13: {
14: return Data;
15: }
16: operator int()
17: {
18: return (int)Data;
19: }
20: };
21:
22: int main()
23: {
24: Number N1(9.7), N2(2.6);
25: float X=(float)N1; //Gi operator float()
26: cout<<X<<endl;
27: int Y=(int)N2; //Gi operator int()
28: cout<<Y<<endl;
29: return 0;
30: }
Chúng ta chy ví d 4.14
, kt qu hình 4.19
Hình 4.19: Kt qu ca ví d 4.14
IX. TOÁN T NEW VÀ DELETE
Các toán t new delete toàn cc có th đc đa nĕng hóa. Điu này cho phép các lp trình viên C++
có kh nĕng xây dng mt h thng cp phát b nh theo ý ngi dùng, cói cùng giao tip nh h thng cp
phát mc đnh.
Có hai cách đa nĕng hóa các toán t newdelete:
Có th đa nĕng hóa mt cách toàn cc nghƿa là thay th hn các toán t new delete mc đnh.
Chúng ta đ
a nĕng hóa các toán t newdelete vi t cách là hàm thành viên ca lp nu mun các
toán t newdelete áp dng đi vi lp đó. Khi chúng ta dùng newdelete đi vi lp nào đó, trình
biên dch s kim tra xem newdeleteđc đnh nghƿa riêng cho lp đó hay không; nu không thì dùng
newdelete toàn cc (có th đã đc đa nĕng hóa).
Hàm toán t ca toán t newdelete có prototype nh
sau:
void * operator new(size_t size);
void operator delete(void * ptr);
Trong đó tham s kiu size_t đc trình biên dch hiu là kích thc ca kiu d liu đc trao cho toán
t new.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
96
IX.1. Đa nĕng hóa toán t new và delete toàn cc
Ví d 4.15:
Đa nĕng hóa toán t newdelete toàn cc đng thi chng t rng toán t newdelete
do đa nĕng hóa thay th toán t newdelete mc đnh.
1: #include <iostream.h>
2: #include <stdlib.h>
3:
4:
class Point
5: {
6: private:
7: int X, Y;
8: public:
9: Point(int A=0,int B=0)
10: {
11: X=A;
12: Y=B;
13: cout<<"Constructor!"<<endl;
14: }
15: ~Point()
16: {
17: cout<<"Destructor!"<<endl;
18: }
19: void Print() const
20: {
21: cout<<"X="<<X<<","<<"Y="<<Y<<endl;
22: }
23: };
24:
25: void * operator new(size_t Size)
26: {
27: return malloc(Size);
28: }
29:
30: void operator delete(void *Ptr)
31: {
32: free(Ptr);
33: }
34:
35: int main()
36: {
37: Point *P1,*P2;
38: P1= new Point(10,20);
39: if (P1==NULL)
40: {
41: cout<<"Out of memory!"<<endl;
42: return 1;
43: }
44: P2= new Point(-10,-20);
45: if (P2==NULL)
46: {
47: cout<<"Out of memory!"<<endl;
48: return 1;
49: }
50: int *X=new int;
51: if (X==NULL)
52: {
53: cout<<"Out of memory!"<<endl;
54: return 1;
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
97
55: }
56: *X=10;
57: cout<<"X="<<*X<<endl;
58: cout<<"Point 1:";
59: P1->Print();
60: cout<<"Point 2:";
61: P2->Print();
62: delete P1;
63: delete P2;
64: delete X;
65: return 0;
66: }
Chúng ta chy ví d 4.15
, kt qu hình 4.20
Hình 4.20: Kt qu ca ví d 4.15
IX.2. Đa nĕng hóa toán t new và delete cho mt lp
Nu mun toán t newdelete có tính cht đc bit ch khi áp dng cho đi tng ca lp nào đó,
chúng ta có th đa nĕng hóa toán t newdelete vi t cách là hàm thành viên ca lp đó. Vic này không
khác lm so vi cách đa nĕng hóa toán t newdelete mt cách toàn cc.
Ví d 4.16:
Đa nĕng hóa toán t newdelete cho mt lp.
1: #include <iostream.h>
2: #include <stdlib.h>
3:
class Number
4: {
5: private:
6: int Data;
7: public:
8: Number(int X=0)
9: {
10: Data=X;
11: }
12:
13: void * operator new(size_t Size)
14: {
15: cout<<"Toan tu new cua lop!"<<endl;
16: return ::new unsigned char[Size];
17: }
18:
19: void operator delete(void *Ptr)
20: {
21: cout<<"Toan tu delete cua lop!"<<endl;
22: ::delete Ptr;
23: }
24:
25: void Print() const
26: {
27: cout<<"Data:"<<Data<<endl;
28: }
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
98
29:
30: };
31:
32: int main()
33: {
34: Number *N;
35: N= new Number(10);
36: if (N==NULL)
37: {
38: cout<<"Out of memory!"<<endl;
39: return 1;
40: }
41: int *X=new int;
42: if (X==NULL)
43: {
44: cout<<"Out of memory!"<<endl;
45: return 1;
46: }
47: *X=10;
48: cout<<"X="<<*X<<endl;
49: N->Print();
50: delete N;
51: delete X;
52: return 0;
53: }
Chúng ta chy ví d 4.16
, kt qu hình 4.21
Hình 4.21: Kt qu ca ví d 4.16
X. ĐA NĔNG HÓA CÁC TOÁN T CHÈN DÒNG << VÀ TRÍCH DÒNG >>
Chúng ta có th đa nĕng hóa các toán t chèn dòng << (stream insertion) và trích dòng >> (stream
extraction). Hàm toán t ca toán t << đc đa nĕng hóa có prototype nh sau:
ostream & operator << (ostream & stream, ClassName Object);
Hàm toán t << tr v tham chiu ch đn dòng xut ostream. Tham s th nht ca hàm toán t <<
mt tham chiu ch đn dòng xut ostream, tham s th hai là đi tng đc chèn vào dòng. Khi s dng,
dòng trao cho toán t << (tham s th
nht) là toán hng bên trái và đi tng đc đa vào dòng (tham s
th hai) là toán hng bên phi. Đ bo đm cách dùng toán t << luôn nht quán, chúng ta không th đnh
nghƿa hàm toán t << nh là hàm thành viên ca lp đang xét, thông thng nó chính là hàm friend.
Còn hàm toán t ca toán t >> đc đa nĕng hóa có prototype nh sau:
istream & operator >> (istream & stream, ClassName Object);
Hàm toán t >> tr v tham chiu ch đn dòng nhp istream. Tham s th nh
t ca hàm toán t này là
mt tham chiu ch đn dòng nhp istream, tham s th hai là đi tng ca lp đang xét mà chúng ta mun
to dng nh vào d liu ly t dòng nhp. Khi s dng, dòng nhp đóng vai toán hng bên trái, đi tng
nhn d liu đóng vai toán hng bên phi. Cũng nh trng hp toán t <<, hàm toán t >> không là hàm
thành viên ca lp, thông thng nó chính là hàm friend.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
99
Ví d 4.17:
1: #include <iostream.h>
2:
3:
class Point
4: {
5: private:
6: int X,Y;
7: public:
8: Point();
9: friend ostream & operator << (ostream & Out,Point & P);
10: friend istream & operator >> (istream & In,Point & P);
11: };
12:
13: Point::Point()
14: {
15: X=Y=0;
16: }
17:
18: ostream & operator << (ostream & Out,Point & P)
19: {
20: Out<<"X="<<P.X<<",Y="<<P.Y<<endl;
21: return Out; //Cho phép cout<<a<<b<<c;
22: }
23:
24: istream & operator >> (istream &In,Point & P)
25: {
26: cout<<"X:";
27: In>>P.X;
28: cout<<"Y:";
29: In>>P.Y;
30: return In; //Cho phép cin>>a>>b>>c;
31: }
32:
33: int main()
34: {
35: Point P;
36: cin>>P;
37: cout<<"Point:"<<P;
38: return 0;
39: }
Chúng ta chy ví d 4.17
, kt qu hình 4.22
Hình 4.22: Kt qu ca ví d 4.17
XI. MT S VÍ D
XI.1. Lp String
Ví d 4.18:
Chúng ta s xây dng mt lp x lý vic to và thao tác trên các chui (string). C++ không
cài sn kiu d liu chui. Nhng C++ cho phép chúng ta thêm kiu chui nh mt lp thông qua c ch đa
nĕng hóa.
#include <iostream.h>
#include <iomanip.h>
#include <string.h>
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
100
#include <assert.h>
class String
{
private:
char *Ptr; //Con tro tro den diem bat dau cua chuoi
int Length; //Chieu dai chuoi
public:
String(const char * = ""); //Constructor chuyen doi
String(const String &); //Constructor sao chep
~String(); //Destructor
const String &operator=(const String &); //Phep gan
String &operator+=(const String &); //Phep noi
int operator!() const; //Kiem tra chuoi rong
int operator==(const String &) const;
int operator!=(const String &) const;
int operator<(const String &) const;
int operator>(const String &) const;
int operator>=(const String &) const;
int operator<=(const String &) const;
char & operator[](int); //Tra ve ky tu tham chieu
String &operator()(int, int); //Tra ve mot chuoi con
int GetLength() const;
friend ostream &operator<<(ostream &, const String &);
friend istream &operator>>(istream &, String &);
};
//Constructor sao chep: Chuyen doi char * thanh String
String::String(const char *S)
{
cout << "Conversion constructor: " << S << endl;
Length = strlen(S);
Ptr = new char[Length + 1];
assert(Ptr != 0);
strcpy(Ptr, S);
}
String::String(const String &Copy)
{
cout << "Copy constructor: " << Copy.Ptr << endl;
Length = Copy.Length;
Ptr = new char[Length + 1];
assert(Ptr != 0);
strcpy(Ptr, Copy.Ptr);
}
//Destructor
String::~String()
{
cout << "Destructor: " << Ptr << endl;
delete [] Ptr;
}
const String &String::operator=(const String &Right)
{
cout << "operator= called" << endl;
if (&Right != this)
{
delete [] Ptr;
Length = Right.Length;
Ptr = new char[Length + 1];
assert(Ptr != 0);
strcpy(Ptr, Right.Ptr);
}
else
cout << "Attempted assignment of a String to itself" << endl;
return *this;
}
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
101
String &String::operator+=(const String &Right)
{
char *TempPtr = Ptr;
Length += Right.Length;
Ptr = new char[Length + 1];
assert(Ptr != 0);
strcpy(Ptr, TempPtr);
strcat(Ptr, Right.Ptr);
delete [] TempPtr;
return *this;
}
int String::operator!() const
{
return Length == 0;
}
int String::operator==(const String &Right) const
{
return strcmp(Ptr, Right.Ptr) == 0;
}
int String::operator!=(const String &Right) const
{
return strcmp(Ptr, Right.Ptr) != 0;
}
int String::operator<(const String &Right) const
{
return strcmp(Ptr, Right.Ptr) < 0;
}
int String::operator>(const String &Right) const
{
return strcmp(Ptr, Right.Ptr) > 0;
}
int String::operator>=(const String &Right) const
{
return strcmp(Ptr, Right.Ptr) >= 0;
}
int String::operator<=(const String &Right) const
{
return strcmp(Ptr, Right.Ptr) <= 0;
}
char &String::operator[](int Subscript)
{
assert(Subscript >= 0 && Subscript < Length);
return Ptr[Subscript];
}
String &String::operator()(int Index, int SubLength)
{
assert(Index >= 0 && Index < Length && SubLength >= 0);
String *SubPtr = new String;
assert(SubPtr != 0);
if ((SubLength == 0) || (Index + SubLength > Length))
SubPtr->Length = Length - Index + 1;
else
SubPtr->Length = SubLength + 1;
delete SubPtr->Ptr;
SubPtr->Ptr = new char[SubPtr->Length];
assert(SubPtr->Ptr != 0);
strncpy(SubPtr->Ptr, &Ptr[Index], SubPtr->Length);
SubPtr->Ptr[SubPtr->Length] = '\0';
return *SubPtr;
}
int String::GetLength() const
{ return Length;
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
102
}
ostream &operator<<(ostream &Output, const String &S)
{
Output << S.Ptr;
return Output;
}
istream &operator>>(istream &Input, String &S)
{
char Temp[100];
Input >> setw(100) >> Temp;
S = Temp;
return Input;
}
int main()
{
String S1("happy"), S2(" birthday"), S3;
cout << "S1 is \"" << S1 << "\"; S2 is \"" << S2
<< "\"; S3 is \"" << S3 << '\"' << endl
<< "The results of comparing S2 and S1:" << endl
<< "S2 == S1 yields " << (S2 == S1) << endl
<< "S2 != S1 yields " << (S2 != S1) << endl
<< "S2 > S1 yields " << (S2 > S1) << endl
<< "S2 < S1 yields " << (S2 < S1) << endl
<< "S2 >= S1 yields " << (S2 >= S1) << endl
<< "S2 <= S1 yields " << (S2 <= S1) << endl;
cout << "Testing !S3:" << endl;
if (!S3)
{
cout << "S3 is empty; assigning S1 to S3;" << endl;
S3 = S1;
cout << "S3 is \"" << S3 << "\"" << endl;
}
cout << "S1 += S2 yields S1 = ";
S1 += S2;
cout << S1 << endl;
cout << "S1 += \" to you\" yields" << endl;
S1 += " to you";
cout << "S1 = " << S1 << endl;
cout << "The substring of S1 starting at" << endl
<< "location 0 for 14 characters, S1(0, 14), is: "
<< S1(0, 14) << endl;
cout << "The substring of S1 starting at" << endl
<< "location 15, S1(15, 0), is: "
<< S1(15, 0) <<endl; // 0 is "to end of string"
String *S4Ptr = new String(S1);
cout << "*S4Ptr = " << *S4Ptr <<endl;
cout << "assigning *S4Ptr to *S4Ptr" << endl;
*S4Ptr = *S4Ptr;
cout << "*S4Ptr = " << *S4Ptr << endl;
delete S4Ptr;
S1[0] = 'H';
S1[6] = 'B';
cout <<"S1 after S1[0] = 'H' and S1[6] = 'B' is: "<< S1 << endl;
cout << "Attempt to assign 'd' to S1[30] yields:" << endl;
S1[30] = 'd'; //Loi: Chi so vuot khoi mien!!!
return 0;
}
Chúng ta chy ví d 4.18
, kt qu hình 4.23
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
103
Hình 4.23: Kt qu ca ví d 4.18
XI.2. Lp Date
Ví d 4.19:
#include <iostream.h>
class Date
{
private:
int Month;
int Day;
int Year;
static int Days[]; //Mang chua so ngay trong thang
void HelpIncrement(); //Ham tang ngay len mot
public:
Date(int M = 1, int D = 1, int Y = 1900);
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
104
void SetDate(int, int, int);
Date operator++(); //Tien to
Date operator++(int); //Hau to
const Date &operator+=(int);
int LeapYear(int); //Kiem tra nam nhuan
int EndOfMonth(int); //Kiem tra cuoi thang
friend ostream &operator<<(ostream &, const Date &);
};
int Date::Days[] = {31, 28, 31, 30, 31, 30,31, 31, 30, 31, 30, 31};
Date::Date(int M, int D, int Y)
{
SetDate(M, D, Y);
}
void Date::SetDate(int MM, int DD, int YY)
{
Month = (MM >= 1 && MM <= 12) ? MM : 1;
Year = (YY >= 1900 && YY <= 2100) ? YY : 1900;
if (Month == 2 && LeapYear(Year))
Day = (DD >= 1 && DD <= 29) ? DD : 1;
else
Day = (DD >= 1 && DD <= Days[Month-1]) ? DD : 1;
}
Date Date::operator++()
{
HelpIncrement();
return *this;
}
Date Date::operator++(int)
{
Date Temp = *this;
HelpIncrement();
return Temp;
}
const Date &Date::operator+=(int AdditionalDays)
{
for (int I = 1; I <= AdditionalDays; I++)
HelpIncrement();
return *this;
}
int Date::LeapYear(int Y)
{
if (Y % 400 == 0 || (Y % 100 != 0 && Y % 4 == 0) )
return 1; //Nam nhuan
return 0; //Nam khong nhuan
}
int Date::EndOfMonth(int D)
{
if (Month == 2 && LeapYear(Year))
return D == 29;
return D == Days[Month-1];
}
void Date::HelpIncrement()
{
if (EndOfMonth(Day) && Month == 12) //Het nam
{
Day = 1;
Month = 1;
++Year;
}
else
if (EndOfMonth(Day)) //Het thang
{
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
105
Day = 1;
++Month;
}
else
++Day;
}
ostream &operator<<(ostream &Output, const Date &D)
{
static char*MonthName[12]={"January","February","March","April","May",
"June","July", "August","September",
"October","November", "December" };
Output << MonthName[D.Month-1] << ' '<< D.Day << ", " << D.Year;
return Output;
}
int main()
{
Date D1, D2(12, 27, 1992), D3(0, 99, 8045);
cout << "D1 is " << D1 << endl
<< "D2 is " << D2 << endl
<< "D3 is " << D3 << endl << endl;
cout << "D2 += 7 is " << (D2 += 7) << endl << endl;
D3.SetDate(2, 28, 1992);
cout << " D3 is " << D3 << endl;
cout << "++D3 is " << ++D3 << endl << endl;
Date D4(3, 18, 1969);
cout << "Testing the preincrement operator:" << endl
<< " D4 is " << D4 << endl;
cout << "++D4 is " << ++D4 << endl;
cout << " D4 is " << D4 << endl << endl;
cout << "Testing the postincrement operator:" << endl
<< " D4 is " << D4 << endl;
cout << "D4++ is " << D4++ << endl;
cout << " D4 is " << D4 << endl;
return 0;
}
Chúng ta chy ví d 4.19
, kt qu hình 4.24
Hình 4.24: Kt qu ca ví d 4.19
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
106
BÀI TP
Bài 1: Xây dng lp Complex cha các s phc gm các phép toán: +, -, *, /, +=, -=, *=, /=, ==,
!=, >, >=, <, <=.
Bài 2: Xây dng lp String đ thc hin các thao tác trên các chui, trong lp này có các phép
toán:
Phép toán + đ ni hai chui li vi nhau.
Phép toán = đ gán mt chui cho mt chui khác.
Phép toán [] truy cp đn mt ký t trong chui.
Các phép toán so sánh: ==, !=, >, >=, <, <=
Bài 3: Xây dng lp ma trn Matrix gm các phép toán cng, tr và nhân hai ma trn bt k.
Bài 4: Xây dng lp Rational cha các s hu t gm các phép toán +, - , *, /, ==, !=, >, >=, <,
<=.
Bài 5: Xây dng lp Time đ lu tr gi, phút, giây gm các phép toán:
Phép cng gia d liu thi gian và mt s nguyên là s giây, kt qu là mt d
liu thi gian.
Phép tr gia hai d liu thi gian, kt qu là mt s nguyên chính là s giây.
++ và – đ tĕng hay gim thi gian xung mt giây.
Các phép so sánh.
Bài 6: Xây dng lp Date đ lu tr ngày, tháng, nĕm gm các phép toán:
Phép cng gia d liu Date và mt s nguyên là s ngày, kt qu là mt d liu
Date.
Phép tr gia hai d liu Date, kt qu là mt s nguyên chính là s ngày.
++ và – đ tĕng hay gim thi gian xung mt ngày.
Các phép so sánh.
Bài 7: Các s nguyên 32 bit có th biu din trong phm vi t 2147483648 đn 2147483647. Hãy
xây dng lp HugeInt đ biu din các s nguyên 32 bit gm các phép toán +, -, *, /
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
107
CHƯƠNG 5
TÍNH K THA
I. DN NHP
Trong chng này và chng k, chúng ta tìm hiu hai kh nĕng mà lp trình hng đi tng cung cp
là tính k tha (inheritance) và tính đa hình (polymorphism). Tính k tha là mt hình thc ca vic s dng
li phn mm trong đó các lp mi đc to t các lp đã có bng cách "hút" các thuc tính và hành vi ca
chúng và tô đim thêm vi các kh nĕng mà các lp mi đòi hi. Vic s dng l
i phn mm tit kim thi
gian trong vic phát trin chng trình. Nó khuyn khích s dng li phn mm cht lng cao đã th thách
và g li, vì th gim thiu các vn đ sau khi mt h tr thành chính thc. Tính đa hình cho phép chúng ta
vit các chng trình trong mt kiu cách chung đ x lý các lp có liên h nhau. Tính k tha và tính đa
hình các k thut có hiu lc đi vi s chia v
i s phc tp ca phn mm.
Khi to mt lp mi, thay vì vit các thành viên d liu và các hàm thành viên, lp trình viên có th thit
k mà lp mi đc k tha các thành viên d liu và các hàm thành viên ca lp trc đnh nghƿa là lp c
s (base class). Lp mi đc tham chiu là lp dn xut (derived class). Mi lp dn xut t nó tr thành
mt ng c
là mt lp c s cho lp dn xut tng lai nào đó.
Bình thng mt lp dn xut thêm các thành viên d liu và các hàm thành viên, vì th mt lp dn
xut thông thng rng hn lp c s ca nó. Mt lp dn xut đc ch đnh hn mt lp c s và biu
din mt nhóm ca các đi tng nh hn. Vi đi tng đn, lp dn xut, lp dn xut bt đu bên ngoài
thc cht ging nh lp c s. Sc mnh thc s ca s k tha là kh nĕng đnh nghƿa trong lp dn xut
các phn thêm, thay th hoc tinh lc các đc tính k tha t lp c s.
Mi đi tng ca m
t lp dn xut cũng là mt đi tng ca lp c s ca lp dn xut đó. Tuy nhiên
điu ngc li không đúng, các đi tng lp c s không là các đi tng ca các lp dn xut ca lp c
s đó. Chúng ta s ly mi quan h "đi tng lp dn xut là mt đi tng l
p c s" đ thc hin các thao
tác quan trng nào đó. Chng hn, chúng ta có th lun mt s đa dng ca các đi tng khác nhau có liên
quan thông qua s k tha thành danh sách liên kt ca các đi tng lp c s. Điu này cho phép s đa
dng ca các đi tng đ x lý mt cách tng quát.
Chúng ta phân bit gia "là mt" (is a) quan h và "có mt" (has a) quan h. "là mt" là s k
tha.
Trong mt "là mt" quan h, mt đi tng ca kiu lp dn xut cũng có th đc x lý nh mt đi tng
ca kiu lp c s. "có mt" là s phc hp (composition). Trong mt "có mt" quan h, mt đi tng lp
có mt hay nhiu đi tng ca các lp khác nh là các thành viên, do đó lp bao các đi tng này gi là
lp phc hp (composed class).
II. K THA ĐN
II.1. Các lp c s và các lp dn xut
Thng mt đi tng ca mt lp tht s là mt đi tng ca lp khác cũng đc. Mt hình ch nht
là mt t giác, vì th lp Rectangle có th k tha t lp Quadrilateral. Trong khung cnh này, lp
Quadrilateral gi là mt lp c s và lp Rectangle gi là mt lp dn xut. Hình 5.1 cho chúng ta mt vài
ví d v k th
a đn.
Các ngôn ng lp trình hng đi tng nh SMALLTALK s dng thut ng khác: Trong k tha, lp
c s đc gi là lp cha (superclass), lp dn xut đc gi là lp con (subclass).
Lp c s Lp dn xut
GraduateStudent Student
UndergraduateStudent
Circle
Triangle
Shape
Rectangle
Loan CarLoan
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
108
HomeImprovementLoan
MortgageLoan
FacultyMember Employee
StaffMember
CheckingAcount Acount
SavingsAcount
Hình 5.1: Mt vài k tha đn.
S k tha hình thành các cu trúc phân cp ging cây (còn gi là cây ph h). Mt lp c s tn ti
trong mt phân cp quan h vi lp dn xut ca nó. Mt lp có th tn ti chc chn bi chính nó, nhng
khi mt lp đc s dng vi c ch ca s k tha thì l
p tr thành hoc là mt lp c s mà cung cp các
thuc tính và các hành vi cho các lp khác, hoc là lp tr thành mt lp dn xut mà k tha các thuc tính
và các hành vi.
Chúng ta phát trin mt phân cp k tha đn. Mt trng đi hc cng đng đc thù có hàng ngàn
ngi mà là các thành viên cng đng. Nhng ngi này gm các ngi làm công và các sinh viên. Nhng
ngi làm công hoc là các thành viên khoa hoc các thành viên nhân viên. Các thành viên khoa hoc là các
nhà qun lý hoc ging viên.
Điu này tr thành phân cp k tha nh hình 5.2
Hình 5.2: Mt phân cp k tha cho các thành viên ca trng đi hc cng đng.
Phân cp k tha quan trng khác là phân cp Shape hình 5.3.
Hình 5.3: Phân cp lp Shape
Đ ch đnh lp CommissionWorker đc dn xut t lp Employee, lp CommissionWorker đc đnh
nghƿa nh sau:
class CommissionWorker: public Employee
{………….
};
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
109
Điu này đc gi là k tha public và là loi mà phn ln đc s dng. Ngoài ra chúng ta còn có k
tha private và k tha protected. Vi k tha public, các thành viên public protected ca lp c s
đc k tha nh là các thành viên public protected ca lp dn xut tng ng. Nên nh rng các thành
viên private ca lp c s không th truy c
p t các lp dn xut ca lp đó.
X lý các đi tng lp c s và các đi tng lp dn xut tng t; ph bin là đc biu din bng
các thuc tính và các hành vi ca lp c s. Các đi tng ca bt k lp nào dn xut t mt lp c s
chung có th tt c đc x lý nh các đi tng ca lp c s đó.
II.2. Các thành viên protected
Các thành viên public ca mt lp c s đc truy cp bi tt c các hàm trong chng trình. Các thành
viên private ca mt lp c s ch đc truy cp bi các hàm thành viên và các hàm friend ca lp c s.
Truy cp protected phc v nh mt mc trung gian ca s bo v gia truy cp public và truy cp
private. Các thành viên protected ca mt lp c s có th
ch đc truy cp bi các hàm thành viên và các
hàm friend ca lp c s và bi các hàm thành viên và các hàm friend ca lp dn xut.
Các thành viên lp dn xut k tha public có th tham kho ti các thành viên public protected
bng cách s dng các tên thành viên.
II.3. Ép kiu các con tr lp c s ti các con tr lp dn xut
Mt đi tng ca mt lp dn xut k tha public cũng có th đc x lý nh mt đi tng ca lp
c s ca nó tng ng. Nhng ngc li không đúng: mt đi tng lp c s cũng không t đng là mt
đi tng lp dn xut.
Tuy nhiên, có th s dng ép kiu đ chuyn đi mt con tr lp c s thành mt con tr lp dn xut.
Ví d 5.1:
Chng trình sau s đc chia thành nhiu file (gm các file .H và .CPP) và to mt project
có tên là CT5_1.PRJ gm các file .cpp
File POINT.H:
1: //POINT.H
2: //Định nghĩa lp Point
3: #ifndef POINT_H
4: #define POINT_H
5:
6: class Point
7: {
8: protected:
9: float X,Y;
10: public:
11: Point(float A= 0, float B= 0);
12: void SetPoint(float A, float B);
13: float GetX() const
14: {
15: return X;
16: }
17: float GetY() const
18: {
19: return Y;
20: }
21: friend ostream & operator <<(ostream &Output, const Point &P);
22: };
23:
24: #endif
File POINT.CPP
1: //POINT.CPP
2: //Định nghĩa các hàm thành viên ca lp Point
3: #include <iostream.h>
4: #include "point.h"
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
110
5:
6: Point::Point(float A, float B)
7: {
8: SetPoint(A, B);
9: }
10:
11: void Point::SetPoint(float A, float B)
12: {
13: X = A;
14: Y = B;
15: }
16:
17: ostream & operator <<(ostream &Output, const Point &P)
18: {
19: Output << '[' << P.X << ", " << P.Y << ']';
20: return Output;
21: }
File CIRCLE.H
1: //CIRCLE.H
2: //Định nghĩa lp Circle
3: #ifndef CIRCLE_H
4: #define CIRCLE_H
5:
6: #include "point.h"
7: class Circle : public Point
8: {
9: protected:
10: float Radius;
11: public:
12: Circle(float R = 0.0, float A = 0, float B = 0);
13: void SetRadius(float R);
14: float GetRadius() const;
15: float Area() const;
16: friend ostream & operator <<(ostream &Output, const Circle &C);
17: };
18:
19: #endif
File CIRCLE.CPP
1: //CIRCLE.CPP
2: //Định nghĩa các hàm thành viên ca lp Circle
3: #include <iostream.h>
4: #include <iomanip.h>
5: #include "circle.h"
6:
7: Circle::Circle(float R, float A, float B): Point(A, B)
8: {
9: Radius = R;
10: }
11:
12: void Circle::SetRadius(float R)
13: {
14: Radius = R;
15: }
16:
17: float Circle::GetRadius() const
18: {
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
111
19: return Radius;
20: }
21:
22: float Circle::Area() const
23: {
24: return 3.14159 * Radius * Radius;
25: }
26:
27: //Xut mt Circle theo dng: Center = [x, y]; Radius = #.##
28: ostream & operator <<(ostream &Output, const Circle &C)
29: {
30: Output << "Center = [" << C.X << ", " << C.Y
31: << "]; Radius = " << setiosflags(ios::showpoint)
32: << setprecision(2) << C.Radius;
33: return Output;
34: }
File CT5_1.CPP:
1: //CT5_1.CPP
2: //Chương trình 5.1: Ép các con tr lp cơ s ti các con tr lp
dn xut
3: #include <iostream.h>
4: #include <iomanip.h>
5: #include "point.h"
6: #include "circle.h"
7:
8: int main()
9: {
10: Point *PointPtr, P(3.5, 5.3);
11: Circle *CirclePtr, C(2.7, 1.2, 8.9);
12: cout << "Point P: "<<P<<endl<<"Circle C: "<<C<< endl;
13 //X lý mt Circle như mt Point (ch xem mt phn lp cơ s)
14: PointPtr = &C;
15: cout << endl << "Circle C (via *PointPtr): "<<*PointPtr<<endl;
16 //X lý mt Circle như mt Circle
17: PointPtr = &C;
18: CirclePtr = (Circle *) PointPtr;
19: cout << endl << "Circle C (via *CirclePtr): " << endl
20: <<*CirclePtr<< endl << "Area of C (via CirclePtr): "
21: << CirclePtr->Area() << endl;
22: //Nguy him: Xem mt Point như mt Circle
23: PointPtr = &P;
24: CirclePtr = (Circle *) PointPtr;
25: cout << endl << "Point P (via *CirclePtr): "<< endl
26: <<*CirclePtr<< endl << "Area of object CirclePtr
points to: "
27: <<CirclePtr->Area() << endl;
28: return 0;
29: }
Chúng ta chy ví d 5.1
, kt qu hình 5.4
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
112
Hình 5.4: Kt qu ca ví d 5.1
Trong đnh nghƿa lp Point, các thành viên d liu X Y đc ch đnh là protected, điu này cho phép
các lp dn xut t lp Point truy cp trc tip các thành viên d liu k tha. Nu các thành viên d liu
này đc ch đnh là private, các hàm thành viên public ca Point phi đc s dng đ truy cp d liu,
ngay c bi các lp dn xu
t.
Lp Circle đc k tha t lp Point vi k tha public ( dòng 7 file CIRCLE.H), tt c các thành
viên ca lp Point đc k tha thành lp Circle. Điu này có nghƿa là giao din public bao gm các hàm
thành viên public ca Point cũng nh các hàm thành viên Area(), SetRadius()GetRadius().
Constructor lp Circle phi bao gm constructor lp Point đ khi đng phn lp c s
ca đi tng
lp Circle dòng 7 file CIRCLE.CPP, dòng này có th đc vit li nh sau:
Circle::Circle(float R, float A, float B)
: Point(A, B) //Gi constructor ca lp c s
Các giá tr A B đc chuyn t constructor lp Circle ti constructor lp Point đ khi đng các
thành viên X Y ca lp c s. Nu constructor lp Circle không bao gm constructor lp Point thì
constructor lp Point gi vi các giá tr m
c đnh cho X Y (nghƿa là 0 và 0). Nu lp Point không cung cp
mt constructor mc đnh thì trình biên dch phát sinh li.
Trong chng trình chính (file CT5_1.CPP) gán mt con tr lp dn xut (đa ch ca đi tng C) cho
con tr lp c s PointPtr và xut đi tng C ca Circle bng toán t chèn dòng ca lp Point ( dòng 14
và 15). Chú ý rng ch phn Point ca đi t
ng C ca Circle đc hin th. Nó luôn luôn đúng đ gán mt
con tr lp dn xut cho con tr lp c s bi vì mt đi tng lp dn xut là mt đi tng lp c s. Con
tr lp c s ch trông thy phn lp c s ca đi tng lp dn xut. Trình biên dch thc hin mt chuyn
đi ngm ca con tr lp dn xut cho mt con tr lp c s.
Sau đó chng trình gán mt con tr lp dn xut (đa ch ca đi tng C) cho con tr lp c s
PointPtr và ép PointPtr tr v kiu Circle *. Kt qu ca ép kiu đc gán cho CirclePtr. Đi tng C ca
Circle đc xut b
ng cách s dng toán t chèn dòng ca Circle. Din tích ca đi tng C đc xut
thông qua CirclePtr. Các kt qu này là giá tr din tích đúng bi vì các con tr luôn luôn đc tr ti mt
đi tng Circle (t dòng 17 đn 22).
K tip, chng trình gán mt con tr lp c s (đa ch ca đi tng P) cho con tr lp c s PointPtr
và ép PointPtr tr
v kiu Circle *. Kt qu ca ép kiu đc gán cho CirclePtr. Đi tng P đc xut s
dng toán t chèn dòng ca lp Circle. Chú ý rng giá tr xut ca thành viên Radius "k l". Vic xut mt
Point nh mt Circle đa đn mt giá tr không hp l cho Radius bi vì các con tr luôn đc tr đn mt
đi tng Point. M
t đi tng Point không có mt thành viên Radius. Vì th, chng trình xut giá tr "rác"
đi vi thành viên d liu Radius. Chú ý rng giá tr ca din tích là 0.0 bi vì tính toàn này da trên giá tr
không tn ti ca Radius (t dòng 23 đn 27).Rõ ràng, truy cp các thành viên d liu mà không phi đó
thì nguy him. Gi các hàm thành viên mà không tn ti có th phá hy chng trình.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
113
II.4. Đnh nghƿa li các thành viên lp c s trong mt lp dn xut
Mt lp dn xut có th đnh nghƿa li mt hàm thành viên lp c s. Điu này đc gi là overriding.
Khi hàm đó đc đ cp bi tên trong lp dn xut, phiên bn ca lp dn xut đc chn mt cách t đng.
Toán t đnh phm vi có th s dng đ truy cp phiên bn ca lp c s t lp d
n xut.
II.5. Các lp c s public, protected và private
Khi dn xut mt lp t mt lp c s, lp c s có th đc k tha là public, protectedprivate.
class <drived_class_name> : <type_of_inheritance> <base_class_name>
{………………..
};
Trong đó type_of_inheritancepublic, protected hoc private. Mc đnh là private.
Khi dn xut mt lp t mt lp c s public, các thành viên public ca lp c s tr thành các thành
viên public ca lp dn xut, và các thành viên protected ca lp c s tr thành các thành viên protected
ca lp dn xut. Các thành viên private ca lp c s không bao gi đc truy cp tr
c tip t mt lp dn
xut.
Khi dn xut mt lp t mt lp c s protected, các thành viên public protected ca lp c s tr
thành các thành viên protected ca lp dn xut. Khi dn xut mt lp t mt lp c s private, các thành
viên public protected ca lp c s tr thành các thành viên private ca l
p dn xut.
Bng sau (hình 5.6)tng kt kh nĕng truy cp các thành viên lp c s trong mt lp dn xut da trên
thuc tính xác đnh truy cp thành viên ca các thành viên trong lp c s và kiu k tha.
Kiu k tha
K tha public K tha protected K tha private
public
public trong lp dn xut.
Có th truy cp trc tip bi
các hàm thành viên không
tƿnh, các hàm friend và các
hàm không thành viên.
protected trong lp dn xut.
Có th truy cp trc tip bi
các hàm thành viên không
tƿnh, các hàm friend.
private trong lp dn
xut.
Có th
truy cp trc ti
p
bi các hàm thành viên
không tƿnh, các hàm
friend.
protected
protected trong lp dn
xut.
Có th truy cp trc tip bi
các hàm thành viên không
tƿnh, các hàm friend.
protected trong lp dn xut.
Có th truy cp trc tip bi
các hàm thành viên không
tƿnh, các hàm friend.
private trong lp dn
xut.
Có th
truy cp trc ti
p
bi các hàm thành viên
không tƿnh, các hàm
friend.
private
Du trong lp dn xut.
Có th truy cp trc tip bi
các hàm thành viên không
tƿnh, các hàm friend thông
qua các hàm thành viên
public protected ca lp
c s.
Du trong lp dn xut.
Có th truy cp trc tip bi
các hàm thành viên không
tƿnh, các hàm friend thông
qua các hàm thành viên
public protected ca lp
c s.
Du trong lp dn xut.
Có th
truy cp trc ti
p
bi các hàm thành viên
không tƿnh, các hàm
friend thông qua các
hàm thành viên public
protected ca lp c
s.
Hình 5.7: Tng kt kh nĕng truy cp thành viên lp c s trong lp dn xut.
II.6. Các contructor và destructor lp dn xut
Bi vì mt lp dn xut kt tha các thành viên lp c s ca nó (ngoi tr constructor và destructor),
khi mt đi tng ca lp dn xut đc khi đng, constructor lp c s phi đc gi đ khi đng các
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
114
thành viên lp c s ca đi tng lp dn xut. Mt b khi to lp c s (s dng cú pháp ging nh b
khi to thành viên) có th đc cung cp trong constructor lp dn xut đ gi tng minh constructor lp
c s, mt khác constructor lp dn xut s gi constructor mc đnh lp c s.
Các constructor lp c s
và các toán t gán lp c s không đc k tha bi lp dn xut.Tuy nhiên,
các constructor và các toán t gán lp dn xut có th gi các constructor và các toán t gán lp c s.
Mt constructor lp dn xut luôn gi constructor lp c s ca nó đu tiên đ khi to các thành viên
lp c s ca lp dn xut. Nu constructor lp dn b b qua, constructor mc đnh lp dn gi constructor
lp c s. Các destructor đc gi theo th t ngc li th t gi các constructor, vì th destructor lp dn
xut đc gi trc destructor lp c s ca nó.
Ví d 5.4:
Minh ha th t các contructor và destructor lp c s và lp dn xut đc gi và project có
tên là CT5_4.PRJ
File POINT.H
1: //POINT.H
2: //Định nghĩa lp Point
3: #ifndef POINT_H
4: #define POINT_H
5:
6: class Point
7: {
8: public:
9: Point(float A= 0.0, float B= 0.0);
10: ~Point();
11: protected:
12: float X, Y;
13: };
14:
15: #endif
File POINT.CPP
1: //POINT.CPP
2: //Định nghĩa các hàm thành viên lp Point
3: #include <iostream.h>
4: #include "point.h"
5:
6: Point::Point(float A, float B)
7: {
8: X = A;
9: Y = B;
10: cout << "Point constructor: "
11: << '[' << X << ", " << Y << ']' << endl;
12: }
13:
14: Point::~Point()
15: {
16: cout << "Point destructor: "
17: << '[' << X << ", " << Y << ']' << endl;
18: }
File CIRCLE.H
1: //CIRCLE.H
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
115
2: //Định nghĩa lp Circle
3: #ifndef CIRCLE_H
4: #define CIRCLE_H
5:
6: #include "point.h"
7: #include <iomanip.h>
8:
9: class Circle : public Point
10: {
11: public:
12: Circle(float R = 0.0, float A = 0, float B = 0);
13: ~Circle();
14: private:
15: float Radius;
16: };
17:
18: #endif
File CIRCLE.CPP
1: //CIRCLE.CPP
2: //Định nghĩa các hàm thành viên lp Circle
3: #include "circle.h"
4:
5: Circle::Circle(float R, float A, float B): Point(A, B)
6: {
7: Radius = R;
8: cout << "Circle constructor: Radius is "
9: << Radius << " [" << A << ", " << B << ']' << endl;
10: }
11:
12: Circle::~Circle()
13: {
14: cout << "Circle destructor: Radius is "
15: << Radius << " [" << X << ", " << Y << ']' << endl;
16: }
File CT5_4.CPP
1: //CT5_4.CPP
2: //Chương trình 5.4
3: #include <iostream.h>
4: #include "point.h"
5: #include "circle.h"
6: int main()
7: {
8: {
9: Point P(1.1, 2.2);
10: }
11: cout << endl;
12: Circle C1(4.5, 7.2, 2.9);
13: cout << endl;
14: Circle C2(10, 5, 5);
15: cout << endl;
16: return 0;
17: }
Chúng ta chy ví d 5.4
, kt qu hình 5.8
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
116
Hình 5.8: Kt qu ca ví d 5.4
II.7. Chuyn đi ngm đnh đi tng lp dn xut sang đi tng lp c s
Mc dù mt đi tng lp dn xut cũng là mt đi tng lp c s, kiu lp dn xut và kiu lp c s
thì khác nhau. Các đi tng lp dn xut có th đc x lý nh các đi tng lp c s. Điu này có ý
nghƿa bi vì lp dn xut có các thành viên tng ng vi mi thành viên ca lp c
s. Phép gán theo chiu
hng ngc li là không cho phép bi vì gán mt đi tng lp c s cho đi tng lp dn xut s cho
phép thêm các thành viên lp dn xut không xác đnh.
Mt con tr tr ti mt đi tng lp dn xut có th đc chuyn đi ngm đnh thành mt con tr tr
ti mt đi tng lp c s
bi vì mt đi tng lp dn xut là mt đi tng lp c s.
Có bn cách đ trn và đi sánh các con tr lp c s và các con tr lp dn xut vi các đi tng lp
c s và các đi tng lp dn xut:
Tham chiu ti mt đi tng lp c s vi mt con tr lp c
s thì không phc tp.
Tham chiu ti mt đi tng lp dn xut vi mt con tr lp dn xut thì không phc tp.
Tham chiu ti đi tng lp dn xut vi mt con tr lp c s thì an toàn bi vì đi tng lp
dn xut cũng là mt đi tng lp c s ca nó. Nh v
y đon mã ch có th tham chiu ti các thành
viên lp c s. Nu đon mã tham chiu ti các thành viên lp dn xut thông qua con tr lp c s,
trình biên dch s báo mt li v cú pháp.
Tham chiu ti mt đi tng lp c s vi mt con tr lp dn xut thì có li cú pháp. Đu tiên
con tr lp dn xut phi
đc ép sang con tr lp c s.
III. ĐA K THA (MULTIPLE INHERITANCE)
Mt lp có th đc dn xut t nhiu lp c s, s dn xut nh vy đc gi là đa k tha. Đa k tha
có nghƿa là mt lp dn xut k tha các thành viên ca các lp c s khác nhau. Kh nĕng mnh này
khuyn khích các dng quan trng ca vic s dng li phn mm, nhng có th
sinh ra các vn đ nhp
nhng.
Ví d 5.7:
Lp Circle và project có tên là CT5_8.PRJ (gm các file DIRIVED.CPP, CT5_8.CPP).
File BASE1.H
1: //BASE1.H
2: //Định nghĩa lp Base1
3: #ifndef BASE1_H
4: #define BASE1_H
5:
6: class Base1
7: {
8: protected:
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
117
9: int Value;
10: public:
11: Base1(int X)
12: {
13: Value = X;
14: }
15: int GetData() const
16: {
17: return Value;
18: }
19: };
20:
21: #endif
File BASE2.H
1: //BASE2.H
2: //Định nghĩa lp Base2
3: #ifndef BASE2_H
4: #define BASE2_H
5:
6: class Base2
7: {
8: protected:
9: char Letter;
10: public:
11: Base2(char C)
12: {
13: Letter = C;
14: }
15: char GetData() const
16: {
17: return Letter;
18: }
19: };
20:
21: #endif
File DERIVED.H
1: //DERIVED.H
2: //Định nghĩa lp Derived mà kế tha t nhiu lp cơ s (Base1 &
Base2)
3: #ifndef DERIVED_H
4: #define DERIVED_H
5:
6: #include "base1.h"
7: #include "base2.h"
8:
9: class Derived : public Base1, public Base2
10: {
11: private:
12: float Real;
13: public:
14: Derived(int, char, float);
15: float GetReal() const;
16: friend ostream & operator <<(ostream &Output, const Derived &D);
17: };
18:
19: #endif
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
118
File DERIVED.CPP
1: //DERIVED.H
2: //Định nghĩa lp Derived kế tha t nhiu lp cơ s (Base1 & Base2)
3: #ifndef DERIVED_H
4: #define DERIVED_H
5:
6: #include "base1.h"
7: #include "base2.h"
8:
9: class Derived : public Base1, public Base2
10: {
11: private:
12: float Real;
13: public:
14: Derived(int, char, float);
15: float GetReal() const;
16: friend ostream & operator <<(ostream &Output, const Derived &D);
17: };
18:
19: #endif
File CT5_8.CPP
1: //CT5_8.CPP
2: //Chương trình 5.8
3: #include <iostream.h>
4: #include "base1.h"
5: #include "base2.h"
6: #include "derived.h"
7:
8: int main()
9: {
10: Base1 B1(10), *Base1Ptr;
11: Base2 B2('Z'), *Base2Ptr;
12: Derived D(7, 'A', 3.5);
13: cout << "Object B1 contains integer "
14: << B1.GetData() << endl
15: << "Object B2 contains character "
16: << B2.GetData() << endl
17: << "Object D contains:" << endl << D << endl << endl;
18: cout << "Data members of Derived can be"
19: << " accessed individually:" << endl
20: << " Integer: " << D.Base1::GetData() << endl
21: << " Character: " << D.Base2::GetData() << endl
22: << "Real number: " << D.GetReal() << endl << endl;
23: cout << "Derived can be treated as an "
24: << "object of either base class:" << endl;
25: Base1Ptr = &D;
26: cout << "Base1Ptr->GetData() yields "
27: << Base1Ptr->GetData() << endl ;
28: Base2Ptr = &D;
29: cout << "Base2Ptr->GetData() yields "
30: << Base2Ptr->GetData() << endl;
31: return 0;
32: }
Chúng ta chy ví d 5.8
, kt qu hình 5.13
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
119
Hình 5.13: Kt qu ca ví d 5.8
Vic k tha nhiu lp c s to ra mt lot các đim nhp nhng trong các chng trình C++. Chng
hn, trong các chng trình ca ví d 5.8, nu thc hin lnh:
D.GetData();
thì trình biên dch (Borland C++ 3.1) s báo li:
Member is ambiguous: ‘Base1::GetData’ and ‘Base1::GetData’
Bi vì lp Derived k tha hai hàm khác nhau có cùng tên là GetData() t hai lp c s ca nó.
Base1::GetData() là hàm thành viên public ca lp c
s public, và nó tr thành mt hàm thành viên public
ca Derived. Base2::GetData() là hàm thành viên public ca lp c s public, và nó tr thành mt hàm
thành viên public ca Derived. Do đó trình biên dch không th xác đnh hàm thành viên GetData() ca lp
c s nào đ gi thc hin. Vì vy, chúng ta phi s dng tên lp c s và toán t đnh phm vi đ xác đnh
hàm thành viên ca lp c s lúc g
i hàm GetData().
Cú pháp ca mt lp k tha nhiu lp c s:
class <drived_class_name> : <type_of_inheritance> <base_class_name1> ,
<type_of_inheritance> <base_class_name2>, …
{
………………..
};
Trình t thc hin constructor trong đa k tha: constructor lp c s xut hin trc s thc hin trc
và cui cùng mi ti constructor lp dn xut. Đi vi destructor có trình t thc hin theo th t ngc li.
IV. CÁC LP C S O (VIRTUAL BASE CLASSES)
Chúng ta không th khai báo hai ln cùng mt lp trong danh sách ca các lp c s cho mt lp dn
xut. Tuy nhiên vn có th có trng hp cùng mt lp c s đc đ cp nhiu hn mt ln trong các lp t
tiên ca mt lp dn xut. Điu này phát sinh li vì không có cách nào đ phân bit hai lp c s gc.
Ví d 5.9:
1: //Chương trình 5.9
2: #include <iostream.h>
3: class A
4: {
5:
public:
6: int X1;
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
120
7: };
8:
9: class B : public A
10: {
11: public:
12: float X2;
13: };
14:
15:
class C : public A
16: {
17: public:
18: double X3;
19: };
20:
21: class D : public B,public C
22: {
23: public:
24: char X4;
25: };
26:
27: int main()
28: {
29: D Obj;
30: Obj.X2=3.14159F;
31: Obj.X1=0;
//Nhp nhng
32: Obj.X4='a';
33: Obj.X3=1.5;
34: cout<<"X1="<<Obj.X1<<endl;
//Nhp nhng
35: cout<<"X2="<<Obj.X2<<endl;
36: cout<<"X3="<<Obj.X3<<endl;
37: cout<<"X4="<<Obj.X4<<endl;
38: return 0;
39: }
Khi biên dch chng trình ví d 5.9, trình biên dch s báo li dòng 31 và 34:
Member is ambiguous: ‘A::X1’ and ‘A::X1’
Hình 5.14
đây chúng ta thy có hai lp c s A cho lp D, và trình biên dch không th nào nhn bit đc vic
truy cp X1 đc k tha thông qua B hoc truy cp X1 đc k tha thông qua C. Đ khc phc điu này,
chúng ta ch đnh mt cách tng minh trong lp D nh sau:
Obj.C::X1=0;
Tuy nhiên, đây cũng ch là gii pháp có tính chp vá, bi thc cht X1 nào trong trng hp nào cũng
đc. Gii pháp cho vn đ này là khai báo A nh lp c s kiu virtual cho c B C. Khi đó chng trình
ví d 5.9 đc vit li nh sau:
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
121
Ví d 5.10:
#include <iostream.h>
class A
{
public:
int X1;
};
class B : virtual public A
{
public:
float X2;
};
class C : virtual public A
{
public:
double X3;
};
class D : public B,public C
{
public:
char X4;
};
int main()
{
D Obj;
Obj.X2=3.14159F;
Obj.X1=0; //OK
Obj.X4='a';
Obj.X3=1.5;
cout<<"X1="<<Obj.X1<<endl; //OK
cout<<"X2="<<Obj.X2<<endl;
cout<<"X3="<<Obj.X3<<endl;
cout<<"X4="<<Obj.X4<<endl;
return 0;
}
Chúng ta chy ví d 5.10, kt qu hình 5.15
Hình 5.15: Kt qu ca ví d 5.10
Các lp c s kiu virtual, có cùng mt kiu lp, s đc kt hp đ to mt lp c s duy nht
có kiu đó cho bt k lp dn xut nào k tha chúng. Hai lp c s A trên bt gi s tr thành mt lp c
s A duy nht cho bt k lp dn xut nào t B và C. Điu này có nghƿa là D ch có mt c s ca lp A, vì
vy tránh đc s nhp nhng.
BÀI TP
Bài 1: Xây dng lp Stack vi các thao tác cn thit. T đó hãy dn xut t lp Stack đ đi
mt s nguyên dng sang h đm bt k.
Bài 2: Hãy xây dng các lp cn thit trong phân cp hình 5.2
Bài 3: Hãy xây dng các lp cn thit trong phân cp hình 5.3 đ tính din tích (hoc din
tích xung quanh) và th tích.
Bài 4: Vit mt phân cp k tha cho các lp Quadrilateral (hình t giác), Trapezoid (hình
thang), Parallelogram (hình bình hành), Rectangle (hình ch nht), và Square (hình vuông). Trong
đó Quadrilateral là lp c s ca phân cp.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
122
CHƯƠNG 6
TÍNH ĐA HÌNH
I. DN NHP
Tính đa hình (polymorphism) là kh nĕng thit k và cài đt các h thng mà có th m rng d dàng
hn. Các chng trình có th đc vit đ x lý tng quát – nh các đi tng lp c s – các đi tng ca
tt c các lp tn ti trong mt phân cp. Kh nĕng cho phép mt chng trình sau khi đã biên dch có th
nhiu din bin xy ra là mt trong nh
ng th hin ca tính đa hình – tính muôn màu muôn v – ca chng
trình hng đi tng, mt thông đip đc gi đi (gi đn đi tng) mà không cn bit đi tng nhn
thuc lp nào. Đ thc hin đc tính đa hình, các nhà thit k C++ cho chúng ta dùng c ch kt ni đng
(dynamic binding) thay cho c ch kt ni tƿnh (static binding) ngay khi chng trình biên dch đc dùng
trong các ngôn ng c
đin nh C, Pascal, …
II. PHNG THC O (VIRTUAL FUNCTION)
Khi xây dng các lp ca mt chng trình hng đi tng đ to nên mt cu trúc phân cp hoc cây
ph h, ngi lp trình phi chun b các hành vi giao tip chung ca các lp đó. Hành vi giao tip chung s
đc dùng đ th hin cùng mt hành vi, nhng có các hành đng khác nhau, đó chính là phng thc o.
Đây là mt phng thc tn ti đ có hiu lc nhng không có thc trong l
p c s, còn trong các lp dn
xut. Nh vy phng thc o ch đc xây dng khi có mt h thng cây ph h. Phng thc này s đc
gi thc hin t thc th ca lp dn xut nhng mô t v chúng trong lp c s.
Chúng ta khai báo phng thc o bng thêm t khóa virtual phía trc. Khi đó các phng th
c có
cùng tên vi phng thc này trong các lp dn xut cũng là phng thc o.
Ví d 6.1:
1: //Chương trình 6.1
2: #include <iostream.h>
3:
4: class Base
5: {
6: public:
7: virtual void Display()
8: {
9: cout<<"class Base"<<endl;
10: }
11: };
12:
13: class Derived : public Base
14: {
15: public:
16: virtual void Display()
17: {
18: cout<<"class Derived"<<endl;
19: }
20: };
21:
21: void Show(Base *B)
22: {
23: B->Display(); //Con tr B ch đến phương thc Display() nào
(ca lp Base
24 //hoc lp Derived) tùy vào lúc chy chương trình.
25: }
26: int main()
27: {
28: Base *B=new Base;
29: Derived *D=new Derived;
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
123
30: B->Display(); //Base::Display()
31: D->Display(); //Derived::Display()
32: Show(B); //Base::Display()
33: Show(D); //Derived::Display()
34: return 0;
35: }
Chúng ta chy ví d 6.1
, kt qu hình 6.1
Hình 6.1: Kt qu ca ví d 6.1
Trong ví d 6.1, lp c s Base có phng thc Display() đc khai báo là phng thc o. Phng
thc này trong lp dn xut Derived đc đnh nghƿa li nhng cũng là mt phng thc o. Tht ra, không
ra không có khai báo virtual cho phng thc Display() ca lp Derived cũng chng sao, trình biên dch vn
hiu đó là phng thc
o. Tuy nhiên, khai báo virtual rõ ràng các lp dn xut làm cho chng trình
trong sáng, d hiu hn. Hai dòng 30 và 31, chúng ta bit chc phng thc Display() ca lp nào đc gi
(ca lp Base hoc lp Derived). Nhng hai dòng 32 và 33, nu không có c ch kt ni đng, chúng ta đoán
rng vic gi hàm Show() s luôn luôn kéo theo phng thc Base::Display(). Qu vy, b đi khai báo
virtual cho phng thc Base::Display(), khi
đó dòng lnh: Show(D);
gi đn Base::Display() đi tng lp dn xut cũng là đi tng lp c s (nghƿa là tdb t đng
chuyn đi kiu: đi tng D kiu Derived chuyn thành kiu Base.
Nh khai báo virtual cho phng thc Base::Display() nên s không thc hin gi phng thc
Base::Display() mt cách cng nhc trong hàm Show() mà chun b m
t c ch mm do cho vic gi
phng thc Display() tùy thuc vào s xác đnh kiu ca tham s vào lúc chy chng trình.
C ch đó ra sao? Khi nhn thy có khai báo virtual trong lp c s, trình biên dch s thêm vào mi
đi tng ca lp c s và các lp dn xut ca nó mt con tr ch đn bng phng thc o (virtual
function table). Con tr đ
ó có tên là vptr (virtual pointer). Bng phng thc o là ni cha các con tr ch
đn đon chng trình đã biên dch ng vi các phng thc o. Mi lp có mt bng phng thc o. Trình
biên dch ch lp bng phng thc o khi bt đu có vic to đi tng ca lp. Đn khi chng trình chy,
phng thc o ca đi t
ng mi đc ni kt và thi hành thông qua con tr vptr.
Trong ví d 6.1, lnh gi hàm: Show(D);
Đi tng D thuc lp Derived tuy b chuyn đi kiu thành mt đi tng thuc lp Base nhng nó
không hoàn toàn ging mt đi tng ca Base chính cng nh B. Nu nh con tr vptr trong B ch đn v trí
trên bng phng thc o ng vi phng thc Base::Display(), thì con tr vptr trong D vn còn ch đn
phng thc Derived::Display() cho dù D b chuyn kiu thành Base. Đó là lý do ti sao lnh: Show(D);
gi đn phng thc Derived::Display().
Các đặc trưng ca phương thc o:
Phng thc o không th là các hàm thành viên tƿnh.
Mt phng thc o có th đc khai báo là friend trong mt lp khác nhng các hàm friend ca lp
thì không th là phng thc o.
Không cn thit phi ghi rõ t khóa virtual khi đnh nghƿa mt phng thc o trong lp dn xut (đ
cũng chng nh hng gì).
Đ s kt ni đng đc thc hin thích hp cho tng lp dc theo cây ph h, mt khi phng thc
nào đó đã đc xác đnh là o, t lp c s đn các lp dn xut đu phi đnh nghƿa thng nht v tên, kiu
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
124
tr v và danh sách các tham s. Nu đi vi phng thc o lp dn xut, chúng ta li s sut đnh nghƿa
các tham s khác đi mt chút thì trình biên dch s xem đó là phng thc khác. Đây chính là điu kin đ
kt ni đng.
Ví d 6.2:
2: #include <iostream.h>
3:
4: class Base
5: {
6: public:
7: virtual void Print(int A,int B);
8: };
9:
10: class Derived : public Base
11: {
12: public:
13: virtual void Print(int A,double D);
14: };
15:
16: void Base::Print(int A,int B)
17: {
18: cout<<"A="<<A<<",B="<<B<<endl;
19: }
20:
21: void Derived::Print(int A,double D)
22: {
23: cout<<"A="<<A<<",D="<<D<<endl;
24: }
25:
26: void Show(Base *B)
27: {
28: B->Print(3,5);
29: }
30:
31: int main()
32: {
33: Base *B=new Base;
34: Derived *D=new Derived;
35: Show(B); //Base::Print()
36: Show(D); //Base::Print()
37: return 0;
38: }
Chúng ta chy ví d 6.2
, kt qu hình 6.2
Hình 6.2: Kt qu ca ví d 6.2
Trong ví d 6.2, trong lp c s Base và lp dn xut Derived đu có phng thc o Print(). Nhng
quan sát k chúng ta, phng thc Print() trong lp Derived có tham s th hai khác kiu vi phng thc
Print() trong lp Base. Vì th, chúng ta không th ch đi lnh dòng 36 s gi đn phng thc
Derived::Print(int,double). Phng thc Derived::Print(int,double) n
m ngoài đng dây phng thc o
nên hàm Show() ch luôn gi đn phng thc Derived::Print(int,int) mà thôi. Do có khai báo virtual đi vi
phng thc Derived::Print(int,double), chúng ta có th nói phng thc này s m đu cho mt đng dây
phng thc o Print(int,double) mi nu sau lp Derived còn có các lp dn xut ca nó.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
125
III. LP TRU TNG (ABSTRACT CLASS)
Trong quá trình thit k chng trình theo hng đi tng, đ to nên mt h thng ph h mang tính
k tha cao, ngi lp trình phi đoán trc s phát trin ca cu trúc, t đó chn la nhng thành viên phù
hp cho các lp trên cùng. Rõ ràng đây là mt công vic vô cùng khó khĕn. Đ tránh tình trng ngi lp
trình xây dng các đi tng lãng phí b nh, ngôn ng C++ cho phép chúng ta thit k các l
p có các
không phng thc o không làm gì c, và cũng không th to ra đi tng thuc lp đó. Nhng lp nh vy
gi là lp tru tng.
Trong cu trúc trên hình 6.3, không phi lp nào cũng thc s cn đn phng thc Print(), nhng nó
mt khp ni đ to ra b mt chung cho mi lp trong cu trúc cây. Phng thc ca lp trên cùng nh
A::Print() th
ng là phng thc o đđc tính đa hình.
Hình 6.3
Nh đó, vi hàm sau:
void Show(A* a)
{
a->Print();
}
chúng ta có th truyn đi tng đ kiu cho nó (A, B, C, D hoc E) mà vn gi đn đúng phung thc
Print() phù hp dù kiu ca đi tng lúc biên dch vn còn cha bit. Vi vai trò "lót đng" nh vy,
phng thc A::Print() có th chng có ni dung gì c
class A
{
public:
virtual void Print()
{
}
};
Khi đó ngi ta gi phng thc A::Print() là phng thc o rng (null virtual function), nó chng làm
gì ht. Tuy nhiên lp A vn là mt lp bình thng, chúng ta có th to ra mt đi tng thuc nó, có th
truy cp ti phng thc A::Print(). Đ tránh trình trng vô tình to ra đi tng thuc lp này, ngi ta
thng xây dng lp tru tng, trình biên dch cho phép to ra lp có các phng thc thu
n o (pure
virtual function) nh sau:
class A
{
public:
virtual void Print() = 0;
};
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
126
Phng thc o Print() bây gi là phng thc thun o – phng thc có tên đc gán bi giá tr zero.
Lp A cha phng thc thun o đc gi là lp tru tng.
Ví d 6.3:
1: //Chương trình 6.3
2: #include <iostream.h>
3:
4: class A
5: {
6: public:
7: virtual void Print()=0; //Phương thc thun o
8: };
9:
10: class B : public A
11: {
12: public:
13: virtual void Print()
14: {
15: cout<<"Class B"<<endl;
16: }
17: };
18:
19: class C : public B
20: {
21: public:
22: virtual void Print()
23: {
24: cout<<"Class C"<<endl;
25: }
26: };
27:
28: void Show(A *a)
29: {
30: a->Print();
31: }
32:
33: int main()
34: {
35: B *b=new B;
36: C *c=new C;
37: Show(b); //B::Print()
38: Show(c); //C::Print()
39: return 0;
40: }
Chúng ta chy ví d 6.3
, kt qu hình 6.4
Hình 6.4: Kt qu ca ví d 6.3
Lp A đc to ra đ làm c s cho vic hình thành các lp con cháu (B C). Nh có Phng thc o
Print() t lp A cho ti lp C, tính đa hình đc th hin.
Lu ý:
Chúng ta không th to ra mt đi tng ca lp tru tng, nhng hoàn toàn có th to ra mt con
tr tr đn lp này (vì con tr không phi là đi tng thuc lp) hoc là mt tham chiu.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
127
Nu trong lp k tha t lp tru tng chúng ta không đnh nghƿa phng thc thun o, do tính k
tha nó s bao hàm phng thc thun o ca lp c s, nên lp dn xut này s tr thành lp tru tng.
Theo đnh nghƿa lp tru tng, nu trong lp dn xut (t lp c s tru tng) chúng ta đnh nghƿa
thêm mt phng thc thun o khác, lp này cũng s tr thành lp tru tng.
IV. CÁC THÀNH VIÊN O CA MT LP
IV.1. Toán t o
Toán t thc cht cũng là mt hàm nên chúng ta có th to ra các toán t o trong mt lp. Tuy nhiên do
đa nĕng hóa khi to mt toán t cn chú ý đn các kiu ca các toán hng phi s dng kiu ca lp c s
gc có toán t o.
Ví d 6.4:
Đa nĕng hóa toán t vi hàm toán t là phng thc o.
1: //Chương trình 6.4: Toán t o
2: #include <iostream.h>
3:
4: class A
5: {
6: protected:
7: int X1;
8: public:
9: A(int I)
10: {
11: X1=I;
12: }
13: virtual A& operator + (A& T);
14: virtual A& operator = (A& T);
15: virtual int GetA()
16: {
17: return X1;
18: }
19: virtual int GetB()
20: {
21: return 0;
22: }
23: virtual int GetC()
24: {
25: return 0;
26: }
27: void Print(char *St)
28: {
29: cout<<St<<":X1="<<X1<<endl;
30: }
31: };
32:
33: class B : public A
34: {
35: protected:
36: int X2;
37: public:
38: B(int I,int J):A(I)
39: {
40: X2=J;
41: }
42: virtual A& operator + (A& T);
43: virtual A& operator = (A& T);
44: virtual int GetB()
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
128
45: {
46: return X2;
47: }
48: void Print(char *St)
49: {
50: cout<<St<<":X1="<<X1<<",X2="<<X2<<endl;
51: }
52: };
53:
54: class C : public B
55: {
56: protected:
57: int X3;
58: public:
59: C(int I,int J,int K):B(I,J)
60: {
61: X3=K;
62: }
63: virtual A& operator + (A& T);
64: virtual A& operator = (A& T);
65: virtual int GetC()
66: {
67: return X3;
68: }
69: void Print(char *St)
70: {
71: cout<<St<<":X1="<<X1<<",X2="<<X2<<",X3="<<X3<<endl;
72: }
73: };
74:
75: A& A::operator + (A& T)
76: {
77: X1+=T.GetA();
78: return *this;
79: }
80:
81: A& A::operator = (A& T)
82: {
83: X1=T.GetA();
84: return *this;
85: }
86:
87: A& B::operator + (A& T)
88: {
89: X1+=T.GetA();
90: X2+=T.GetB();
91: return *this;
92: }
93:
94: A& B::operator = (A& T)
95: {
96: X1=T.GetA();
97: X2=T.GetB();
98: return *this;
99: }
100:
101:A& C::operator + (A& T)
102: {
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
129
103: X1+=T.GetA();
104: X2+=T.GetB();
105: X3+=T.GetC();
106: return *this;
107 }
108:
109: A& C::operator = (A& T)
110: {
111: X1=T.GetA();
112: X2=T.GetB();
113: X3=T.GetC();
114: return *this;
115: }
116:
117: void AddObject(A& T1,A& T2)
118: {
119: T1=T1+T2;
120: }
121:
122: int main()
123: {
124: A a(10);
125: B b(10,20);
126: C c(10,20,30);
127: a.Print("a");
128: b.Print("b");
129: c.Print("c");
130: AddObject(a,b);
131: a.Print("a");
132: AddObject(b,c);
133: b.Print("b");
134: AddObject(c,a);
135: c.Print("c");
136: a=b+c;
137: a.Print("a");
138: c=c+a;
139: c.Print("c");
140: return 0;
141: }
Chúng ta chy ví d 6.4
, kt qu hình 6.5
Hình 6.5: Kt qu ca ví d 6.4
IV.2. Có constructor và destructor o hay không?
Khi mt đi tng thuc lp có phng thc o, đ thc hin c ch kt ni đng, trình biên dch s to
thêm mt con tr vptr nh mt thành viên ca lp, con tr này có nhim v qun lý đa ch ca phng thc
o. Mt lp ch có mt bng phng thc o, trong khi đó có th có nhiu đi tng thuc l
p, nên khi mt
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
130
đi tng khác thuc cùng lp to ra thì con tr vptr đã còn ti. Chính vì vy bng phng thc o phi đc
to ra trc khi gi thc hin constructor, nên constructor không th là phng thc o. Ngc li do mt
lp ch có mt bng phng thc o nên khi mt đi tng thuc lp b hy b, bng phng thc o vn
còn đó, và con tr vptr v
n còn đó. Hn na, destructor đc gi thc hin trc khi vùng nh dành cho đi
tng b thu hi, do đó destructor có th là phng thc o. Tuy nhiên, constructor ca mt lp có th gi
phng thc o khác. Điu này hoàn toàn không có gì mâu thun vi c ch kt ni đng.
Ví d 6.5:
1: //Chương trình 6.5: Destructor o
2: #include <iostream.h>
3:
4: class Base
5: {
6: public:
7: virtual ~Base()
8: {
9: cout<<"~Base"<<endl;
10: }
11: };
12:
13: class Derived:public Base
14: {
15: public:
16: virtual ~Derived()
17: {
18: cout<<"~Derived"<<endl;
18: }
19: };
20:
21: int main()
22: {
23: Base *B;
24: B = new Derived;
25: delete B;
26: return 0;
27: }
Chúng ta chy ví d 6.5
, kt qu hình 6.6
Hình 6.6: Kt qu ca ví d 6.5
Nu destructor không là phng thc o thì khi gii phóng đi tng B ch có destructor ca lp c s
đc gi mà thôi nhng khi destructor là phng thc o thì khi gii phóng đi tng B ( dòng 25)
destructor ca lp dn xut đc gi thc hin ri đn destructor ca lp c s.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
131
BÀI TP
Bài 1
: Hãy xây dng các lp cn thit trong phân cp hình 5.3 đ tính din tích (hoc din tích xung
quanh) và th tích trong đó lp Shape là lp c s tru tng.
Bài 2
: Hãy sa đi h thng lng ca chng trình ví d 6.6 bng thêm các thành viên d liu
BrithData (mt đi tng kiu Date) và DepartmentCode (kiu int) vào lp Employee. Gi s lng này
đc x lý mt ln trên mt tháng. Sau đó, chng trình tính bng lng cho mi Employee (tính đa hình),
cng thêm 100.00
$
tin thng vào tng s lng ca mi ngi nu đây là tháng mà ngày sinh ca
Employee xy ra.
Bài 3
: Cài đt các lp trong cây ph h lp sau:
Trong đó các lp Person, Student và Staff là các lp tru tng, các lp còn li là các lp dn xut thc.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
132
CHƯƠNG 7
THIT K CHNG TRÌNH THEO HNG ĐI TNG
I. DN NHP
Trong chng này, chúng ta tìm hiu mt ít v cách thit k chng trình theo hng đi tng, các
bc c bn cn thit khi bt tay vào vit chng trình trên quan đim thit k và tho chng.
II. CÁC GIAI ĐON PHÁT TRIN H THNG
Có nĕm giai đon đ phát trin h thng phn mm theo hng đi tng:
Phân tích yêu cu (Requirement analysis)
Phân tích (Analysis)
Thit k (Design)
Lp trình (Programming)
Kim tra (Testing)
Phân tích yêu cu
Bng vic tìm hiu các trng hp s dng (use case) đ nm bt các yêu cu ca khách hàng,
ca vn đ cn gii quyt. Qua trng hp s dng này, các nhân t bên ngoài có tham gia vào h
thng cũng đc mô hình hóa bng các tác nhân. Mi trng hp s dng đc mô t bng vĕn bn,
đc t yêu cu ca khách hàng.
Phân tích
T các đc t yêu cu trên, h thng s bc đu đc mô hình hóa bi các khái nim lp, đi
tng và các c ch đ din t hot đng ca h thng.
Trong giai đon phân tích chúng ta ch mô t các lp trong lƿnh vc ca vn đ cn gii quyt
ch chúng ta không đi sâu vào các chi tit k thut.
Thit k
Trong giai đon thit k, các kt qu ca quá trình phân tích đc m rng thành mt gii pháp
k thut. Mt s các lp đc thêm vào đ cung cp c s h tng k thut nh lp giao din, lp c
s d liu, lp chc nĕng, …
Lp trình
Đây còn gi là bc xây dng, giai đon này s đc t chi tit kt qu ca giai đon thit k. Các
lp ca bc thit k s đc chuyn thành mã ngun theo mt ngôn ng lp trình theo hng đi
tng nào đó.
Kim tra
Trong giai đon kim tra, có bn hình thc kim tra h thng:
Kim tra tng đn th (unit testing) đc dùng kim tra các lp hoc các nhóm đn.
Kim tra tính tích hp (integration testing), đc kt hp vi các thành phn và các lp đ
kim tra xem chúng hot đng vi nhau có đúng không.
Kim tra h thng (system testing) ch đ kim tra xem h thng có đáp ng đc chc nĕng
mà ngi dùng yêu cu không.
Kim tra tính chp nhn đc(acceptance testing), vic kim tra này đc thc hin bi khách
hàng, vic kim tra cũng thc hin ging nh kim tra h thng.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
133
III. CÁCH TÌM LP
Lp nên đc tìm t phm vi bài toán cn gii quyt, vì vy tên ca lp cũng nên đt tên các đi tng
thc mà chúng ta biu din. Đ tìm ra lp cho bài toán, chúng ta cn tr li các câu hi sau:
Có thông tin nào cn lu tr hay phân tích không? Nu có bt k thông tin nào cn phi lu tr,
bin đi, phân tích hoc x lý thì đó chính là mt lp d đnh cn xây dng.
h thng bên ngoài bên ngoài hay không? H thng ngoài có th đc xem nh các lp mà
h thng ca chúng ta cha hoc tng tác vi nó.
Có các mu thit k, th vin lp, thành phn, … hay không? Các thành phn này đã đc xây
dng t các project trc đó, t các đng nghip hoc các nhà sn xut?
thit b nào mà h thng phi đáp ng? Bt c thit b nào đc ni vi h thng có th
chuyn thành lp d tuyn.
Tác nhân đóng vai trò nh th nào trong h thng? Các vai din này nên đc xem là lp nh
ngi s dng, khách hang, ngi điu khin h thng,…
IV. CÁC BC CN THIT Đ THIT K CHNG TRÌNH
Đ thit k mt chng trình theo hng đi tng, chúng ta phi tri qua bn bc sau, t đó chúng ta
xây dng đc mt cây ph h mang tính k tha và các mi quan h gia các đi tng:
Xác đnh các dng đi tng (lp) ca bài toán (đnh dang các đi tng).
Tìm kim các đc tính chung (d liu chung) trong các dng đi tng này, nhng gì chúng cùng
nhau chia x.
Xác đnh đc lp c s da trên c s các đc tính chung ca các dng đi tng.
T lp c s, s dng quan h tng quát hóa đ đc t trong vic đa ra các lp dn xut cha các
thành phn, nhng đc tính không chung còn li ca dng đi tng. Bên cnh đó, chúng ta còn đa ra
các lp có quan h vi các lp c s và lp dn xut; các quan h này có th là quan h kt hp, quan h
tp hp li, quan h ph thu
c.
Vi các bc trên chúng ta có đc cây ph h và quan h gia các lp. Đi vi h thng phc tp hn,
chúng ta cn phi phân tích đ gii quyt đc vn đ đt ra theo trt t sau:
Phân tích mt cách cn thn v các đi tng ca bài toán theo trt t t di lên (bottom up).
Tìm ra nhng gì tn ti chung gia các đi tng, nhóm các đc tính này li đ đc các lp c
s nh hình 7.1
Hình 7.1
Tip tc theo hng t di lên, chúng ta thit k đc các đi tng phù hp nh hình 7.2
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
134
Hình 7.2
Bng cách này, chúng ta tip tc tìm các đc tính chung cho đn tt cùng ca các đi tng.
Sau đó cài đt theo hng đi tng t trên xung bng cách cài đt lp c s chung nht.
Tip tc cài đt các lp dn xut trên c s các đc tính chung ca tng nhóm đi tng.
Cho đn khi tt c các dng đi tng ca h thng đc cài đt xong đ đc cây ph h.
V. CÁC VÍ D
Ví d 7.1: Tính tin lng ca các nhân viên trong c quan theo các dng khác nhau. Dng ngi lao
đng lãnh lng t ngân sách Nhà nc đc gi là cán b, công chc (dng biên ch). Dng ngi lao đng
lãnh lng t ngân sách ca c quan đc gi là ngi làm hp đng. Nh vy h thng chúng ta có hai đi
tng: biên ch và hp đng.
Hai loi đi tng này có đc tính chung đó là viên chc làm vic cho c quan. T đây có th to
nên lp c s đ qun lý mt viên chc (lp Nguoi) bao gm mã s, h tên và lng.
Sau đó chúng ta xây dng các lp còn li k tha t lp c s trên:
Lp dành cho cán b, công chc (lp BienChe) gm các thuc tính: h s lng, tin ph cp
chc v.
Lp dành cho ngi làm hp đng (lp HopDong) gm các thuc tính: tin công lao đng, s
ngày làm vic trong tháng, h s vt gi.
Hình 7.3
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
135
File PERSON.H
1: //PERSON.H
2: Định nghĩa lp Nguoi
3: #ifndef PERSON_H
4: #define PERSON_H
5:
6: #include <iostream.h>
7:
8: #define MAX_TEN 50
9: #define MAX_MASO 5
10: #define MUC_CO_BAN 120000
11:
12: class Nguoi
13: {
14: protected:
15: char HoTen[MAX_TEN];
16: char MaSo[MAX_MASO];
17: float Luong;
18: public:
19: Nguoi();
20: virtual void TinhLuong()=0;
21: void Xuat() const;
22: virtual void Nhap();
23: };
24:
25: #endif
File PERSON.CPP
1: //PERSON.CPP
2: Định nghĩa hàm thành viên cho lp Nguoi
3: #include <iomanip.h>
4: #include <string.h>
5: #include "person.h"
6:
7: Nguoi::Nguoi()
8: {
9: strcpy(HoTen,"");
10: strcpy(MaSo,"");
11: Luong=0;
12: }
13:
14: void Nguoi::Xuat() const
15: {
16: cout<<"Ma so:"<<MaSo<<",Ho va ten:"<<HoTen
17: #9;
<<",Luong:"<<setiosflags(ios::fixed)<<setprecision(0)<<Luong<<endl;
18: }
19:
20: void Nguoi::Nhap()
21: {
22: cout<<"Ma so:";
23: cin>>MaSo;
24: cin.ignore();
25: cout<<"Ho va ten:";
26: cin.getline(HoTen,MAX_TEN);
27: }
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
136
File STAFF.H
1: //STAFF.H
2 Định nghĩa lp BienChe
3: #ifndef STAFF_H
4: #define STAFF_H
5:
5: #include "person.h"
6:
7: class BienChe: public Nguoi
8: {
9: protected:
10: float HeSoLuong;
11: float HeSoPhuCap;
12: public:
13: BienChe();
14: virtual void TinhLuong();
15: virtual void Nhap();
16: };
17:
18: #endif
File STAFF.CPP
1: //STAFF.CPP
2: Định nghĩa hàm thành viên cho lp BienChe
3: #include "staff.h"
4:
5: BienChe::BienChe()
6: {
7: HeSoLuong=HeSoPhuCap=0;
8: }
9:
10: void BienChe::Nhap()
11: {
12: Nguoi::Nhap();
13: cout<<"He so luong:";
14: cin>>HeSoLuong;
15: cout<<"He so phu cap chu vu:";
16: cin>>HeSoPhuCap;
17: }
18:
19: void BienChe::TinhLuong()
20: {
21: Luong=MUC_CO_BAN*(1.0+HeSoLuong+HeSoPhuCap);
22: }
File CONTRACT.H
1: //CONTRACT.H
2: Định nghĩa lp HopDong
3: #ifndef CONTRACT_H
4: #define CONTRACT_H
5:
6: #include "person.h"
7:
8: class HopDong : public Nguoi
9: {
10: protected:
11: float TienCong;
12: float NgayCong;
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
137
13: float HeSoVuotGio;
14: public:
15: HopDong();
16: virtual void TinhLuong();
17: virtual void Nhap();
18: };
19:
20: #endif
File CONTRACT.CPP:
1: //CONTRACT.CPP
2: Định nghĩa hàm thành viên cho lp HopDong
3: #include "contract.h"
4:
5: HopDong::HopDong()
6: {
7: TienCong=NgayCong=HeSoVuotGio=0;
8: }
9:
10: void HopDong::Nhap()
11: {
12: Nguoi::Nhap();
13: cout<<"Tien cong:";
14: cin>>TienCong;
15: cout<<"Ngay cong:";
16: cin>>NgayCong;
17: cout<<"He so vuot gio:";
18: cin>>HeSoVuotGio;
19: }
20:
21: void HopDong::TinhLuong()
22: {
23: Luong=TienCong*NgayCong*(1+HeSoVuotGio);
24: }
File CT7_1.CPP:
1: //CT7_1.CPP
2: //Chương trình 7.1
3: #include <iostream.h>
4: #include <ctype.h>
5: #include "person.h"
6: #include "staff.h"
7: #include "contract.h"
8:
9: int main()
10: {
11: Nguoi *Ng[100];
12: int N=0;
13: char Chon,Loai;
14: do
15: {
16: cout<<"Bien che hay Hop dong (B/H)? ";
17: cin>>Loai;
18: Loai=toupper(Loai);
19: if (Loai=='B')
20: Ng[N]=new BienChe;
21: else
22: Ng[N]=new HopDong;
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
138
23: Ng[N++]->Nhap();
24: cout<<"Tiep tuc (C/K)? ";
25: cin>>Chon;
26: Chon=toupper(Chon);
27: if ((N==100)||(Chon=='K'))
28: break;
29: }
30: while (1);
31: for(int I=0;I<N;++I)
32: {
33: Ng[I]->TinhLuong();
34: Ng[I]->Xuat();
35: }
36: return 0;
37: }
Chúng ta chy ví d 7.1
, kt qu hình 7.4
Hình 7.4: Kt qu ca ví d 7.1
Ví d 7.2: Gi s cui nĕm hc cn trao gii thng cho các sinh viên xut sc và các ging viên có
nhiu công trình khoa hc đc công b trên tp chí. Các lp trong cây ph h nh hình 7.5: lp Nguoi đ
qun lý h s cá nhân, lp SinhVien qun lý v sinh viên và lp GiangVien qun lý ging viên.
Lp Nguoi:
D liu h và tên.
Phng thc kim tra kh nĕng đc khen thng. Đây là phng thc thun o.
Phng thc xut. Đây là phng thc thun o.
Lp SinhVien:
D liu đim trung bình.
Phng thc kim tra kh nĕng đc khen thng.
Phng thc xut.
Lp GiangVien:
D liu đim trung bình.
Phng thc kim tra kh nĕng đc khen thng.
Phng thc xut.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
139
Hình 7.5
File PERSON.H
1: //PERSON.H
2: Định nghĩa lp Nguoi
3: #ifndef PERSON_H
4: #define PERSON_H
5:
6: #include <iostream.h>
7:
8: #define MAX_TEN 50
9:
10: class Nguoi
11: {
12: protected:
13: char HoTen[MAX_TEN];
14: public:
15: Nguoi(char *HT);
16: virtual int DuocKhenThuong() const=0;
17: virtual void Xuat() const=0;
18: };
19:
20: #endif
File PERSON.CPP:
1: //PERSON.CPP
2: Định nghĩa hàm thành viên cho lp Nguoi
3: #include <string.h>
4: #include "person.h"
5:
6: Nguoi::Nguoi(char *HT)
7: {
8: strcpy(HoTen,HT);
9: }
File STUDENT.H:
1: //STUDENT.H
2: Định nghĩa lp SinhVien
3: #ifndef STUDENT_H
4: #define STUDENT_H
5:
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
140
6: #include "person.h"
7:
8: class SinhVien : public Nguoi
9: {
10: protected:
11: float DiemTB;
12: public:
13: SinhVien(char *HT,float DTB);
14: virtual int DuocKhenThuong() const;
15: virtual void Xuat() const;
16: };
17:
18: #endif
File STUDENT.CPP:
1: //STUDENT.CPP
2: Định nghĩa hàm thành viên cho lp SinhVien
3: #include "student.h"
4:
5: SinhVien::SinhVien(char *HT,float DTB):Nguoi(HT)
6: {
7: DiemTB=DTB;
8: }
9:
10: int SinhVien::DuocKhenThuong() const
11: {
12: return DiemTB>9.0;
13: }
14:
15: void SinhVien::Xuat() const
16: {
17: cout<<"Ho va ten cua sinh vien:"<<HoTen;
18: }
File TEACHER.H:
1: //TEACHER.H
2: Định nghĩa lp GiangVien
3: #ifndef TEACHER_H
4: #define TEACHER_H
5:
6: #include "person.h"
7:
8: class GiangVien : public Nguoi
9: {
10: protected:
11: int SoBaiBao;
12: public:
13: GiangVien(char *HT,int SBB);
14: virtual int DuocKhenThuong() const;
15: virtual void Xuat() const;
16: };
17:
18: #endif
File TEACHER.CPP:
1: //TEACHER.CPP
2: Định nghĩa hàm thành viên cho lp GiangVien
3: #include "teacher.h"
4:
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
141
5: GiangVien::GiangVien(char *HT,int SBB):Nguoi(HT)
6: {
7: SoBaiBao=SBB;
8: }
9:
10: int GiangVien::DuocKhenThuong() const
11: {
12: return SoBaiBao>5;
13: }
14:
15: void GiangVien::Xuat() const
16: {
17: cout<<"Ho va ten cua giang vien:"<<HoTen;
18: }
File CT7_2.CPP:
1: //CT7_2.CPP
2: //Chương trình 7.2
3: #include <ctype.h>
4: #include "person.h"
5: #include "student.h"
6: #include "teacher.h"
7:
8: int main()
9: {
10: Nguoi *Ng[100];
11: int N=0;
12: char Chon,Loai;
13: char HoTen[MAX_TEN];
14: do
15: {
16: cout<<"Ho va ten:";
17: cin.getline(HoTen,MAX_TEN);
18: cout<<"Sinh vien hay Giang vien(S/G)? ";
19: cin>>Loai;
20: Loai=toupper(Loai);
21: if (Loai=='S')
22: {
23: float DTB;
24: cout<<"Diem trung binh:";
25: cin>>DTB;
26: Ng[N++]=new SinhVien(HoTen,DTB);
27: }
28: else
29: {
30: int SoBaiBao;
31: cout<<"So bai bao:";
32: cin>>SoBaiBao;
33: Ng[N++]=new GiangVien(HoTen,SoBaiBao);
34: }
35: cout<<"Tiep tuc (C/K)? ";
36: cin>>Chon;
37: Chon=toupper(Chon);
38: cin.ignore();
39: if ((N==100)||(Chon=='K'))
40: break;
41: }
42: while (1);
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
142
43: for(int I=0;I<N;++I)
44: {
45: Ng[I]->Xuat();
46: if (Ng[I]->DuocKhenThuong())
47: cout<<". Nguoi nay duoc khen thuong";
48: cout<<endl;
49: }
50: return 0;
51: }
Chúng ta chy ví d 7.2
, kt qu hình 7.6
Hình 7.6: Kt qu ca ví d 7.2
Ví d 7.3: Gi s cn phi to các hình: hình tròn và hình ch nht đc tô theo hai màu red và blue.
Xây dng mt cây ph h đ qun lý các hình này.
Trc ht chúng ta cn có lp c s Shape đ lu tr thông tin chung cho các hình, sau đó là hai lp dn
xut Rectangle v hình hình ch nht và Circle v hình tròn nh hình 7.7
Lp Shape:
Ta đ tâm.
Màu đng biên.
Màu tô.
Phng thc thit lp tô màu.
Phng thc v hình. Đây là phng thc thun
o.
Lp Rectangle:
Chiu dài và chiu rng.
Phng thc v hình.
Lp Circle:
Bán kính.
Phng thc v hình.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
143
CHƯƠNG 8
CÁC DNG NHP/XUT
I. DN NHP
Các th vin chun C++ cung cp mt tp hp các kh nĕng nhp/xut rng ln. Trong chng này
chúng ta tìm hiu mt phm vi ca các kh nĕng đ đ phn ln các thao tác nhp xut.
Phn ln các đc tính nhp xut mô t đây theo hng đi tng. Kiu này ca nhp/xut thi hành
vic s dng các đc tính khác ca C++ nh các tham chiu, đ
a nĕng hóa hàm và đa nĕng hóa toán t.
Nh chúng ta s thy, C++ s dng nhp/xut kiu an toàn (type safe). Mi thao tác nhp/xut đc
thc hin mt cách t đng theo li nhy cm v kiu d liu. Mi thao tác nhp xut có đc đnh nghƿa
thích hp đ x lý mt kiu d liu c th thì hàm đó đc gi đ x lý kiu d liu đó. Nu không có đi
sánh gia kiu ca d liu hin ti và mt hàm cho vic x lý kiu d liu đó, mt ch dn li biên dch đc
thit lp. Vì th d liu không thích hp không th "lách" qua h thng.
Các ngi dùng có th ch đnh nhp/xut ca các kiu d liu do ngi dùng đnh nghƿa cũng nh
các
kiu d liu chun. Tính m rng này là mt trong các đc tính quan trng ca C++.
II. CÁC DÒNG(STREAMS)
Nhp/xut C++ xy ra trong các dòng ca các byte. Mt dòng đn gin là mt dãy tun t các byte.
Trong các thao tác nhp, các byte chy t thit b (chng hn: mt bàn phím, mt đƿa, mt kt ni mng)
ti b nh chính. Trong các thao tác xut, các byte chy t b nh chính ti mt thit b (chng hn: mt
màn hình, mt máy in, mt đƿa, mt kt ni mng).
ùng dng liên kt vi các byte. Các byte có th biu din các ký t ASCII, bên trong đnh dng d liu
thô, các nh đ ha, ting nói s, hình nh s hoc bt c loi thông tin mt ng dng có th đòi hi.
Công vic ca các c ch h thng nhp/xut là di chuyn các byte t các thit b ti b nh và ngc
li theo li chc và đáng tin c
y. Nh th các di chuyn thng bao gm s di chuyn c hc nh s quay
ca mt đƿa hoc mt bĕng t, hoc nhn phím ti mt bàn phím. Thi gian các di chuyn này thông thng
khng l so vi thi gian b x lý thao tác d liu ni ti. Vì th, các thao tác nhp/xut đòi hi có k hoch
cn thn và điu chnh đ b
o đm s thi hành ti đa.
C++ cung cp c hai kh nĕng nhp/xut "mc thp" (low-level) và "mc cao" (high-level). Các kh
nĕng nhp/xut mc thp (nghƿa là nhp/xut không đnh dng) ch đnh c th s byte nào đó phi đc di
chuyn hoàn toàn t thit b ti b nh hoc t b nh ti thit b. Trong các di chuyn nh th
, byte riêng r
là mc cn quan tâm. Vì th các kh nĕng mc thp cung cp tc đ cao, các di chuyn dung lng cao,
nhng các kh nĕng này không phi là tin li lm cho lp trình viên.
Các lp trình viên u thích quan đim nhp/xut mc cao, nghƿa là nhp/xut có đnh dng, trong đó các
byte đc nhóm thành các đn v có ý nghƿa nh các s nguyên, các s chm đng, các ký t, các chui và
các kiu do ngi dùng đ
nh nghƿa.
II.1. Các file header ca th vin iostream
Th vin iostream ca C++ cung cp hàng trĕm kh nĕng ca nhp/xut. Mt vài tp tin header cha
các phn ca giao din th vin.
Phn ln chng trình C++ thng include tp tin header <iostream.h> mà cha các thông tin c bn
đòi hi tt c các thao tác dòng nhp/xut. Tp tin header <iostream.h> cha các đi tng cin, cout, cerr
clog mà tng ng vi dòng nhp chun, dòng xut chun, dòng li chun không vùng đm và dòng li
chun vùng đm. C hai kh nĕng nhp/xut đnh dng và không đnh dng đc cung cp.
Header <iomanip.h> cha thông tin hu ích cho vic thc hin nhp/xut đnh dng vi tên gi là các
b x lý dòng biu hin bng tham s (parameterized stream manipulators).
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
144
Header <fstream.h> cha các thông tin quan trng cho các thao tác x lý file do ngi dùng kim
soát.
Header <strstream.h> cha các thông tin quan trng cho vic thc hin các đnh dng trong b nh.
Điu này tng t x lý file, nhng các thao tác nhp/xut ti và t mng các ký t hn là file.
Header <stdiostream.h> cha các thông tin quan trng cho các chng trình trn các kiu nhp/xut
ca C và C++. Các chng trình mi phi tránh kiu nhp/xut C, nhng cn thì hiu chnh các chng trình
C, hoc tin trin chng trình C thành C++.
II.2. Các lp và các đi tng ca dòng nhp/xut
Th vin iostream cha nhiu lp đ x lý mt s đa dng rng ca các thao tác nhp/xut. Lp
istream h tr các thao tác dòng nhp. Lp ostream h tr các thao tác dòng xut. Lp iostream h tr c
hai thao tác dòng nhp và dòng xut. Lp istream và lp ostream đu k tha đn t lp c s ios. Lp
iostream đc k th
a thông qua đa k tha t hai lp istream ostream.
Hình 8.1: Mt phn ca phân cp lp dòng nhp/xut
Đa nĕng hóa toán t cung cp mt ký hiu thích hp cho vic thc hin nhp/xut. Toán t dch chuyn
trái (<<) đc đa nĕng hóa đ đnh rõ dòng xut và đc tham chiu nh là toán t chèn dòng. Toán t dch
chuyn phi (>>) đc đa nĕng hóa đ đnh rõ dòng nhp và đc tham chiu nh là toán t trích dòng. Các
toán t
này đc s dng vi các đi tng dòng chun cin, cout, cerr clog, và bình thng vi các đi
tng dòng do ngi dùng đnh nghƿa.
cin là mt đi tng ca lp istream đc nói là "b ràng buc ti" (hoc kt ni ti) thit b nhp
chun, thông thng là bàn phím. Toán t trích dòng đc s dng lnh sau to ra mt giá tr cho bin
nguyên X đc nhp t cin ti b nh:
int X;
cin >> X;
cout là mt đi tng ca lp ostream đc nói là "b ràng buc ti" thit b xut chun, thông
thng là màn hình. Toán t chèn dòng đc s dng lnh sau to ra mt giá tr cho bin nguyên X đc
xut t b nh ti thit b chun:
cout << X;
cerr là mt đi tng ca lp ostream đc nói là "b ràng buc ti" thit b li chun. Vic xut
đi tng cerr là không vùng đm. Điu này có nghƿa là mi ln chèn ti cerr to ra kt xut ca nó xut
hin ngay tc thì; Điu này thích hp cho vic thông báo nhanh chóng ngi dùng khi có s c.
clog là mt đi tng ca lp ostream đc nói là "b ràng buc ti" thit b li chun. Vic xut
đi tng cerr là có vùng đm. Điu này có nghƿa là mi ln chèn ti cerr to ra kt xut ca nó đc gi
trong vùng đm cho đn khi vùng đm đy hoc vùng đm đc flush.
Vic x lý file ca C++ s dng các lp ifstream đ thc hin các thao tác nhp file, ofstream cho các
thao tác xut file, và fstream cho các thao tác nhp/xut file. Lp ifstream k tha t istream, ofstream lp
k tha t ostream, và lp fstream k tha t iostream.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
145
Hình 8.2: Mt phn ca phân cp lp dòng nhp/xut vi vic x lý file.
III. DÒNG XUT
ostream ca C++ cung cp kh nĕng đ thc hin xut đnh dng và không đnh dng. Các kh nĕng
xut bao gm: xut các kiu d liu chun vi toán t chèn dòng; xut các ký t vi hàm thành viên put();
xut không đnh dng vi hàm thành viên write; xut các s nguyên dng thp phân, bát phân và thp lc
phân; xut các giá tr chm đng vi đ chính xác khác nhau, vi du chm thp phân, theo ký hi
u khoa hc
và theo ký hiu c đnh; xut d liu theo các trng đn thêm các ký t ch đnh; và xut các mu t ch
hoa theo ký hiu khoa hc và ký hiu thp lc phân.
III.1. Toán t chèn dòng
Dòng xut có th đc thc hin vi toán t chèn dòng, nghƿa là toán t << đã đa nĕng hóa. Toán t <<
đã đc đa nĕng hóa đ xut các mc d liu ca các kiu có sn, xut chui, và xut các giá tr con tr.
Ví d 8.1: Minh ha xut chui s dng mt lnh chèn dòng.
1: //Chương trình 8.1:Xut mt chui s dng chèn dòng
2: #include <iostream.h>
3:
4: int main()
5: {
6: cout<<"Welcome to C++!\n";
7: return 0;
8: }
Chúng ta chy ví d 8.1
, kt qu hình 8.3
Hình 8.3: Kt qu ca ví d 8.1
Ví d 8.2: Minh ha xut chui s dng nhiu lnh chèn dòng.
1: //Chương trình 8.2:Xut mt chui s dng hai chèn dòng
2: #include <iostream.h>
3:
4: int main()
5: {
6: cout<<"Welcome to";
7: cout<<"C++!\n";
8: return 0;
9: }
Chúng ta chy ví d 8.2
, kt qu hình 8.4
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
146
Hình 8.4: Kt qu ca ví d 8.2
Hiu qu ca chui thoát \n (newline) cũng đt đc bi b x lý dòng (stream manipulator) endl (end
line).
Ví d 8.3:
1: //Chương trình 8.3:S dng b x lý dòng endl
2: #include <iostream.h>
3:
4: int main()
5: {
6: cout<<"Welcome to";
7: cout<<"C++!";
8: cout<<endl;
9: return 0;
10: }
Chúng ta chy ví d 8.3
, kt qu hình 8.5
Hình 8.5: Kt qu ca ví d 8.3
B x lý dòng endl đa ra mt ký t newline, và hn na, flush vùng đm xut (nghƿa là to ra vùng
đm xut đc xut ngay lp tc k c nó cha đy). Vùng đm xut cũng có th đc flush bng:
cout<<flush;
Ví d 8.4: Các biu thc có th xut
1: //Chương trình 8.4: Xut giá tr biu thc.
2: #include <iostream.h>
3:
4: int main()
5: {
6: cout<<"47 plus 53 is ";
7: cout<< (47+53);
8: cout<<endl;
9: return 0;
10: }
Chúng ta chy ví d 8.4
, kt qu hình 8.6
Hình 8.6: Kt qu ca ví d 8.4
III.2. Ni các toán t chèn dòng và trích dòng
Các toán t đã đa nĕng hóa << >> có th đc theo dng ni vào nhau.
Ví d 8.5: Ni các toán t đã đa nĕng hóa
1: //Chương trình 8.5: Ni toán t << đã đa năng hóa.
2: #include <iostream.h>
3:
4: int main()
5: {
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
147
6: cout<<"47 plus 53 is "<< (47+53)<<endl;
7: return 0;
8: }
Chúng ta chy ví d 8.5
, kt qu hình 8.7
Hình 8.7: Kt qu ca ví d 8.5
Nhiu chèn dòng dòng 6 trong ví d 8.5 đc thc thi nu có th vit:
(((cout<<"47 plus 53 is ")<< (47+53))<<endl);
nghƿa là << liên kt t trái qua phi. Loi liên kt ca các toán t chèn dòng đc phép bi vì toán t đa
nĕng hóa << tr v mt tham chiu ti đi tng toán hng bên trái ca nó, nghƿa là cout. Vì th biu thc
đt trong ngoc bên cc trái:
(cout<<"47 plus 53 is ")
xut ra mt chui đã ch đnh và tr v mt tham chiu ti cout. Điu này cho phép biu thc đt trong
ngoc gia đc c lng:
(cout<< (47+53))
xut giá tr nguyên 100 và tr v mt tham chiu ti cout. Sau đó biu thc đt trong ngoc bên cc phi
đc c lng:
cout<<endl;
xut mt newline, flush cout và tr v mt tham chiu ti cout. Tr v
cui cùng này không đc s
dng.
8.3.3 Xut các bin kiu char *
:
Trong nhp/xut kiu C, tht cn thit cho lp trình viên đ cung cp thông tin kiu. C++ xác
đnh các kiu d liu mt cách t đng – mt ci tin hay hn C. Đôi khi điu này là mt tr ngi.
Chng hn, chúng ta bit rng mt chui ký t là kiu char *. Mc đích ca chúng ta in giá tr ca
con tr đó, nghƿa là đa ch b nh ca ký t đu tiên ca chui đó. Nhng toán t << đã đc đa
nĕng hóa đ in d liu ca kiu char * nh là chui kt thúc ký t null. Gii pháp là ép con tr thành
kiu void *.
Ví d 8.6: In đa ch lu trong mt bin kiu char *
Chúng ta chy ví d 8.6
, kt qu hình 8.8
Hình 8.8: Kt qu ca ví d 8.6
III.3. Xut ký t vi hàm thành viên put(); Ni vi nhau hàm put()
Hàm thành viên put() ca lp ostream xut mt ký t có dng :
ostream& put(char ch);
Chng hn:
cout.put(‘A’);
Gi put() có th đc ni vào nhau nh:
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
148
cout.put(‘A’).put(‘\n’);
Hàm put() cũng có th gi vi mt biu thc có giá tr là mã ASCII nh:
cout.put(65);
IV. DÒNG NHP
Dòng nhp có th đc thc hin vi toán t trích, nghƿa là toán t đã đa nĕng hóa >>. Bình thng toán
t này b qua các ký t khong trng (nh các blank, tab và newline). trong dòng nhp. Toán t trích dòng
tr v zero (false) khi kt thúc file (end-of-file) đc bt gp trên mt dòng; Ngc li, toán t trích dòng tr
v mt tham chiu ti đi tng xuyên qua đó nó đc kéo theo. Mi dòng cha mt tp các bit trng thái
(state bit) s dng
đ điu khin trng thái ca dòng (nghƿa là đnh dng, n đnh các trng thái li,…). Trích
dòng sinh ra failbit ca dòng đc thit lp nu d liu ca kiu sai đc nhp, và sinh ra badbit ca dòng
đc thit lp nu thao tác sai.
IV.1. Toán t trích dòng:
Đ đc hai s nguyên s dng đi tng cin và toán t trích dòng đã đa nĕng hóa >>.
Ví d 8.7:
1: //Chương trình 8.7
2: #include <iostream.h>
3:
4: int main()
5: {
6: int X, Y;
7: cout << "Enter two integers: ";
8: cin >> X >> Y;
9: cout << "Sum of " << X << " and " << Y << " is: "
10: << (X + Y) << endl;
11: return 0;
12: }
Chúng ta chy ví d 8.7
, kt qu hình 8.9
Hình 8.9: Kt qu ca ví d 8.7
Mt cách ph bin đ nhp mt dãy các giá tr là s dng toán t trích dòng trong vòng lp while. Toán
t trích dòng tr v false (0) khi end-of-file đc bt gp:
Ví d 8.8:
2: #include <iostream.h>
3:
4: int main()
5: {
6: int Grade, HighestGrade = -1;
7: cout << "Enter grade (enter end-of-file to end): ";
8: while (cin >> Grade)
9: {
10: if (Grade > HighestGrade )
11: HighestGrade = Grade;
12: cout << "Enter grade (enter end-of-file to end): ";
13: }
14: cout <<endl<< "Highest grade is:" << HighestGrade<< endl;
15: return 0;
16: }
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
149
Chúng ta chy ví d 8.8
, kt qu hình 8.10
Hình 8.10: Kt qu ca ví d 8.8
IV.2. Các hàm thành viên get() và getline()
Hàm istream::get() có các dng sau:
(1) int get();
(2) istream& get(unsigned char &ch);
(3) istream& get(signed char &ch);
(4) istream& get(unsigned char * puch, int len, char delim=’\n’);
(5) istream& get(signed char * psch, int len, char delim=’\n’);
Dng (1) trích ký t đn t dòng và tr v nó hoc EOF khi end-of-file trên dòng đc bt gp.
Dng (2) và (3) trích mt ký t đn t dòng và lu tr nó vào ch.
Dng (4) và (5) trích các ký t t dòng cho đn khi hoc delim đc tìm thy, gii hn len đt đn, hoc
end-of-file đc bt gp. Các ký t đc lu trong con tr ch đn mng ký t puch hoc psch.
Ví d 8.9: S dng hàm get() dng (1)
1: //Chương trình 8.9
2: #include <iostream.h>
3: int main()
4: {
5: int Ch;
6: cout << "Before input, cin.eof() is " << cin.eof() << endl
7: << "Enter a sentence followed by end-of-file:" << endl;
8: while ( ( Ch = cin.get() ) != EOF)
9: cout.put(Ch);
10: cout << endl << "EOF in this system is: " << Ch << endl;
11: cout << "After input, cin.eof() is " << cin.eof() << endl;
12: return 0;
13: }
Chúng ta chy ví d 8.9
, kt qu hình 8.11
Hình 8.11: Kt qu ca ví d 8.9
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
150
Trong ví d 8.9 trên, chúng ta có s dng hàm ios::eof() có dng sau:
int eof(); Hàm tr v giá tri khác zero nu end-of-file bt gp.
Ví d 8.10: S dng hàm get() dng (5)
1: //Chương trình 8.10
2: #include <iostream.h>
3:
4: const int SIZE = 80;
5:
6: int main()
7: {
8: char Buffer1[SIZE], Buffer2[SIZE];
9: cout << "Enter a sentence:" << endl;
10: cin >> Buffer1;
11: cout << endl << "The string read with cin was:" << endl
12: << Buffer1 << endl << endl;
13: cin.get(Buffer2, SIZE);
14: cout << "The string read with cin.get was:" << endl
15: << Buffer2 << endl;
16: return 0;
17: }
Chúng ta chy ví d 8.10
, kt qu hình 8.12
Hình 8.12: Kt qu ca ví d 8.10
Hàm istream::getline() có các dng sau:
(1) istream& getline(unsigned char * puch, int len, char delim=’\n’);
(2) istream& getline(signed char * psch, int len, char delim=’\n’);
Ví d 8.11: S dng hàm getline()
1: //Chương trình 8.11
2: #include <iostream.h>
3:
4: const SIZE = 80;
5:
6: int main()
7: {
8: char Buffer[SIZE];
9: cout << "Enter a sentence:" << endl;
10: cin.getline(Buffer, SIZE);
11: cout << endl << "The sentence entered is:" << endl
12: << Buffer << endl;
13: return 0;
14: }
Chúng ta chy ví d 8.11
, kt qu hình 8.13
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
151
Hình 8.13: Kt qu ca ví d 8.11
IV.3. Các hàm thành viên khác ca istream
Hàm ignore():
istream& ignore(int nCount = 1, int delim = EOF);
Trích và loi b lên đn nCount ký t. Vic trích dng nu delim đc bt gp hoc nu end-of-file bt
gp.
Hàm putback():
istream& putback(char ch);
Đt mt ký t ngc li dòng nhp.
Hàm peek():
int peek();
Hàm tr v ký t k tip mà không trích nó t dòng.
IV.4. Nhp/xut kiu an toàn
C++ cung cp nhp/xut kiu an toàn (type-safe). Các toán t << >> đc đa nĕng hóa đ nhn các
mc d liu ca kiu c th. Nu d liu bt ng đc x lý, các c hiu li khác nhau đc thit lp mà
ngi dùng có th kim tra đ xác đnh nu mt thao tác nhp/xut thành công hoc tht bi. Phn sau chúng
ta s kho sát k hn.
V. NHP/XUT KHÔNG ĐNH DNG VI READ(),GCOUNT() VÀ WRITE()
Nhp/xut không đnh dng đc thc hin vi các hàm thành viên istream::read()
ostream::write().
Hàm istream::read():
istream& read(unsigned char* puch, int nCount);
istream& read(signed char* psch, int nCount);
Trích các byte t dòng cho đn khi gii hn nCount đt đn hoc cho đn khi end- of-file đt đn. Hàm
này có ích cho dòng nhp nh phân.
Hàm ostream::write():
ostream& write(const unsigned char* puch, int nCount);
ostream& write(const signed char* psch, int nCount);
Chèn nCount byte vào t vùng đm (đc tr bi puch psch) vào dòng. Nu file đc m ch đ
text, các ký t CR có th đc chèn vào. Hàm này có ích cho dòng xut nh phân. Chng hn:
char Buff[]="HAPPY BIRTHDAY";
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
152
cout.write(Buff,10);
Hàm istream::gcount():
int gcount();
Hàm tr v s ký t đã trích bi hàm nhp không đnh dng cui cùng.
VI. DÒNG NHP/ XUT FILE
Đ thc thi x lý file trong C++, các chng trình phi include tp tin <iostream.h> <fstream.h>.
Header <fstream.h> gm đnh nghƿa cho các lp dòng ifstream cho nhp (đc) t mt file, ofstream cho
xut (ghi) ti mt file) và fstream cho nhp/xut (đc/ghi) ti mt file. Các file đc m bng cách to các
đi tng ca các lp dòng này. Cây ph h ca các lp này hình 8.2.
Constructor ca lp ofstream:
(1) ofstream();
(2) ofstream(const char* szName,int nMode=ios::out,int nProt
=filebuf::openprot);
(3) ofstream(int fd);
(4) ofstream(filedesc fd, char* pch, int nLength);
Trong đó: szName: Tên file đc m.
nMode: Mt s nguyên cha các bit mode đnh nghƿa là kiu liy kê ca ios. Có th kt hp bng toán t
|. Tham s này có th mt trong các giá tr sau:
Mode Ý nghƿa
ios::app
Hàm di chuyn con tr file ti end-of-file. Khi các byte mi đc ghi lên file,
chúng luôn luôn ni thêm vào cui, ngay c v trí đc di chuyn vi hàm
ostream::seekp().
ios::ate
Hàm di chuyn con tr file ti end-of-file. Khi byte mi đu tiên đc ghi lên file,
chúng luôn luôn ni thêm vào cui, nhng khi các byte k tip đc ghi, chúng ghi
vào v trí hin hành.
ios::in
M file đ đc.Vi dòng ifstream, vic m file đng nhiên đc thc hin ch
đ này.
ios::out
M file đ đc.Vi dòng ofstream, vic m file đng nhiên đc thc hin
ch đ này.
ios::trunc
Xóa file hin có trên đƿa và to file mi cùng tên. Cũng có hiu đây là cht ct file
cũ, làm cho kích thc ca nó bng 0, chun b ghi ni dung mi. Mode này đc áp
dng nu ios::out đc ch đnh và ios::app, ios::ate, và ios::in không đc ch đnh.
ios::nocreate
Nu file không tn ti thì thao tác m tht bi.
ios::noreplace
Nu file tn ti thì thao tác m tht bi.
ios::binary
M file ch đ nh phân (mc đnh là ch đ vĕn bn).
nProt: Đc t ch đ bo v file.
fd: Mã nhn din file.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
153
pch: Con tr tr ti vùng dành riêng chiu dài nLength. Giá tr NULL (hoc nLength=0) dn đn dòng
không vùng đm.
nLength: Chiu dài tính theo byte ca vùng dành riêng (0=không vùng đm).
Dng (1) xây dng mt đi tng ofstream mà không m file.
Dng (2) xây dng mt đi tng ofstream và m file đã ch đnh.
Dng (3) xây dng mt đi tng ofstream và gn (attach) vi mt file m.
Dng (4) xây dng mt đi tng ofstream mà liên kt vi đi tng filebuf. Đi tng filebuf đc
gn ti file m và vùng dành riêng.
Constructor ca lp ifstream:
(1) ifstream();
(2) ifstream(const char* szName,int nMode=ios::in,int nProt=filebuf::openprot);
(3) ifstream(int fd);
(4) ifstream(filedesc fd, char* pch, int nLength);
Dng (1) xây dng mt đi tng ifstream mà không m file.
Dng (2) xây dng mt đi tng ifstream và m file đã ch đnh.
Dng (3) xây dng mt đi tng ifstream và gn (attach) vi mt file m.
Dng (4) xây dng mt đi tng ofstream mà liên kt vi đi tng filebuf. Đi tng filebuf đc
gn ti file m và vùng dành riêng.
Constructor ca lp fstream:
(1) fstream();
(2) fstream(const char* szName,int nMode,int nProt=filebuf::openprot);
(3) fstream(int fd);
(4) fstream(filedesc fd, char* pch, int nLength);
Dng (1) xây dng mt đi tng fstream mà không m file.
Dng (2) xây dng mt đi tng fstream và m file đã ch đnh.
Dng (3) xây dng mt đi tng fstream và gn (attach) vi mt file m.
Dng (4) xây dng mt đi tng ofstream mà liên kt vi đi tng filebuf. Đi tng filebuf đc
gn ti file m và vùng dành riêng.
Nu chúng ta s dng constructor dng (1) thì chúng ta dùng hàm open() đ m file:
Hàm ofstream::open():
void open(const char* szName,int nMode=ios::out,int nProt=filebuf::openprot);
Hàm ifstream::open():
void open(const char* szName,int nMode=ios::in,int nProt=filebuf::openprot);
Hàm fstream::open():
void open(const char* szName,int nMode,int nProt=filebuf::openprot);
Đ đóng file chúng ta dùng hàm close(), hàm này các lp ifstream, ofstream, và fstream đu có
dng:
void close();
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
154
Các hàm liên quan đến con tr file:
- Lp istream:
Hàm seekg(): (seek get)
(1) istream& seekg(streampos pos);
(2) istream& seekg(streamoff off,ios::seek_dir dir);
Trong đó:
+ pos: V trí mi. streampos là tng đng typedef vi long.
+ off: Giá tr offset mi. là tng đng typedef vi long.
+ dir: hng seek. Có mt trong các tr sau:
ios::begin
Seek t bt đu ca dòng.
ios::cur
Seek t øv trí hin hành ca
dòng
ios::end
Seek t
cui ca dòng
Hàm tellg()
: (tell get)
streampos tellg();
Hàm tr v v trí hin hành ca con tr file.
- Lp ostream:
Hàm seekp(): (seek put)
(1) ostream& seekp(streampos pos);
(2) ostream& seekp(streamoff off,ios::seek_dir dir);
Hàm tellp(): (tell put)
streampos tellp();
Hàm tr v v trí hin hành ca con tr file.
VI.1. Nhp/xut file vĕn bn
Nu dòng đc gn vi file vĕn bn, vic nhp/xut file đc thc hin mt cách đn gin bi các toán
t >> <<, ging nh khi chúng ta làm vic vi cin cout. File vĕn bn cha d liu dng mã ASCII,
kt thúc bi ký t EOF.
Ví d 8.28:
To file vĕn bn có th đc s dng trong h thng có th nhn đc các tài khon đ giúp
đ qun lý tin n bi các khách hàng tín dng ca công ty. Mi khách hàng, chng trình cha mt s tài
khon, tên và s d (balance).
1: //Chương trình 8.28
2: #include <iostream.h>
3: #include <fstream.h>
4: #include <stdlib.h>
5:
6: int main()
7: {
8: ofstream OutClientFile("clients.dat", ios::out);
9: if (!OutClientFile)
10: {
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
155
11: cerr << "File could not be opened" << endl;
12: exit(1);
13: }
14: cout << "Enter the Account, Name, and Balance." << endl
15: << "Enter EOF to end input." << endl << "? ";
16: int Account;
17: char Name[10];
18: float Balance;
19: while (cin >> Account >> Name >> Balance)
20: {
21: OutClientFile << Account << " " << Name
22: << " " << Balance << endl;
23: cout << "? ";
24: }
25: OutClientFile.close();
26: return 0;
27: }
Chúng ta chy ví d 8.28
, kt qu hình 8.30
Hình 8.30: Kt qu ca ví d 8.28
Ví d 8.29:
Đc file vĕn bn to ví d 8.28 và xut ra màn hình.
1: //Chương trình 8.29
2: #include <iostream.h>
3: #include <fstream.h>
4: #include <iomanip.h>
5: #include <stdlib.h>
6:
7: void OutputLine(int, char*, float);
8:
9: int main()
10: {
11: ifstream InClientFile("clients.dat", ios::in);
12: if (!InClientFile)
13: {
14: cerr << "File could not be opened" << endl;
15: exit(1);
16: }
17: int Account;
18: char Name[10];
19: float Balance;
20: cout << setiosflags(ios::left) << setw(10) << "Account"
21: << setw(13) << "Name" << "Balance" << endl;
22: while (InClientFile >> Account >> Name >> Balance)
23: OutputLine(Account, Name, Balance);
24: InClientFile.close();
25: return 0;
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
156
26: }
27:
28: void OutputLine(int Acct, char *Name, float Bal)
29: {
30: cout << setiosflags(ios::left) << setw(10) << Acct
31: << setw(13) << Name << setw(7) << etprecision(2)
32:<< setiosflags(ios::showpoint | ios::right) << Bal << endl;
33: }
Chúng ta chy ví d 8.29
, kt qu hình 8.31
Hình 8.31: Kt qu ca ví d 8.29
Do lp ifstream dn xut t lp istream nên chúng ta có th dùng các hàm istream::get(),
istream::getline().
Ví d 8.30:
Đc file vĕn bn to ví d 8.28 bng hàm istream::getline() và xut ra màn hình.
1: //Chương trình 8.30
2: #include <iostream.h>
3: #include <fstream.h>
4: #include <iomanip.h>
5: #include <stdlib.h>
6:
7: #define MAXLINE 256
8:
9: int main()
10: {
11: ifstream InClientFile("clients.dat", ios::in);
12: if (!InClientFile)
13: {
14: cerr << "File could not be opened" << endl;
15: exit(1);
16: }
17: char Line[MAXLINE];
18: while (!InClientFile.eof())
19: {
20: InClientFile.getline(Line,MAXLINE-1);
21: cout<<Line<<endl;
22: }
23: InClientFile.close();
24: return 0;
25: }
Chúng ta chy ví d 8.30
, kt qu hình 8.32.(ni dung tp tin clients.dat)
Hình 8.32: Kt qu ca ví d 8.30
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
157
VI.2. Nhp/xut file nh phân
Đối vi file nh phân (còn gi là file truy cp ngu nhiên), chúng ta m chế độ ios::binary. Đối vi
file nh phân, chúng ta có th dùng hàm istream::get() ostream::put() để đc và ghi tng byte mt. Để
đc và ghi nhiu byte cùng lúc chúng ta có th dùng istream::read() ostream::write().
Ví d 8.31:
Ly li ví d 8.28 nhng lu d liu di dng nh phân.
1: //Chương trình 8.31
2: #include <iostream.h>
3: #include <fstream.h>
4: #include <stdlib.h>
5:
6: typedef struct
7: {
8: int Account;
9: char Name[10];
10: float Balance;
11: }Client;
12:
13: int main()
14: {
15: ofstream OutClientFile("credit.dat", ios::out|ios::binary);
16: if (!OutClientFile)
17: {
18: cerr << "File could not be opened" << endl;
19: exit(1);
20: }
21: cout << "Enter the Account, Name, and Balance." << endl
22: << "Enter EOF to end input." << endl << "? ";
23: Client C;
24: while (cin >> C.Account >> C.Name >> C.Balance)
25: {
26: OutClientFile.write((char *)&C,sizeof(Client));
27: cout << "? ";
28: }
29: OutClientFile.close();
30: return 0;
31: }
Chúng ta chy ví d 8.31
, kt qu hình 8.33 (ni dung tp tin credit.dat)
Hình 8.33: Kt qu ca ví d 8.31
Ví d 8.32:
Đc file to ví d 8.31 và xut ra màn hình.
1: //Chương trình 8.32
2: #include <iostream.h>
3: #include <fstream.h>
4: #include <iomanip.h>
5: #include <stdlib.h>
6:
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
158
7: typedef struct
8: {
9: int Account;
10: char Name[10];
11: float Balance;
12: }Client;
13:
14: void OutputLine(Client);
15:
16: int main()
17: {
18: ifstream InClientFile("credit.dat", ios::in|ios::binary);
19: if (!InClientFile)
20: {
21: cerr << "File could not be opened" << endl;
22: exit(1);
23: }
24: cout << setiosflags(ios::left) << setw(10) << "Account"
25: << setw(13) << "Name" << "Balance" << endl;
26: Client C;
27: while (InClientFile.read((char *)&C,sizeof(Client)))
28: OutputLine(C);
29: InClientFile.close();
30: return 0;
31: }
32:
33: void OutputLine(Client C)
34: {
35: cout << setiosflags(ios::left) << setw(10) << C.Account
36: << setw(13) << C.Name << setw(7) << setprecision(2)
37: << setiosflags(ios::showpoint | ios::right)<<
C.Balance << endl;
38: }
Chúng ta chy ví d 8.32
, kt qu hình 8.34
Hình 8.34: Kt qu ca ví d 8.32
BÀI TP
Bài 1: Cài đt toán t >> và << cho kiu d liu mng đ nhp và xut.
Bài 2: Cài đt thêm toán t >> và << cho lp Time trong bài 5 ca chng 4.
Bài 3: Cài đt thêm toán t >> và << cho lp Date trong bài 6 ca chng 4.
Bài 4: Vit chng trình kim tra các giá tr nguyên nhp vào dng h 10, h 8 và h 16.
Bài 5: Vit chng trình in bng mã ASCII cho các ký t có mã ASCII t 33 đn 126. Chng
trình in gm giá tr ký t, giá tr h 10, giá tr h 8 và giá tr h 16.
Bài 6: Vit chng trình in các giá tr nguyên dng luôn có du + phía trc.
Bài 7: Vit chng trình tng t nh lnh COPY ca DOS đ sao chép ni dung ca file .
Bài 8: Vit chng trình cho bit kích thc file.
Bài 9: Vit chng trình đm s lng t có trong mt file vĕn bn ting Anh.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
159
CHƯƠNG 9
HÀM LP TEMPLATE
Trong phn này, chúng ta tìm hiu v mt trong các đc tính còn li ca C++, đó là template (khuôn
mu). Các template cho phép chúng ta đ đnh rõ, vi mt đon mã đn gin, mt toàn b phm vi ca các
hàm có liên quan (đa nĕng hóa)–gi là các hàm template-hoc mt toàn b phm vi ca các lp có liên quan-
gi là lp template.
Chúng ta có th vit mt hàm template đn gin cho vic sp xp mt mng và C++ t đng phát sinh
các hàm template riêng bit mà s sp x
p mt mng int, sp xp mt mng float, …
Chúng ta có th vit mt lp template cho lp stack và sau đó C++ t đng phát sinh các lp template
riêng bit nh lp stack ca int, lp stack ca float,…
I. Các hàm template
Các hàm đa nĕng hóa bình thng đc s dng đ thc hin các thao tác tng t trên các kiu khác
nhau ca d liu. Nu các thao tác đng nht cho mi kiu, điu này có th thc hin mch lc và thun tin
hn s dng các hàm template. Lp trình viên vit đnh nghƿa hàm template đn gin. Da vào các kiu tham
s cung cp trong li gi hàm này, trình biên dch t đng phát sinh các hàm mã đi t
ng riêng bit đ x
lý mi kiu ca li gi thích hp. Trong C, điu này có th đc thc hin bng cách s dng các macro to
vi tin x#define. Tuy nhiên, các macro biu th kh nĕng đi vi các hiu ng l nghiêm trng và
không cho phép trình biên dch thc hin vic kim tra kiu. Các hàm template cung cp mt gii pháp mch
lc ging nh các macro, nhng cho phép kim tra ki
u đy đ. Chng hn, chúng ta mun vit hàm ly tr
tuyt đi ca mt s, chúng ta có th vit nhiu dng khác nhau nh sau:
int MyAbs(int X)
{
return X>=0?X:-X;
}
long MyAbs(long X)
{
return X>=0?X:-X;
}
double MyAbs(double X)
{
return X>=0?X:-X;
}
Tuy nhiên vi các hàm này chúng ta vn cha có gii pháp tt, mang tính tng quát nht nh hàm có
tham s kiu int nhng giá tr tr v là double và ngc li.
Tt c các hàm template đnh nghƿa bt đu vi t khóa template theo sau mt danh sách các tham s
hình thc vi hàm template vây quanh trong các ngoc nhn (<>); Mi tham s hình thc phi đc đt
trc bi t khóa class nh:
template <class T>
hoc template <class T1, class T2,>
Các tham s hình thc ca mt đnh nghƿa template đc s dng đ mô t các kiu ca các tham s cho
hàm, đ mô t kiu tr v ca hàm, và đ khai báo các bin bên trong hàm. Phn đnh nghƿa hàm theo sau và
đc đnh nghƿa ging nh bt k hàm nào. Chú ý t khóa class s dng đ mô t các kiu tham s ca hàm
template thc s nghƿa là "kiu có sn và kiu ngi dùng đnh ngh
ƿa bt k".
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
160
Khi đó, hàm tr tuyt đi trên vit theo hàm template:
template <class T>
T MyAbs(T x)
{
return (x>=0)?x:-x;
}
Hàm template MyAbs() khai báo mt tham s hình thc T cho kiu ca mt s. T đc tham kho nh
mt tham s kiu. Khi trình biên dch phát hin ra mt li gi hàm MyAbs() trong chng trình, kiu ca
tham s th nht ca hàm MyAbs() đc thay th cho T thông qua đnh nghƿa template, và C++ to mt hàm
template đy đ đ tr v tr tuyt đi ca mt s ca ki
u d liu đã cho. Sau đó, hàm mi to đc biên
dch. Chng hn:
cout<<MyAbs(-2)<<endl;
cout<<MyAbs(3.5)<<endl;
Trong ln gi th nht, hàm MyAbs() có tham s thc là int nên trình biên dch to ra hàm int
MyAbs(int) theo dng ca hàm template, ln th hai s to ra hàm float MyAbs(float).
Mi tham s hình thc trong mt đnh nghƿa hàm template phi xut hin trong danh sách tham s ca
hàm ti thiu mt ln. Tên ca tham s hình thc ch có th s dng mt ln trong danh sách tham s ca
phn đ
u template.
Ví d 9.1: S dng hàm template đ in các giá tr ca mt mng có kiu bt k.
1: //Chương trình 9.1
2: #include <iostream.h>
3:
4: template<class T>
5: void PrintArray(T *Array, const int Count)
6: {
7: for (int I = 0; I < Count; I++)
8: cout << Array[I] << " ";
9:
10: cout << endl;
11: }
12:
13: int main()
14: {
15: const int Count1 = 5, Count2 = 7, Count3 = 6;
16: int A1[Count1] = {1, 2, 3, 4, 5};
17: float A2[Count2] = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7};
18: char A3[Count3] = "HELLO";
19: cout << "Array A1 contains:" << endl;
20: PrintArray(A1, Count1); //Hàm template kiu int
21: cout << "Array A2 contains:" << endl;
22: PrintArray(A2, Count2); //Hàm template kiu float
23: cout << "Array A3 contains:" << endl;
24: PrintArray(A3, Count3); //Hàm template kiu char
25: return 0;
26: }
Chúng ta chy ví d 9.1
, kt qu hình 9.1
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
161
Hình 9.1: Kt qu ca ví d 9.1
Ví d 9.2: Hàm template có th có nhiu tham s.
1: //Chương trình 9.2
2: #include <iostream.h>
3:
4: template<class T>
5: T Max(T a, T b)
6: {
7: return (a>b)?a:b;
8: }
9:
10: int main()
11: {
12: float A,B;
13: cout<<"Enter first number:";
14: cin>>A;
15: cout<<"Enter second number:";
16: cin>>B;
17: cout<<"Maximum:"<<Max(A,B);
18: return 0;
19: }
Chúng ta chy ví d 9.2
, kt qu hình 9.2
Hình 9.2: Kt qu ca ví d 9.2
Mt hàm template có th đc đa nĕng hóa theo vài cách. Chúng ta có th cung cp các hàm template
khác mà mô t cùng tên hàm nhng các tham s hàm khác nhau. Mt hàm template cũng có th đc đa
nĕng hóa bi cung cp hàm non-template vi cùng tên hàm nhng các tham s hàm khác nhau. Trình biên
dch thc hin mt x lý so sánh đ xác đnh hàm gi khi mt hàm đc gi. Đu tiên trình biên dch c
gng tìm và s dng mt đi sánh chính xác mà các tên hàm và các kiu tham s đi sánh chính xác. N
u
điu này tht bi, trình biên dch kim tra nu mt hàm template đã có mà có th phát sinh mt hàm template
vi mt đi sánh chính xác ca tên hàm và các kiu tham s. Nu mt hàm template nh th đc tìm thy,
trình biên dch phát sinh và s dng hàm template thích hp. Chú ý xđi sánh này vi các template đòi
yêu các đi sánh chính xác trên tt c kiu tham s-không có các chuyn đi t đng đc áp dng.
II. Các lp template
Bên cnh hàm template, ngôn ng C++ còn trang b thêm lp template, lp này cũng mang đy đ ý
tng ca hàm template. Các lp template đc gi là các kiu có tham s (parameterized types) bi vì
chúng đòi hi mt hoc nhiu tham s đ mô t làm th nào tùy chnh mt lp template chung đ to thành
mt lp template c th.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
162
Chúng ta cài đt mt lp Stack, thông thng chúng ta phi đnh nghƿa trc mt kiu d liu cho tng
phn t ca stack. Nhng điu này ch mang li s trong sáng cho mt chng trình và không gii quyt
đc vn đ tng quát. Do đó chúng ta đnh nghƿa lp template Stack.
Ví d 9.3:
File TSTACK.H
:
1: //TSTACK.H
2: //Lp template Stack
3: #ifndef TSTACK_H
4: #define TSTACK_H
5:
6: #include <iostream.h>
7:
8: template<class T>
9: class Stack
10: {
11: private:
12: int Size; //Kích thước stack
13: int Top;
14: T *StackPtr;
15: public:
16: Stack(int = 10);
17: ~Stack()
18: {
19: delete [] StackPtr;
20: }
21: int Push(const T&);
22: int Pop(T&);
23: int IsEmpty() const
24: {
25: return Top == -1;
26: }
27: int IsFull() const
28: {
29: return Top == Size - 1;
30: }
31: };
32:
33: template<class T>
34: Stack<T>::Stack(int S)
35: {
36: Size = (S > 0 && S < 1000) ? S : 10;
37: Top = -1;
38: StackPtr = new T[Size];
39: }
40:
41: template<class T>
42: int Stack<T>::Push(const T &Item)
43: {
44: if (!IsFull())
45: {
46: StackPtr[++Top] = Item;
47: return 1;
48: }
49: return 0;
50: }
51:
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
163
52: template<class T>
53: int Stack<T>::Pop(T &PopValue)
54: {
55: if (!IsEmpty())
56: {
57: PopValue = StackPtr[Top--];
58: return 1;
59: }
60: return 0;
61: }
62:
63: #endif
File CT9_3.CPP:
1: //CT9_3.CPP
2: //Chương trình 9.3
3: #include "tstack.h"
4:
5: int main()
6: {
7: Stack<float> FloatStack(5);
8: float F = 1.1;
9: cout << "Pushing elements onto FloatStack" << endl;
10: while (FloatStack.Push(F))
11: {
12: cout << F << ' ';
13: F += 1.1;
14: }
15:cout << endl << "Stack is full. Cannot push " << F << endl
16: << endl << "Popping elements from FloatStack" << endl;
17: while (FloatStack.Pop(F))
18: cout << F << ' ';
19: cout << endl << "Stack is empty. Cannot pop" << endl;
20: Stack<int> IntStack;
21: int I = 1;
22: cout << endl << "Pushing elements onto IntStack" << endl;
23: while (IntStack.Push(I))
24: {
25: cout << I << ' ';
26: ++I ;
27: }
28:cout << endl << "Stack is full. Cannot push " << I << endl
29: << endl << "Popping elements from IntStack" << endl;
30: while (IntStack.Pop(I))
31: cout << I << ' ';
32: cout << endl << "Stack is empty. Cannot pop" << endl;
33: return 0;
34: }
Chúng ta chy ví d 9.3
, kt qu hình 9.3
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
164
Hình 9.3: Kt qu ca ví d 9.3
Hàm thành viên đnh nghƿa bên ngoài lp template bt đu vi phn đu là
template <class T>
Sau đó mi đnh nghƿa tng t mt đnh nghƿa hàm thng ngoi tr kiu phn t luôn luôn đc lit
kê tng quát nh tham s kiu T. Chng hn:
template<class T>
int Stack<T>::Push(const T &Item)
{
…………….
}
Ngôn ng C++ còn cho phép chúng ta to ra các lp template linh đng hn bng cách cho phép thay
đi giá tr ca các thành viên d liu bên trong lp. Khi đó lp có dng ca mt hàm vi tham s hình thc.
BÀI TP
Bài 1: Vit hàm template tr v giá tr trung bình ca mt mng, các tham s hình thc ca hàm này là
tên mng và kích thc mng.
Bài 2: Cài đt hàng đi template.
Bài 3: Cài đt lp template dùng cho cây nh phân tìm kim (BST).
Bài 4: Cài đt lp template cho vector đ qun lý vector các thành phn có kiu bt k.
Bài 5: Vit hàm template đ sp xp kiu d liu bt k.
Bài 6: Trong C++, phép toán new đc dùng đ cp phát b nh, khi không cp phát đc con tr
giá tr NULL. Hãy cài đt li các lp Matrix và Vector trong đó có b sung thêm thành viên là lp exception
vi tên gi là Memory đ kim tra vic cp phát này.
Giáo trình môn Lp trình hng đi tng Trang
Biên son: Lê Th M Hnh
165
TÀI LIU THAM KHO

[1] Lp trình hng đi tng C++ ca Nguyn Thanh Thu
[2] Lp trình hng đi tng C++ ca Trn Vĕn Lĕng
[3] C++ K thut và ng dng – Scott Robert Ladd
[4] Ngôn ng lp trình C và C++
[5] Bài tp Lp trình hng đi tng - Nguyn Thanh Thu
[6] Introduction to Object-Oriented Programming Using C++ - Peter Müller
[7] ..
| 1/165

Preview text:

Đ I H C ĐÀ NẴNG TR NG Đ I H C K THU T
KHOA CÔNG NGH THÔNG TIN - ĐI N T VI N THÔNG GIÁO TRÌNH MÔN H C
LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG BIÊN SO N: LÊ TH M H NH ĐÀ N NG, 09/2002
Giáo trình môn L p trình h ng đ i t ng Trang 2 M C L C CH
NG 1: GI I THI U V L P TRÌNH H NG Đ I T
NG.......................... 5 I. L P TRÌNH H NG Đ I T
NG (OOP) LÀ GÌ ? .............................................. 5 I.1.
L p trình tuy n tính ............................................................................................ 5 I.2.
L p trình c u trúc................................................................................................ 5 I.3. Sự tr u t
ng hóa d li u................................................................................... 6 I.4. L p trình h ng đ i t
ng ................................................................................. 6
II. M T S KHÁI NI M M I TRONG L P TRÌNH H NG Đ I T NG........... 8 II.1.
Sự đóng gói (Encapsulation) .............................................................................. 8 II.2.
Tính k th a (Inheritance) .................................................................................. 9 II.3.
Tính đa hình (Polymorphism) .......................................................................... 10
III. CÁC NGÔN NG VÀ VÀI NG D NG C A OOP............................................ 11 CH
NG 2: CÁC M R NG C A C++ ...................................................................... 12 I.
L CH S C A C++ ................................................................................................. 12
II. CÁC M R NG C A C++..................................................................................... 12 II.1.
Các t khóa m i c a C++................................................................................. 12 II.2.
Cách ghi chú thích ............................................................................................ 12 II.3.
Dòng nh p/xu t chu n...................................................................................... 13 II.4.
Cách chuy n đ i ki u d li u ........................................................................... 14 II.5.
V trí khai báo bi n ........................................................................................... 14 II.6.
Các bi n const................................................................................................... 15 II.7.
V struct, union và enum.................................................................................. 16 II.8.
Toán t đ nh ph m vi ....................................................................................... 16 II.9.
Toán t new và delete....................................................................................... 17
II.10. Hàm inline ........................................................................................................ 23
II.11. Các giá tr tham s m c đ nh ............................................................................ 24
II.12. Phép tham chi u ............................................................................................... 25
II.13. Phép đa nĕng hóa (Overloading) ...................................................................... 29 CH NG 3: L P VÀ Đ I T
NG .............................................................................. 39 I.
D N NH P .............................................................................................................. 39 II. CÀI Đ T M T KI U DO NG
I DÙNG Đ NH NGHƾA V I M T STRUCT. 39
III. CÀI Đ T M T KI U D LI U TR U T
NG V I M T L P...................... 41
IV. PH M VI L P VÀ TRUY C P CÁC THÀNH VIÊN L P .................................. 45
V. ĐI U KHI N TRUY C P T I CÁC THÀNH VIÊN ............................................ 47
VI. CÁC HÀM TRUY C P VÀ CÁC HÀM TI N ÍCH............................................... 48 VII. KH I Đ NG CÁC Đ I T
NG C A L P : CONSTRUCTOR......................... 49
VIII.S D NG DESTRUCTOR..................................................................................... 51
IX. KHI NÀO CÁC CONSTRUTOR VÀ DESTRUCTOR Đ C G I ? .................. 53
X. S D NG CÁC THÀNH VIÊN D LI U VÀ CÁC HÀM THÀNH VIÊN ........ 54
XI. TR V M T THAM CHI U T I M T THÀNH VIÊN D LI U PRIVATE.. 57
XII. PHÉP GÁN B I TOÁN T SAO CHÉP THÀNH VIÊN M C Đ NH ................. 59 XIII.CÁC Đ I T
NG H NG VÀ CÁC HÀMTHÀNH VIÊN CONST..................... 60
XIV.L P NH LÀ CÁC THÀNH VIÊN C A CÁC L P KHÁC ............................... 64
XV. CÁC HÀM VÀ CÁC L P FRIEND........................................................................ 67
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 3
XVI.CON TR THIS ...................................................................................................... 68 XVII.CÁC Đ I T NG Đ
C C P PHÁT Đ NG ................................................... 71
XVIII.CÁC THÀNH VIÊN TƾNH C A L P................................................................. 72 CH
NG 4: ĐA NĔNG HÓA TOÁN T ...................................................................... 76 I.
D N NH P .............................................................................................................. 76
II. CÁC NGUYÊN T C C B N C A ĐA NĔNG HÓA TOÁN T ...................... 76
III. CÁC GI I H N C A ĐA NĔNG HÓA TOÁN T .............................................. 76
IV. CÁC HÀM TOÁN T CÓ TH LÀ CÁC THÀNH VIÊN C A L P HO C
KHÔNG LÀ CÁC THÀNH VIÊN........................................................................... 77
V. ĐA NĔNG HOÁ CÁC TOÁN T HAI NGÔI ....................................................... 80
VI. ĐA NĔNG HÓA CÁC TOÁN T M T NGÔI ..................................................... 87
VII. ĐA NĔNG HÓA M T S TOÁN T Đ C BI T ................................................ 90
VII.1.Toán t [] ............................................................................................................ 91
VII.2.Toán t () ............................................................................................................ 92
VIII.TOÁN T CHUY N Đ I KI U............................................................................ 94
IX. TOÁN T NEW VÀ DELETE................................................................................ 95
IX.1.Đa nĕng hóa toán t new và delete toàn c c........................................................ 96
IX.2.Đa nĕng hóa toán t new và delete cho m t l p .................................................. 97
X. ĐA NĔNG HÓA CÁC TOÁN T CHÈN DÒNG << VÀ TRÍCH DÒNG >> ...... 98 XI. M T S VÍ D
....................................................................................................... 99
XI.1.L p String............................................................................................................. 99
XI.2.L p Date............................................................................................................. 103 CH
NG 5: TÍNH K TH A ...................................................................................... 107 I.
D N NH P ............................................................................................................ 107
II. K TH A Đ N ..................................................................................................... 107
II.1.Các l p c s và các l p d n xu t ....................................................................... 107
II.2.Các thành viên protected...................................................................................... 109
II.3.Ép ki u các con tr l p c s t i các con tr l p d n xu t.................................. 109
II.4.Đ nh nghƿa l i các thành viên l p c s trong m t l p d n xu t:........................ 113
II.5.Các l p c s public, protected và private........................................................... 113
II.6.Các contructor và destructor l p d n xu t ........................................................... 113
II.7.Chuy n đ i ng m đ nh đ i t ng l p d n xu t sang đ i t ng l p c s ........... 116
III. ĐA K TH A (MULTIPLE INHERITANCE)..................................................... 116
IV. CÁC L P C S O (VIRTUAL BASE CLASSES) ......................................... 119 CH
NG 6: TÍNH ĐA HÌNH ....................................................................................... 122 I.
D N NH P ............................................................................................................ 122 II. PH
NG TH C O (VIRTUAL FUNCTION) .................................................. 122 III. L P TR U T
NG (ABSTRACT CLASS) ....................................................... 125
IV. CÁC THÀNH VIÊN O C A M T L P............................................................ 127
IV.1.Toán t o........................................................................................................... 127
IV.2.Có constructor và destructor o hay không? ...................................................... 129 CH NG 7: THI T K CH NG TRÌNH THEO H NG Đ I T NG ......... 132 I.
D N NH P ............................................................................................................ 132
II. CÁC GIAI ĐO N PHÁT TRI N H TH NG..................................................... 132
III. CÁCH TÌM L P .................................................................................................... 133 IV. CÁC B C C N THI T Đ THI T K CH
NG TRÌNH ............................. 133
V. CÁC VÍ D ............................................................................................................ 134
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 4 CH
NG 8: CÁC D NG NH P/XU T...................................................................... 143 I.
D N NH P ............................................................................................................ 143
II. CÁC DÒNG(STREAMS) ...................................................................................... 143
II.1.Các file header c a th vi n iostream.................................................................. 143 II.2.Các l p và các đ i t
ng c a dòng nh p/xu t ..................................................... 144
III. DÒNG XU T......................................................................................................... 145
III.1.Toán t chèn dòng .............................................................................................. 145
III.2.N i các toán t chèn dòng và trích dòng............................................................ 146
III.3.Xu t ký tự v i hàm thành viên put(); N i v i nhau hàm put() .......................... 147
IV. DÒNG NH P ......................................................................................................... 148
IV.1.Toán t trích dòng: ............................................................................................. 148
IV.2.Các hàm thành viên get() và getline() ................................................................ 149
IV.3.Các hàm thành viên khác c a istream ................................................................ 151
IV.4.Nh p/xu t ki u an toàn....................................................................................... 151
V. NH P/XU T KHÔNG Đ NH D NG V I READ(),GCOUNT() VÀ WRITE() 151
VI. DÒNG NH P/ XU T FILE .................................................................................. 152
VI.1.Nh p/xu t file vĕn b n ....................................................................................... 154 CH
NG 9: HÀM VÀ L P TEMPLATE................................................................... 159 I.
CÁC HÀM TEMPLATE ........................................................................................ 159
II. CÁC L P TEMPLATE........................................................................................... 161
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 5 CHƯƠNG 1
GI I THI U V L P TRÌNH H NG Đ I T NG I. L P TRÌNH H NG Đ I T NG (OOP) LÀ GÌ ? L p trình h ng đ i t
ng (Object-Oriented Programming, vi t t t là OOP) là m t ph ng pháp m i trên b c đ
ng ti n hóa c a vi c l p trình máy tính, nh m làm cho ch
ng trình tr nên linh ho t, tin c y
và d phát tri n. Tuy nhiên đ hi u đ
c OOP là gì, chúng ta hãy b t đ u t l ch s c a quá trình l p trình –
xem xét OOP đã ti n hóa nh th nào.
I.1. L p trình tuy n tính Máy tính đ u tiên đ
c l p trình b ng mã nh phân, s d ng các công t t c khí đ n p ch ng trình.
Cùng v i sự xu t hi n c a các thi t b l u tr l n và b nh máy tính có dung l ng l n nên các ngôn ng
l p trình c p cao đ u tiên đ
c đ a vào s d ng . Thay vì ph i suy nghƿ trên m t dãy các bit và byte, l p
trình viên có th vi t m t lo t l nh g n v i ti ng Anh và sau đó ch
ng trình d ch thành ngôn ng máy.
Các ngôn ng l p trình c p cao đ u tiên đ c thi t k đ l p các ch
ng trình làm các công vi c t ng
đ i đ n gi n nh tính toán. Các ch ng trình ban đ u ch y u liên quan đ n tính toán và không đòi h i gì
nhi u ngôn ng l p trình. H n n a ph n l n các ch ng trình này t ng đ i ng n, th ng ít h n 100 dòng.
Khi kh nĕng c a máy tính tĕng lên thì kh nĕng đ tri n khai các ch
ng trình ph c t p h n cũng tĕng
lên. Các ngôn ng l p trình ngày tr
c không còn thích h p đ i v i vi c l p trình đòi h i cao h n. Các ph
ng ti n c n thi t đ s d ng l i các ph n mã ch
ng trình đã vi t h u nh không có trong ngôn ng l p
trình tuy n tính. Th t ra, m t đo n l nh th ng ph i đ
c chép l p l i m i khi chúng ta dùng trong nhi u ch ng trình do đó ch
ng trình dài dòng, logic c a ch ng trình khó hi u. Ch ng trình đ c đi u khi n
đ nh y đ n nhi u ch mà th ng không có sự gi i thích rõ ràng, làm th nào đ ch ng trình đ n ch c n thi t ho c t i sao nh v y.
Ngôn ng l p trình tuy n tính không có kh nĕng ki m soát ph m vi nhìn th y c a các d li u. M i d li u trong ch
ng trình đ u là d li u toàn c c nghƿa là chúng có th b s a đ i b t kỳ ph n nào c a ch
ng trình. Vi c dò tìm các thay đ i không mong mu n đó c a các ph n t d li u trong m t dãy mã l nh
dài và vòng vèo đã t ng làm cho các l p trình viên r t m t th i gian.
I.2. L p trình c u trúc
Rõ ràng là các ngôn ng m i v i các tính nĕng m i c n ph i đ
c phát tri n đ có th t o ra các ng
d ng tinh vi h n. Vào cu i các nĕm trong 1960 và 1970, ngôn ng l p trình có c u trúc ra đ i. Các ch ng trình có c u trúc đ
c t ch c theo các công vi c mà chúng thực hi n. V b n ch t, ch
ng trình chia nh thành các ch
ng trình con riêng r (còn g i là hàm hay th t c)
thực hi n các công vi c r i r c trong quá trình l n h n, ph c t p h n. Các hàm này đ c gi càng đ c l p
v i nhau càng nhi u càng t t, m i hàm có d li u và logic riêng.Thông tin đ c chuy n giao gi a các hàm
thông qua các tham s , các hàm có th có các bi n c c b mà không m t ai n m bên ngoài ph m vi c a hàm l i có th truy xu t đ
c chúng. Nh v y, các hàm có th đ c xem là các ch ng trình con đ c đ t chung
v i nhau đ xây dựng nên m t ng d ng.
M c tiêu là làm sao cho vi c tri n khai các ph n m m d dàng h n đ i v i các l p trình viên mà v n c i thi n đ
c tính tin c y và d b o qu n ch ng trình. M t ch ng trình có c u trúc đ c hình thành b ng
cách bẻ gãy các ch c nĕng c b n c a ch
ng trình thành các m nh nh mà sau đó tr thành các hàm. B ng
cách cô l p các công vi c vào trong các hàm, ch
ng trình có c u trúc có th làm gi m kh nĕng c a m t hàm này nh h
ng đ n m t hàm khác. Vi c này cũng làm cho vi c tách các v n đ tr nên d dàng h n. Sự
gói g n này cho phép chúng ta có th vi t các ch
ng trình sáng s a h n và gi đ c đi u khi n trên t ng
hàm. Các bi n toàn c c không còn n a và đ
c thay th b ng các tham s và bi n c c b có ph m vi nh
h n và d ki m soát h n. Cách t ch c t t h n này nói lên r ng chúng ta có kh nĕng qu n lý logic c a c u trúc ch
ng trình, làm cho vi c tri n khai và b o d ng ch
ng trình nhanh h n và h u hi n h n và hi u qu h n.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 6 M t khái ni m l n đã đ
c đ a ra trong l p trình có c u trúc là sự tr u t
ng hóa (Abstraction). Sự tr u t
ng hóa có th xem nh kh nĕng quan sát m t sự vi c mà không c n xem xét đ n các chi ti t bên trong c a nó. Trong m t ch
ng trình có c u trúc, chúng ta ch c n bi t m t hàm đã cho có th làm đ c m t
công vi c c th gì là đ . Còn làm th nào mà công vi c đó l i thực hi n đ
c là không quan tr ng, ch ng nào hàm còn tin c y đ
c thì còn có th dùng nó mà không c n ph i bi t nó thực hi n đúng đ n ch c nĕng
c a mình nh th nào. Đi u này g i là sự tr u t
ng hóa theo ch c nĕng (Functional abstraction) và là
n n t ng c a l p trình có c u trúc.
Ngày nay, các k thu t thi t k và l p trình có c u trúc đ
c s r ng rãi. G n nh m i ngôn ng l p trình đ u có các ph
ng ti n c n thi t đ cho phép l p trình có c u trúc. Ch
ng trình có c u trúc d vi t, d b o d ng h n các ch ng trình không c u trúc.
Sự nâng c p nh v y cho các ki u d li u trong các ng d ng mà các l p trình viên đang vi t cũng đang
ti p t c di n ra. Khi đ ph c t p c a m t ch
ng trình tĕng lên, sự ph thu c c a nó vào các ki u d li u c
b n mà nó x lý cũng tĕng theo. V n đ tr rõ ràng là c u trúc d li u trong ch ng trình quan tr ng ch ng
kém gì các phép toán thực hi n trên chúng. Đi u này càng tr rõ ràng h n khi kích th c c a ch ng trình
càng tĕng. Các ki u d li u đ
c x lý trong nhi u hàm khác nhau bên trong m t ch ng trình có c u trúc.
Khi có sự thay đ i trong các d li u này thì cũng c n ph i thực hi n c các thay đ i m i n i có các thao tác
tác đ ng trên chúng. Đây có th là m t công vi c t n th i gian và kém hi u qu đ i v i các ch ng trình có
hàng ngàn dòng l nh và hàng trĕm hàm tr lên.
M t y u đi m n a c a vi c l p trình có c u trúc là khi có nhi u l p trình viên làm vi c theo nhóm cùng
m t ng d ng nào đó. Trong m t ch
ng trình có c u trúc, các l p trình viên đ c phân công vi t m t t p
h p các hàm và các ki u d li u. Vì có nhi u l p trình viên khác nhau qu n lý các hàm riêng, có liên quan
đ n các ki u d li u dùng chung nên các thay đ i mà l p trình viên t o ra trên m t ph n t d li u s làm nh h
ng đ n công vi c c a t t c các ng
i còn l i trong nhóm. M c dù trong b i c nh làm vi c theo nhóm, vi c vi t các ch
ng trình có c u trúc thì d dàng h n nh ng sai sót trong vi c trao đ i thông tin gi a các
thành viên trong nhóm có th d n t i h u qu là m t r t nhi u th i gian đ s a ch a ch ơng trình. I.3. Sự tr u t ng hóa d li u Sự tr u t
ng hóa d li u (Data abstraction) tác đ ng trên các d li u cũng t ng tự nh sự tr u t
ng hóa theo ch c nĕng. Khi có tr u t
ng hóa d li u, các c u trúc d li u và các ph n t có th đ c s
d ng mà không c n b n tâm đ n các chi ti t c th . Ch ng h n nh các s d u ch m đ ng đã đ c tr u t
ng hóa trong t t c các ngôn ng l p trình, Chúng ta không c n quan tâm cách bi u di n nh phân chính
xác nào cho s d u ch m đ ng khi gán m t giá tr , cũng không c n bi t tính b t th ng c a phép nhân nh
phân khi nhân các giá tr d u ch m đ ng. Đi u quan tr ng là các s d u ch m đ ng ho t đ ng đúng đ n và hi u đ c. Sự tr u t
ng hóa d li u giúp chúng ta không ph i b n tâm v các chi ti t không c n thi t. N u l p
trình viên ph i hi u bi t v t t c các khía c nh c a v n đ , m i lúc và v t t c các hàm c a ch ng trình thì ch ít hàm m i đ c vi t ra, may m n thay tr u t
ng hóa theo d li u đã t n t i s n trong m i ngôn ng
l p trình đ i v i các d li u ph c t p nh s d u ch m đ ng. Tuy nhiên ch m i g n đây, ng i ta m i phát
tri n các ngôn ng cho phép chúng ta đ nh nghƿa các ki u d li u tr u t ng riêng. I.4. L p trình h ng đ i t ng Khái ni m h ng đ i t ng đ
c xây dựng trên n n t ng c a khái ni m l p trình có c u trúc và sự tr u t
ng hóa d li u. Sự thay đ i cĕn b n ch , m t ch ng trình h ng đ i t ng đ c thi t k xoay quanh
d li u mà chúng ta có th làm vi c trên đó, h n là theo b n thân ch c nĕng c a ch ng trình. Đi u này hoàn
toàn tự nhiên m t khi chúng ta hi u r ng m c tiêu c a ch
ng trình là x lý d li u. Suy cho cùng, công vi c
mà máy tính thực hi n v n th ng đ
c g i là x lý d li u. D li u và thao tác liên k t v i nhau m t m c
c b n (còn có th g i là m c th p), m i th đ u đòi h i th kia có m c tiêu c th , các ch ng trình h ng đ i t ng làm t ng minh m i quan h này. L p trình h ng đ i t
ng (Object Oriented Programming - g i t t là OOP) hay chi ti t h n là Lập trình
định hướng đối tượng, chính là ph ng pháp l p trình l y đ i t ng làm n n t ng đ xây dựng thu t gi i, xây
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 7 dựng ch
ng trình. Thực ch t đây không ph i là m t ph
ng pháp m i mà là m t cách nhìn m i trong vi c
l p trình. Đ phân bi t, v i ph
ng pháp l p trình theo ki u c u trúc mà chúng ta quen thu c tr c đây, hay còn g i là ph ng pháp l p trình h
ng th t c (Procedure-Oriented Programming), ng i l p trình phân
tích m t nhi m v l n thành nhi u công vi c nh h n, sau đó d n d n chi ti t, c th hoá đ đ c các v n đ
đ n gi n, đ tìm ra cách gi i quy t v n đ d i d ng nh ng thu t gi i c th rõ ràng qua đó d dàng minh
ho b ng ngôn ng gi i thu t (hay còn g i các thu t gi i này là các ch
ng trình con). Cách th c phân tích
và thi t k nh v y chúng ta g i là nguyên lý l p trình t trên xu ng (top-down), đ th hi n quá trình suy
di n t cái chung cho đ n cái c th . Các ch
ng trình con là nh ng ch c nĕng đ c l p, sự ghép n i chúng l i v i nhau cho chúng ta m t h th ng ch
ng trình đ gi i quy t v n đ đ t ra. Chính vì v y, cách th c phân tích m t h th ng l y ch ng trình con làm n n t ng, ch
ng trình con đóng vai trò trung tâm c a vi c l p trình, đ c hi u nh ph ng pháp l p trình h
g v th t c. Tuy nhiên, khi phân tích đ thi t k m t h th ng không nh t thi t ph i luôn luôn suy nghƿ theo h
ng “làm thế nào để giải quyết công việc”, chúng ta có th đ nh h ng t duy theo
phong cách “với một số đối tượng đã có, phải làm gì để giải quyết được công việc đặt ra” ho c phong phú
h n, “làm cái gì với một số đối tượng đã có đó”, t đó cũng có th gi i quy t đ c nh ng công vi c c th . V i ph
ng pháp phân tích trong đó đ i t
ng đóng vai trò trùng tâm c a vi c l p trình nh v y, ng i ta
g i là nguyên lý l p trình t d i lên (Bôttm-up). L p trình h ng đ i t
ng liên k t c u trúc d li u v i các thao tác, theo cách mà t t c th ng nghƿ v
th gi i quanh mình. Chúng ta th
ng g n m t s các ho t đ ng c th v i m t lo i ho t đ ng nào đó và đ t
các gi thi t c a mình trên các quan h đó.
Ví d 1.1: Đ d hình dùng h n, chúng ta th nhìn qua các công trình xây dựng hi n đ i, nh sân v n
đ ng có mái che hình vòng cung, nh ng ki n trúc th m mƿ v i đ ng nét hình cong. T t c nh ng s n ph m
đó xu t hi n cùng v i nh ng v t li u xây dựng. Ngày nay, không ch ch ng lên nhau nh ng viên g ch,
nh ng t ng đá đ t o nên nh ng qu n th ki n trúc (nh Tháp Chàm Nha Trang, Kim Tự Tháp,...), mà có th
v i bêtông, s t thép và không nhi u l m nh ng viên g ch, ng
i xây dựng cũng có th thi t k nh ng công
trình ki n trúc tuy t m , nh ng toà nhà hi n đ i. Chính các ch t li u xây dựng đã làm nh h ng ph ng
pháp xây dựng, ch t li u xây dựng và nguyên lý k t dính caá ch t li u đó l i v i nhau cho chúng ta m t đ i t
ng đ kh o sát, Ch t li u xây dựng và nguyên lý k t dính các ch t li u l i v i nhau đ c hi u theo nghƿa d li u và ch
ng trình con tác đ ng trên d li u đó.
Ví d 1.2: Chúng ta bi t r ng m t chi c xe có các bánh xe, di chuy n đ c và có th đ i h ng c a nó b ng cách quẹo tay lái. T
ng tự nh th , m t cái cây là m t lo i thực v t có thân g và lá. M t chi c xe
không ph i là m t cái cây, mà cái cây không ph i là m t chi c xe, chúng ta có th gi thi t r ng cái mà chúng ta có th làm đ
c v i m t chi c xe thì không th làm đ
c v i m t cái cây. Ch ng h n, th t là vô
nghƿa khi mu n lái m t cái cây, còn chi c xe thì l i ch ng l n thêm đ c khi chúng ta t i n c cho nó. L p trình h ng đ i t
ng cho phép chúng ta s d ng các quá trình suy nghƿ nh v y v i các khái ni m tr u t ng đ c s d ng trong các ch
ng trình máy tính. M t m u tin (record) nhân sự có th đ c đ c ra,
thay đ i và l u tr l i; còn s ph c thì có th đ
c dùng trong các tính toán. Tuy v y không th nào l i vi t
m t s ph c vào t p tin làm m u tin nhân sự và ng
c l i hai m u tin nhân sự l i không th c ng v i nhau
đ c. M t ch ng trình h ng đ i t ng s xác đ nh đ c đi m và hành vi c th c a các ki u d li u, đi u
đó cho phép chúng ta bi t m t cách chính xác r ng chúng ta có th có đ c nh ng gì các ki u d li u khác nhau.
Chúng ta còn có th t o ra các quan h gi a các ki u d li u t
ng tự nh ng khác nhau trong m t ch ng trình h ng đ i t ng. Ng i ta th
ng tự nhiên phân lo i ra m i th , th ng đ t m i liên h gi a
các khái ni m m i v i các khái ni m đã có, và th
ng có th thực hi n suy di n gi a chúng trên các quan h
đó. Hãy quan ni m th gi i theo ki u c u trúc cây, v i các m c xây dựng chi ti t h n k ti p nhau cho các th h sau so v i các th h tr c. Đây là ph
ng pháp hi u qu đ t ch c th gi i quanh chúng ta. Các ch ng trình h ng đ i t ng cũng làm vi c theo m t ph ng th c t
ng tự, trong đó chúng cho phép xây
dựng các các c c u d li u và thao tác m i dựa trên các c c u có s n, mang theo các tính nĕng c a các c
c u n n mà chúng dựa trên đó, trong khi v n thêm vào các tính nĕng m i.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 8 L p trình h ng đ i t
ng cho phép chúng ta t ch c d li u trong ch ng trình theo m t cách t ng tự
nh các nhà sinh h c t ch c các lo i thực v t khác nhau. Theo cách nói l p trình đ i t ng, xe h i, cây c i,
các s ph c, các quy n sách đ u đ
c g i là các l p (Class).
M t l p là m t b n m u mô t các thông tin c u trúc d li u, l n các thao tác h p l c a các ph n t d li u. Khi m t ph n t d li u đ
c khai báo là ph n t c a m t l p thì nó đ c g i là m t đ i t ng (Object). Các hàm đ
c đ nh nghƿa h p l trong m t l p đ c g i là các ph
ng th c (Method) và chúng
là các hàm duy nh t có th x lý d li u c a các đ i t
ng c a l p đó. M t thực th (Instance) là m t v t
th có thực bên trong b nh , thực ch t đó là m t đ i t ng (nghƿa là m t đ i t ng đ c c p phát vùng nh ). M i m t đ i t
ng có riêng cho mình m t b n sao các ph n t d li u c a l p còn g i là các bi n thực
th (Instance variable). Các ph
ng th c đ nh nghƿa trong m t l p có th đ c g i b i các đ i t ng c a l p đó. Đi u này đ
c g i là g i m t thông đi p (Message) cho đ i t
ng. Các thông đi p này ph thu c vào đ i t ng, ch đ i t
ng nào nh n thông đi p m i ph i làm vi c theo thông đi p đó. Các đ i t ng đ u
đ c l p v i nhau vì v y các thay đ i trên các bi n th hi n c a đ i t ng này không nh h ng gì trên các bi n th hi n c a các đ i t
ng khác và vi c g i thông đi p cho m t đ i t ng này không nh h ng gì đ n các đ i t ng khác. Nh v y, đ i t ng đ
c hi u theo nghƿa là m t thực th mà trong đó caá d li u và th t c tác
đ ng lên d li u đã đ c đóng gói l i v i nhau. Hay “đối tượng được đặc trưng bởi một số thao tác
(operation) và các thông tin (information) ghi nhơ sự tác động của caá thao tác này.

Ví d 1.3: Khi nghiên c v ngĕn x p (stack), ngoài các d li u vùng ch a ngĕn x p, đ nh c a
ngĕn x p, chúng ta ph i cài đ t kèm theo các thao tác nh kh i t o (creat) ngĕn x p, ki m tra ngĕn
x p r ng (empty), đ y (push) m t ph n t vào ngĕn x p, l y (pop) m t ph n t ra kh i ngĕn x p. Trên quan đi m l y đ i t
ng làm n n t ng, rõ ràng d li u và các thao tác trên d li u luôn g n bó
v i nhau, sự k t dính chúng chính là đ i t ng chúng ta c n kh o sát. Các thao tác trong đ i t ng đ c g i là các ph
ng th c hay hành vi c a đ i t ng đó. Ph ng th c và d li u c a đ i t
ng luôn tác đ ng l n nhau và có vai trò ngang nhau trong đ i t ng, Ph ng th c c a đ i t ng đ c qui đ nh b i d li u và ng c l i, d li u c a đ i t ng
đ c đ t tr ng b i các ph ng th c c a đ i t ng. Chính nh sự g n bó đó, chúng ta có th g i
cùng m t thông đi p đ n nh ng đ i t
ng khác nhau. Đi u này giúp ng i l p trình không ph i x lý trong ch
ng trình c a mình m t dãy các c u trúc đi u khi n tuỳ theo thông đi p nh n vào, mà ch ng trình đ
c x lý vào th i đi m thực hi n.
Tóm l i, so sánh l p trình c u trúc v i ch ng trình con làm n n t ng: Ch
ng trình = C u trúc d li u + Thu t gi i Trong l p trình h ng đ i t ng chúng ta có:
Đ i t ng = Ph ng th c + D li u
Đây chính là 2 quan đi m l p trình đang t n t i và phát tri n trong th gi i ngày nay.
II. M T S KHÁI NI M M I TRONG L P TRÌNH H NG Đ I T NG
Trong ph n này, chúng ta tìm hi u các khái ni m nh sự đóng gói, tính k th a và tính đa hình. Đây là
các khái ni m cĕn b n, là n n t ng t t ng c a l p trình h ng đ i t ng. Hi u đ c khái ni m này, chúng ta b
c đ u ti p c n v i phong cách l p trình m i, phong cách l p trình dựa vào đ i t ng làm n n t ng mà
trong đó quan đi m che d u thông tin thông qua s đóng gói là quan đi m trung tâm c a v n đ .
II.1. Sự đóng gói (Encapsulation)
Sự đóng gói là c ch ràng bu c d li u và thao tác trên d li u đó thành m t th th ng nh t, tránh đ c
các tác đ ng b t ng t bên ngoài. Th th ng nh t này g i là đ i t ng.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 9
Trong Objetc Oriented Software Engineering c a Ivar Jacibson, t t c các thông tin c a m t h th ng
đ nh h ng đ i t ng đ c l u tr bên trong đ i t ng c a nó và ch có th hành đ ng khi các đ i t ng đó
đ c ra l nh thực hi n các thao tác. Nh v t, sự đóng gói không ch đ n thu n là sự gom chung d li u và ch
ng trình vào trong m t kh i, chúng còn đ
c hi u theo nghƿa là sự đ ng nh t gi a d li u và các thao
tác tác đ ng lên d li u đó. Trong m t đ i t
ng, d li u hay thao tác hay c hai có th là riêng (private) ho c chung (public) c a
đ i t ng đó. Thao tác hay d li u riêng là thu c v đ i t ng đó ch đ c truy c p b i các thành ph n c a
đ i t ng, đi u này nghƿa là thao tác hay d li u riêng không th truy c p b i các ph n khác c a ch ng trình t n t i ngoài đ i t
ng. Khi thao tác hay d li u là chung, các ph n khác c a ch ng trình có th truy c p nó m c dù nó đ
c đ nh nghƿa trong m t đ i t
ng. Các thành ph n chung c a m t đ i t ng dùng đ
cung c p m t giao di n có đi u khi n cho các thành thành riêng c a đ i t ng. C ch đóng gói là ph
ng th c t t đ thực hi n c ch che d u thông tin so v i các ngôn ng l p trình c u trúc. II.2. Tính k th a (Inheritance)
Chúng ta có th xây dựng các l p m i t các l p cũ thông qua sự k th a. M t l p m i còn g i là l p
d n xu t (derived class), có th th a h ng d li u và các ph
ng th c c a l p c s (base class) ban đ u.
Trong l p này, có th b sung các thành ph n d li u và các ph
ng th c m i vào nh ng thành ph n d li u và các ph ng th c mà nó th a h
ng t l p c s . M i l p (k c l p d n xu t) có th có m t s l ng b t
kỳ các l p d n xu t. Qua c c u k th a này, d ng hình cây c a các l p đ
c hình thành. D ng cây c a các
l p trông gi ng nh các cây gia ph vì th các l p c s còn đ
c g i là l p cha (parent class) và các l p d n xu t đ
c g i là l p con (child class).
Ví d 1.2: Chúng ta s xây dựng m t t p các l p mô t cho th vi n các n ph m. Có hai ki u n ph m:
t p chí và sách. Chúng ta có th t o m t n ph m t ng quát b ng cách đ nh nghƿa các thành ph n d li u t
ng ng v i s trang, mã s tra c u, ngày tháng xu t b n, b n quy n và nhà xu t b n. Các n ph m có th
đ c l y ra, c t đi và đ c. Đó là các ph ng th c thực hi n trên m t n ph m. Ti p đó chúng ta đ nh nghƿa
hai l p d n xu t tên là t p chí và sách. T p chí có tên, s ký phát hành và ch a nhi u bài c a các tác gi khác
nhau . Các thành ph n d li u t ng ng v i các y u t này đ
c đ t vào đ nh nghƿa c a l p t p chí. T p chí cũng c n có m t ph
ng th c n a đó là đ t mua. Các thành ph n d li u xác đ nh cho sách s bao g m tên
c a (các) tác gi , lo i bìa (c ng hay m m) và s hi u ISBN c a nó. Nh v y chúng ta có th th y, sách và t p
chí có chung các đ c tr ng n ph m, trong khi v n có các thu c tính riêng c a chúng.
Hình 1.1: L p n ph m và các l p d n xu t c a nó. V i tính k th a, chúng ta
không ph i m t công xây dựng l i t
đ u các l p m i, ch c n b sung đ có đ
c trong các l p d n xu t các đ c tr ng c n thi t.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 10 II.3. Tính
đa hình (Polymorphism)
Đó là kh nĕng đ cho m t thông đi p có th thay đ i cách thực hi n c a nó theo l p c th c a đ i t
ng nh n thông đi p. Khi m t l p d n xu t đ
c t o ra, nó có th thay đ i cách thực hi n các ph ng th c nào đó mà nó th a h
ng t l p c s c a nó. M t thông đi p khi đ c g i đ n m t đ i t ng c a l p c s , s dùng ph
ng th c đã đ nh nghƿa cho nó trong l p c s . N u m t l p d n xu t đ nh nghƿa l i m t ph ng th c th a h
ng t l p c s c a nó thì m t thông đi p có cùng tên v i ph ng th c này, khi đ c g i t i m t đ i t ng c a l p d n xu t s g i ph
ng th c đã đ nh nghƿa cho l p d n xu t.
Nh v y đa hình là kh nĕng cho phép g i cùng m t thông đi p đ n nh ng đ i t ng khác nhau có cùng
chung m t đ c đi m, nói cách khác thông đi p đ
c g i đi không c n bi t thực th nh n thu c l p nào, ch
bi t r ng t p h p các thực th nh n có chung m t tính ch t nào đó. Ch ng h n, thông đi p “vẽ hình” đ c g i đ n c hai đ i t
ng hình h p và hình tròn. Trong hai đ i t ng này đ u có chung ph ng th c v hình,
tuy nhiên tuỳ theo th i đi m mà đ i t ng nh n thông đi p, hình t ng ng s đ c v lên.
Trong các ngôn ng l p trình OOP, tính đa hình th hi n qua kh nĕng cho phép mô t nh ng ph ng
th c có tên gi ng nhau trong các l p khác nhau. Đ c đi m này giúp ng
i l p trình không ph i vi t nh ng c u trúc đi u khi n r m rà trong ch
ng trình, các kh nĕng khác nhau c a thông đi p ch thực sự đòi h i khi ch ng trình thực hi n.
Ví d 1.3: Xét l i ví d 1.2, chúng ta th y r ng c t p chí và và sách đ u ph i có kh nĕng l y ra. Tuy nhiên ph
ng pháp l y ra cho t p chí có khác so v i ph
ng pháp l y ra cho sách, m c dù k t qu cu i cùng
gi ng nhau. Khi ph i l y ra t p chí, thì ph i s d ng ph
ng pháp l y ra riêng cho t p chí (dựa trên m t b n
tra c u) nh ng khi l y ra sách thì l i ph i s d ng ph
ng pháp l y ra riêng cho sách (dựa trên h th ng
phi u l u tr ). Tính đa hình cho phép chúng ta xác đ nh m t ph
ng th c đ l y ra m t t p chí hay m t cu n
sách. Khi l y ra m t t p chí nó s dùng ph
ng th c l y ra dành riêng cho t p chí, còn khi l y ra m t cu n sách thì nó s d ng ph ng th c l y ra t
ng ng v i sách. K t qu là ch c n m t tên ph ng th c duy nh t
đ c dùng cho c hai công vi c ti n hành trên hai l p d n xu t có liên quan, m c dù vi c thực hi n c a ph
ng th c đó thay đ i tùy theo t ng l p.
Tính đa hình dựa trên sự n i k t (Binding), đó là quá trình g n m t ph
ng th c v i m t hàm thực sự. Khi các ph ng th c ki u đa hình đ
c s d ng thì trình biên d ch ch a th xác đ nh hàm nào t ng ng v i ph ng th c nào s đ c g i. Hàm c th đ
c g i s tuỳ thu c vào vi c ph n t nh n thông đi p lúc đó là
thu c l p nào, do đó hàm đ c g i ch xác đ nh đ c vào lúc ch
ng trình ch y. Đi u này g i là sự k t n i
mu n (Late binding) hay k t n i lúc ch y
(Runtime binding) vì nó x y ra khi ch ng trình đang thực hi n.
Hình 1.2: Minh h a tính đa hình đ i v i
l p n ph m và các l p d n xu t c a nó.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 11
III. CÁC NGÔN NG VÀ VÀI NG D NG C A OOP Xu t phát t t t
ng c a ngôn ng SIMULA67, trung tâm nghiên c u Palo Alto (PARC) c a hãng
XEROR đã t p trung 10 nĕm nghiên c u đ hoàn thi n ngôn ng OOP đ u tiên v i tên g i là Smalltalk. Sau
đó các ngôn ng OOP l n l t ra đ i nh Eiffel, Clos, Loops, Flavors, Object Pascal, Object C, C++, Delphi, Java…
Chính XEROR trên c s ngôn ng OOP đã đ ra t t ng giao di n bi u t ng trên màn hình (icon
base screen interface), k t đó Apple Macintosh cũng nh Microsoft Windows phát tri n giao di n đ h a
nh ngày nay. Trong Microsoft Windows, t t ng OOP đ
c th hi n m t cách rõ nét nh t đó là "chúng ta click vào đ i t ng", m i đ i t
ng có th là control menu, control menu box, menu bar, scroll bar, button,
minimize box, maximize box, … s đáp ng công vi c tùy theo đ c tính c a đ i t ng. Turbo Vision c a
hãng Borland là m t ng d ng OOP tuy t v i, giúp l p trình viên không quan tâm đ n chi ti t c a ch ng
trình gia di n mà ch c n thực hi n các n i dung chính c a v n đ .
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 12 CHƯƠNG 2 CÁC M R NG C A C++ I. L CH S C A C++
Vào nh ng nĕm đ u th p niên 1980, ng
i dùng bi t C++ v i tên g i "C with Classes" đ c mô t trong
hai bài báo c a Bjarne Stroustrup (thu c AT&T Bell Laboratories) v i nhan đ "Classes: An Abstract Data
Type Facility for the C Language" và "Adding Classes to C : AnExercise in Language Evolution". Trong
công trình này, tác gi đã đ xu t khái ni m l p, b sung vi c ki m tra ki u tham s c a hàm, các chuy n đ i
ki u và m t s m r ng khác vào ngôn ng C. Bjarne Stroustrup nghiên c u m r ng ngôn ng C nh m đ t
đ n m t ngôn ng mô ph ng (simulation language) v i nh ng tính nĕng h ng đ i t ng.
Trong nĕm 1983, 1984, ngôn ng "C with Classes" đ
c thi t k l i, m r ng h n r i m t trình biên
d ch ra đ i. Và chính t đó, xu t hi n tên g i "C++". Bjarne Stroustrup mô t ngôn ng C++ l n đ u tiên
trong bài báo có nhan đ "Data Abstraction in C". Sau m t vài hi u ch nh C++ đ c công b r ng rãi trong
quy n "The C++ Programming Language" c a Bjarne Stroustrup xu t hi n đánh d u sự hi n di n thực sự c a C++, ng
i l p tình chuyên nghi p t đây đã có m t ngôn ng đ m nh cho các d án thực ti n c a mình.
V thực ch t C++ gi ng nh C nh ng b sung thêm m t s m r ng quan tr ng, đ c bi t là ý t ng v
đ i t ng, l p trình đ nh h ng đ i t ng.Th t ra các ý t ng v c u trúc trong C++ đã xu t phát vào các
nĕm 1970 t Simula 70 và Algol 68. Các ngôn ng này đã đ a ra các khái ni m v l p và đ n th . Ada là
m t ngôn ng phát tri n t đó, nh ng C++ đã kh ng đ nh vai trò thực sự c a mình. II. CÁC M R NG C A C++ II.1. Các t khóa m i c a C++
Đ b sung các tính nĕng m i vào C, m t s t khóa (keyword) m i đã đ c đ a vào C++ ngoài các t khóa có trong C. Các ch
ng trình b ng C nào s d ng các tên trùng v i các t khóa c n ph i thay đ i tr c khi ch ng trình đ
c d ch l i b ng C++. Các t khóa m i này là : asm catch class delete friend inline new operator private protected public template this throw try virtual
II.2. Cách ghi chú thích
C++ ch p nh n hai ki u chú thích. Các l p trình viên b ng C đã quen v i cách chú thích b ng /*…*/.
Trình biên d ch s b qua m i th n m gi a /*…*/. Ví d 2.1: Trong ch ng trình sau : #include int main() { int I;
for(I = 0; I < 10 ; ++ I) // 0 - 9 cout<// In ra return 0; }
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 13
M i th n m gi a /*…*/ t dòng 1 đ n dòng 3 đ u đ c ch ng trình b qua. Ch ng trình này còn
minh h a cách chú thích th hai. Đó là cách chú thích b t đ u b ng // dòng 8 và dòng 9. Chúng ta ch y ví d 2.1, k t qu hình 2.1.
Hình 2.1: K t qu c a ví d 2.1
Nói chung, ki u chú thích /*…*/ đ
c dùng cho các kh i chú thích l n g m nhi u dòng, còn ki u //
đ c dùng cho các chú thích m t dòng. II.3. Dòng nh p/xu t chu n Trong ch ng trình C, chúng ta th
ng s d ng các hàm nh p/xu t d li u là printf() và scanf(). Trong
C++ chúng ta có th dùng dòng nh p/xu t chu n (standard input/output stream) đ nh p/xu t d li u thông qua hai bi n đ i t
ng c a dòng (stream object) là cout cin. Ví d 2.2: Ch
ng trình nh p vào hai s . Tính t ng và hi u c a hai s v a nh p. //Chuong trinh 2.2 #include int main() { int X, Y;
cout<< "Nhap vao mot so X:"; cin>>X;
cout<< "Nhap vao mot so Y:"; cin>>Y;
cout<<"Tong cua chung:"<
cout<<"Hieu cua chung:"< return 0; }
Đ thực hi n dòng xu t chúng ta s d ng bi n cout (console output) k t h p v i toán t chèn (insertion
operator) << nh các dòng 5, 7, 9 và 10. Còn dòng nh p chúng ta s d ng bi n cin (console input) k t h p
v i toán t trích (extraction operator) >> nh các dòng 6 và 8. Khi s d ng cout hay cin, chúng ta ph i kéo
file iostream.h nh dòng 1. Chúng ta s tìm hi u k v dòng nh p/xu t ch
ng 8. Chúng ta ch y ví d 2.2 , k t qu hình 2.2.
Hình 2.2: K t qu c a ví d 2.2
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 14
Hình 2.3: Dòng nh p/xu t d li u II.4. Cách
chuy n đ i ki u d li u
Hình th c chuy n đ i ki u trong C t
ng đ i t i nghƿa, vì v y C++ trang b thêm m t cách chuy n đ i
ki u gi ng nh m t l nh g i hàm. Ví d 2.3: #include int main() { int X = 200;
long Y = (long) X; //Chuyen doi kieu theo cach cua C
long Z = long(X); //Chuyen doi kieu theo cach moi cua C++ cout<< "X = "< cout<< "Y = "< cout<< "Z = "< return 0; }
Chúng ta ch y ví d 2.3 , k t qu hình 2.4.
Hình 2.4: K t qu c a ví d 2.3
II.5. V trí khai báo bi n Trong ch
ng trình C đòi h i t t c các khai báo bên trong m t ph m vi cho tr c ph i đ c đ t ngay
đ u c a ph m vi đó. Đi u này có nghƿa là t t c các khai báo toàn c c ph i đ t tr c t t c các hàm và các khai báo c c b ph i đ c ti n hành tr
c t t c các l nh thực hi n. Ng
c l i C++ cho phép chúng ta khai
báo linh ho t b t kỳ v trí nào trong m t ph m vi cho tr
c (không nh t thi t ph i ngay đ u c a ph m vi),
chúng ta xen k vi c khai báo d li u v i các câu l nh thực hi n. Ví d 2.4: Ch
ng trình mô ph ng m t máy tính đ n gi n 1: #include 2: int main() 3: { 4: int X;
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 15
5: cout<< "Nhap vao so thu nhat:"; 6: cin>>X; 7: int Y;
8: cout<< "Nhap vao so thu hai:"; 9: cin>>Y; 10: char Op;
11: cout<<"Nhap vao toan tu (+-*/):"; 12: cin>>Op; 13: switch(Op) 14: { 15: case ‘+’:
16: cout<<"Ket qua:"<17: break; 18: case ‘-’:
19: cout<<"Ket qua:"<20: break; 21: case ‘*’:
22: cout<<"Ket qua:"<23: break; 24: case ‘/’: 25: if (Y)
26: cout<<"Ket qua:"<27: else
28: cout<<"Khong the chia duoc!" <<"\n"; 9; 9; 29: break; 30: default :
31: cout<<"Khong hieu toan tu nay!"<<"\n"; 32: } 33: return 0; 34: } Trong ch
ng trình chúng ta xen kẻ khai báo bi n v i l nh thực hi n dòng 4 đ n dòng 12. Chúng ta
ch y ví d 2.4, k t qu hình 2.5.
Hình 2.5: K t qu c a ví d 2.4
Khi khai báo m t bi n trong ch
ng trình, bi n đó s có hi u lực trong ph m vi c a ch ng trình đó k
t v trí nó xu t hi n. Vì v y chúng ta không th s d ng m t bi n đ c khai báo bên d i nó. II.6. Các bi n const
Trong ANSI C, mu n đ nh nghƿa m t h ng có ki u nh t đ nh thì chúng ta dùng bi n const (vì n u dùng
#define thì t o ra các h ng không có ch a thông tin v ki u). Trong C++, các bi n const linh ho t h n m t cách đáng k :
C++ xem const cũng nh #define n u nh chúng ta mu n dùng h ng có tên trong ch ng trình. Chính
vì v y chúng ta có th dùng const đ quy đ nh kích th
c c a m t m ng nh đo n mã sau: const int ArraySize = 100; int X[ArraySize];
Khi khai báo m t bi n const trong C++ thì chúng ta ph i kh i t o m t giá tr ban đ u nh ng đ i v i
ANSI C thì không nh t thi t ph i làm nh v y (vì trình biên d ch ANSI C tự đ ng gán tr zero cho bi n const
n u chúng ta không kh i t o giá tr ban đ u cho nó).
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 16
Ph m vi c a các bi n const gi a ANSI C và C++ khác nhau. Trong ANSI C, các bi n const đ c khai
báo bên ngoài m i hàm thì chúng có ph m vi toàn c c, đi u này nghƿa là chúng có th nhìn th y c bên ngoài file mà chúng đ
c đ nh nghƿa, tr khi chúng đ
c khai báo là static. Nh ng trong C++, các bi n const đ
c hi u m c đ nh là static.
II.7. V struct, union và enum
Trong C++, các structunion thực sự các các ki u class. Tuy nhiên có sự thay đ i đ i v i C++. Đó là
tên c a structunion đ
c xem luôn là tên ki u gi ng nh khai báo b ng l nh typedef v y.
Trong C, chúng ta có th có đo n mã sau :
Trong C++, v n đ tr nên đ n gi n h n: struct Complex struct Complex { { float Real; float Real; float Imaginary; float Imaginary; }; }; ………………….. ………………….. struct Complex C; Complex C;
Quy đ nh này cũng áp d ng cho c union enum. Tuy nhiên đ t
ng thích v i C, C++ v n ch p nh n cú pháp cũ.
M t ki u union đ c bi t đ
c thêm vào C++ g i là union n c danh (anonymous union). Nó ch khai báo m t lo t các tr
ng(field) dùng chung m t vùng đ a ch b nh . M t union n c danh không có tên tag, các tr ng có th đ
c truy xu t trực ti p b ng tên c a chúng. Ch ng h n nh đo n mã sau: union { int Num; float Value; };
C hai Num và Value đ u dùng chung m t v trí và không gian b nh . Tuy nhiên không gi ng nh ki u union có tên, các tr ng c a union n c danh thì đ
c truy xu t trực ti p, ch ng h n nh sau: Num = 12; Value = 30.56; II.8. Toán t đ nh ph m vi
Toán t đ nh ph m vi (scope resolution operator) ký hi u là ::, nó đ
c dùng truy xu t m t ph n t b che b i ph m vi hi n th i. Ví d 2.5 : 1: #include 2: int X = 5; 3: int main() 4: { 5: int X = 16;
6: cout<< "Bien X ben trong = "<7: cout<< "Bien X ben ngoai = "<<::X<<"\n"; 8: return 0; 9: }
Chúng ta ch y ví d 2.5, k t qu hình 2.6
Hình 2.6: K t qu c a ví d 2.5
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 17 Toán t đ nh ph m vi còn đ
c dùng trong các đ nh nghƿa hàm c a các ph ng th c trong các l p, đ khai báo l p ch c a các ph ng th c đang đ
c đ nh nghƿa đó. Toán t đ nh ph m vi còn có th đ c dùng
đ phân bi t các thành ph n trùng tên c a các l p c s khác nhau. II.9. Toán t new và delete Trong các ch
ng trình C, t t c các c p phát đ ng b nh đ u đ
c x lý thông qua các hàm th vi n
nh malloc(), calloc()free(). C++ đ nh nghƿa m t ph
ng th c m i đ thực hi n vi c c p phát đ ng b
nh b ng cách dùng hai toán t new delete. S d ng hai toán t này s linh ho t h n r t nhi u so v i các hàm th vi n c a C.
Đo n ch ng trình sau dùng đ c p phát vùng
Trong C++, chúng ta có th vi t l i đo n ch ng
nh đ ng theo l i c đi n c a C. trình trên nh sau: int *P; int *P; P = malloc(sizeof(int)); P = new int; if (P==NULL) if (P==NULL)
printf("Khong con du bo nho de cap phat\n");
cout<<"Khong con du bo nho de cap phat\n"; else else { { *P = 290; *P = 290; printf("%d\n", *P); cout<<*P<<"\n"; free(P); delete P; } }
Chúng ta nh n th y r ng, cách vi t c a C++ sáng s a và d s d ng h n nhi u. Toán t new thay th
cho hàm malloc() hay calloc() c a C có cú pháp nh sau : new type_name
new ( type_name )
new type_name initializer
new ( type_name ) initializer Trong đó :
type_name: Mô t ki u d li u đ
c c p phát. N u ki u d li u mô t ph c t p, nó có th đ c đ t bên trong các d u ngo c.
initializer: Giá tr kh i đ ng c a vùng nh đ c c p phát.
N u toán t new c p phát không thành công thì nó s tr v giá tr NULL.
Còn toán t delete thay th hàm free() c a C, nó có cú pháp nh sau : delete pointer
delete [] pointer
Chúng ta có th v a c p phát v a kh i đ ng nh sau : int *P; P = new int(100); if (P!=NULL) { cout<<*P<<"\n"; delete P; } else
cout<<"Khong con du bo nho de cap phat\n";
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 18
Đ c p phát m t m ng, chúng ta làm nh sau : int *P;
P = new int[10]; //C p phát m ng 10 s nguyên if (P!=NULL) { for(int I = 0;I<10;++) P[I]= I; for(I = 0;I<10;++) cout<

delete []P;
}else cout<<"Khong con du bo nho de cap phat\n";
Chú ý: Đ i v i vi c c p phát m ng chúng ta không th v a c p phát v a kh i đ ng giá tr cho chúng, ch ng h n đo n ch ng trình sau là sai : int *P;
P = new (int[10])(3); //Sai !!! Ví d 2.6: Ch
ng trình t o m t m ng đ ng, kh i đ ng m ng này v i các giá tr ng u nhiên và s p x p chúng. 1: #include 2: #include 3: #include 4: int main() 5: { 6: int N;
7: cout<<"Nhap vao so phan tu cua mang:"; 8: cin>>N; 9: int *P=new int[N]; 10: if (P==NULL) 11: {
12: cout<<"Khong con bo nho de cap phat\n"; 13: return 1; 14: }
15: srand((unsigned)time(NULL));
16: for(int I=0;I17: P[I]=rand()%100; //Tạo các số ng u nhiên từ 0 đến 99
18: cout<<"Mang truoc khi sap xep\n";
19: for(I=0;I20: cout<

21: for(I=0;I22: for(int J=I+1;J23: if (P[I]>P[J]) 24: { 25: int Temp=P[I]; 26: P[I]=P[J]; 27: P[J]=Temp; 28: }
29: cout<<"\nMang sau khi sap xep\n";
30: for(I=0;I31: cout<

32: delete []P; 33: return 0; 34: }
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 19
Chúng ta ch y ví d 2.6, k t qu hình 2.7
Hình 2.7: K t qu c a ví d 2.6 Ví d 2.7: Ch
ng trình c ng hai ma tr n trong đó m i ma tr n đ c c p phát đ ng.
Chúng ta có th xem m ng hai chi u nh m ng m t chi u nh hình 2.8
Hình 2.8: M ng hai chi u có th xem nh m ng m t chi u.
G i X là m ng hai chi u có kích th c m dòng và n c t. A là m ng m t chi u t ng ng.
N u X[i][j] chính là A[k] thì k = i*n + j Chúng ta có ch ng trình nh sau : 1: #include 2: #include 3: //prototype
4: void AddMatrix(int * A,int *B,int*C,int M,int N);
5: int AllocMatrix(int **A,int M,int N); 6: void FreeMatrix(int *A);
7: void InputMatrix(int *A,int M,int N,char Symbol);
8: void DisplayMatrix(int *A,int M,int N); 9: 10: int main() 11: { 12: int M,N;
13: int *A = NULL,*B = NULL,*C = NULL; 14: 15: clrscr();
16: cout<<"Nhap so dong cua ma tran:"; 17: cin>>M;
18: cout<<"Nhap so cot cua ma tran:"; 19: cin>>N;
20: //Cấp phát vùng nhớ cho ma tr n A
21: if (!AllocMatrix(&A,M,N))
22: { //endl: Xuất ra kí tự xuống dòng (‘\n’)
23: cout<<"Khong con du bo nho!"<24: return 1; 25: }
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 20
26: //Cấp phát vùng nhớ cho ma tr n B
27: if (!AllocMatrix(&B,M,N)) 28: {
29: cout<<"Khong con du bo nho!"<30: FreeMatrix(A);//Giải phóng vùng nhớ A 31: return 1; 32: }
33: //Cấp phát vùng nhớ cho ma tr n C
34: if (!AllocMatrix(&C,M,N)) 35: {
36: cout<<"Khong con du bo nho!"<37: FreeMatrix(A);//Giải phóng vùng nhớ A
38: FreeMatrix(B);//Giải phóng vùng nhớ B 39: return 1; 40: }
41: cout<<"Nhap ma tran thu 1"<42: InputMatrix(A,M,N,'A');
43: cout<<"Nhap ma tran thu 2"<44: InputMatrix(B,M,N,'B'); 45: clrscr();
46: cout<<"Ma tran thu 1"<47: DisplayMatrix(A,M,N);
48: cout<<"Ma tran thu 2"<49: DisplayMatrix(B,M,N); 50: AddMatrix(A,B,C,M,N);
51: cout<<"Tong hai ma tran"<52: DisplayMatrix(C,M,N);
53: FreeMatrix(A);//Giải phóng vùng nhớ A
54: FreeMatrix(B);//Giải phóng vùng nhớ B
55: FreeMatrix(C);//Giải phóng vùng nhớ C 56: return 0; 57: } 68: //Cộng hai ma tr n
69: void AddMatrix(int *A,int *B,int*C,int M,int N) 70: {
71: for(int I=0;I72: C[I] = A[I] + B[I]; 73: }
74: //Cấp phát vùng nhớ cho ma tr n
75: int AllocMatrix(int **A,int M,int N) 76: { 77: *A = new int [M*N]; 78: if (*A == NULL) 79: return 0; 80: return 1; 81: }
82: //Giải phóng vùng nhớ 83: void FreeMatrix(int *A) 84: { 85: if (A!=NULL) 86: delete [] A; 87: }
88: //Nh p các giá trị của ma tr n
89: void InputMatrix(int *A,int M,int N,char Symbol) 90: {
91: for(int I=0;I92: for(int J=0;J93 {
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 21
94: cout<95: cin>>A[I*N+J]; 96: } 97: } 100: //Hi n thị ma tr n
101: void DisplayMatrix(int *A,int M,int N) 102: { 103: for(int I=0;I104: { 105: for(int J=0;J106: {
107: out.width(7);//canh le phai voi chieu dai 7 ky tu 108: cout<109: } 110: cout<111: } 112: }
Chúng ta ch y ví du 2.7 , k t qu hình 2.9
Hình 2.9: K t qu c a ví d 2.7
M t cách khác đ c p phát m ng hai chi u A g m M dòng và N c t nh sau: int ** A = new int *[M]; int * Tmp = new int[M*N]; for(int I=0;I{ A[I]=Tmp; Tmp+=N; }
//Thao tác trên m ng hai chi u A ………………….. delete [] *A; delete [] A;
Toán t new còn có m t thu n l i khác, đó là t t c các l i c p phát đ ng đ u có th b t đ c b ng m t hàm x lý l i do ng
i dùng tự đ nh nghƿa. C++ có đ nh nghƿa m t con tr (pointer) tr đ n hàm đ c bi t.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 22 Khi toán t new đ
c s d ng đ c p phát đ ng và m t l i x y ra do c p phát, C++ tự g i đ n hàm đ c ch
b i con tr này. Đ nh nghƿa c a con tr này nh sau: typedef void (*pvf)();
pvf _new_handler(pvf p);
Đi u này có nghƿa là con tr _new_handler là con tr tr đ n hàm không có tham s và không tr v giá
tr . Sau khi chúng ta đ nh nghƿa hàm nh v y và gán đ a ch c a nó cho _new_handler chúng ta có th b t
đ c t t c các l i do c p phát đ ng. Ví d 2.8: 1: #include 2: #include 3: #include 4: 5: void MyHandler(); 6: 7: unsigned long I = 0; 9; 8: void main() 9: { 10: int *A; 11: _new_handler = MyHandler; 12: for( ; ; ++I) 13: A = new int; 14: 15: } 16: 17: void MyHandler() 18: {
19: cout<<"Lan cap phat thu "<20: cout<<"Khong con du bo nho!"<21: exit(1); 22: }
S d ng con tr _new_handler chúng ta ph i include file new.h nh dòng 3. Chúng ta ch y ví d 2.8, k t qu hình 2.10.
Hình 2.10: K t qu c a ví d 2.8
Th vi n cũng còn có m t hàm đ
c đ nh nghƿa trong new.h là hàm có prototype sau :
void ( * set_new_handler(void (* my_handler)() ))();
Hàm set_new_handler() dùng đ gán m t hàm cho _new_handler. Ví d 2.9: 1: #include 2: #include 3: #include 4: 5: void MyHandler(); 6: 7: int main(void) 8: { 9: 10: char *Ptr; 11:
12: set_new_handler(MyHandler);
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 23 13: Ptr = new char[64000u];
14: set_new_handler(0); //Thiết l p lại giá trị mặc định 15: return 0; 16: } 17: 18: void MyHandler() 19: { 20: cout <21: exit(1); 22 }
Chúng ta ch y ví d 2.9, k t qu hình 2.11
Hình 2.11: K t qu c a ví d 2.9 II.10. Hàm inline M t ch
ng trình có c u trúc t t s d ng các hàm đ chia ch
ng trình thành các đ n v đ c l p có logic
riêng. Tuy nhiên, các hàm th
ng ph i ch a m t lo t các x lý đi m vào (entry point): tham s ph i đ c
đ y vào stack, m t l nh g i ph i đ c thực hi n và sau đó vi c quay tr v cũng ph i đ c thực hi n b ng
cách gi i phóng các tham s ra kh i stack. Khi các x lý đi m vào ch m ch p th ng các l p trình viên C
ph i s d ng cách chép l p l i các đo n ch
ng trình n u mu n tĕng hi u qu .
Đ tránh kh i ph i x lý đi m vào, C++ trang b thêm t khóa inline đ lo i vi c g i hàm. Khi đó trình
biên d ch s không biên d ch hàm này nh m t đo n ch
ng trình riêng bi t mà nó s đ c chèn th ng vào các ch mà hàm này đ
c g i. Đi u này làm gi m vi c x lý đi m vào mà v n cho phép m t ch ng trình
đ c t ch c d i d ng có c u trúc. Cú pháp c a hàm inline nh sau :
inline data_type function_name ( parameters ) {
…………………………….. }
Trong đó: data_type: Ki u tr v c a hàm. Function_name:Tên c a hàm.
Parameters: Các tham s c a hàm.
Ví d 2.10: Tính th tích c a hình l p ph ng 1: #include 2: inline float Cube(float S) 3: { 4: return S*S*S; 5: } 6: 7: int main() 8: {
9: cout<<"Nhap vao chieu dai canh cua hinh lap phuong:"; 10: float Side; 11: cin>>Side;
12: cout<<"The tich cua hinh lap phuong = "<13: return 0; 14: }
Chúng ta ch y ví d 2.10, k t qu hình 2.12
Hình 2.12: K t qu c a ví d 2.10
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 24 Chú ý:
S d ng hàm inline s làm cho ch
ng trình l n lên vì trình biên d ch chèn đo n ch ng trình vào các ch mà hàm này đ c g i. Do đó th ng các hàm inline th
ng là các hàm nh , ít ph c t p.
Các hàm inline ph i đ c đ nh nghƿa tr
c khi s d ng. ví d 2.10 chúng ta s a l i nh sau thì ch ng trình s b báo l i: #include float Cube(float S); int main() {
cout<<"Nhap vao chieu dai canh cua hinh lap phuong:"; float Side; cin>>Side;
cout<<"The tich cua hinh lap phuong = "< return 0; } inline float Cube(float S) { return S*S*S; } Các hàm đ quy không đ c là hàm inline.
II.11. Các giá tr tham s m c đ nh
M t trong các đ c tính n i b t nh t c a C++ là kh nĕng đ nh nghƿa các giá tr tham s m c đ nh cho các hàm. Bình th
ng khi g i m t hàm, chúng ta c n g i m t giá tr cho m i tham s đã đ c đ nh nghƿa trong
hàm đó, ch ng h n chúng ta có đo n ch ng trình sau:
void MyDelay(long Loops); //prototype
……………………………….. void MyDelay(long Loops) {
for(int I = 0; I < Loops; ++I) ; }
M i khi hàm MyDelay() đ
c g i chúng ta ph i g i cho nó m t giá tr cho tham s Loops. Tuy nhiên, trong nhi u tr
ng h p chúng ta có th nh n th y r ng chúng ta luôn luôn g i hàm MyDelay() v i cùng m t
giá tr Loops nào đó. Mu n v y chúng ta s dùng giá tr m c đ nh cho tham s Loops, gi s chúng ta mu n
giá tr m c đ nh cho tham s Loops là 1000. Khi đó đo n mã trên đ c vi t l i nh sau :
void MyDelay(long Loops = 1000); //prototype
……………………………….. void MyDelay(long Loops) {
for(int I = 0; I < Loops; ++I) ; }
M i khi g i hàm MyDelay() mà không g i m t tham s t
ng ng thì trình biên d ch s tự đ ng gán cho
tham s Loops giá tr 1000.
MyDelay(); // Loops có giá tr là 1000
MyDelay(5000); // Loops có giá tr là 5000
Giá tr m c đ nh cho tham s có th là m t h ng, m t hàm, m t bi n hay m t bi u th c.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 25
Ví d 2.11: Tính th tích c a hình h p 1: #include
2: int BoxVolume(int Length = 1, int Width = 1, int Height = 1); 3: 4: int main() 5: {
6: cout << "The tich hinh hop mac dinh: "
7: << BoxVolume() << endl << endl
8: << "The tich hinh hop voi chieu dai=10,do rong=1,chieu cao=1:"
9: << BoxVolume(10) << endl << endl
10: << "The tich hinh hop voi chieu dai=10,do rong=5,chieu cao=1:"
11: << BoxVolume(10, 5) << endl << endl
12: << "The tich hinh hop voi chieu dai=10,do rong=5,chieu cao=2:"
13: << BoxVolume(10, 5, 2)<< endl; 14: return 0; 15: }
16: //Tính th tích của hình hộp
17: int BoxVolume(int Length, int Width, int Height) 18: {
19: return Length * Width * Height; 20: }
Chúng ta ch y ví d 2.11, k t qu hình 2.13
Hình 2.13: K t qu c a ví d 2.11 Chú ý:
Các tham s có giá tr m c đ nh ch đ
c cho trong prototype c a hàm và không đ c l p l i trong
đ nh nghƿa hàm (Vì trình biên d ch s dùng các thông tin trong prototype ch không ph i trong đ nh nghƿa hàm đ t o m t l nh g i).
M t hàm có th có nhi u tham s có giá tr m c đ nh. Các tham s có giá tr m c đ nh c n ph i đ c
nhóm l i vào các tham s cu i cùng (ho c duy nh t) c a m t hàm. Khi g i hàm có nhi u tham s có giá tr
m c đ nh, chúng ta ch có th b b t các tham s theo th tự t ph i sang trái và ph i b liên ti p nhau,
ch ng h n chúng ta có đo n ch ng trình nh sau:
int MyFunc(int a= 1, int b , int c = 3, int d = 4); //prototype sai!!!
int MyFunc(int a, int b = 2 , int c = 3, int d = 4); //prototype đúng ………………………..
MyFunc(); // L i do tham s a không có giá tr m c đ nh
MyFunc(1);// OK, các tham s b, c và d l y giá tr m c đ nh
MyFunc(5, 7); // OK, các tham s c và d l y giá tr m c đ nh
MyFunc(5, 7, , 8); // L i do các tham s b b ph i liên ti p nhau
II.12. Phép tham chi u
Trong C, hàm nh n tham s là con tr đòi h i chúng ta ph i th n tr ng khi g i hàm. Chúng ta c n vi t
hàm hoán đ i giá tr gi a hai s nh sau:
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 26 void Swap(int *X, int *Y); { int Temp = *X; *X = *Y; *Y = *Temp; }
Đ hoán đ i giá tr hai bi n A B thì chúng ta g i hàm nh sau: Swap(&A, &B);
Rõ ràng cách vi t này không đ c thu n ti n l m. Trong tr
ng h p này, C++ đ a ra m t ki u bi n r t
đ c bi t g i là bi n tham chi u (reference variable). M t bi n tham chi u gi ng nh là m t bí danh c a bi n
khác. Bi n tham chi u s làm cho các hàm có thay đ i n i dung các tham s c a nó đ c vi t m t cách thanh
thoát h n. Khi đó hàm Swap() đ c vi t nh sau:
void Swap(int &X, int &Y); { int Temp = X; X = Y; Y = Temp ; } Chúng ta g i hàm nh sau : Swap(A, B);
V i cách g i hàm này, C++ tự g i đ a ch c a A B làm tham s cho hàm Swap(). Cách dùng bi n
tham chi u cho tham s c a C++ t ng tự nh các tham s đ
c khai báo là Var trong ngôn ng Pascal. Tham s này đ
c g i là tham s ki u tham chi u (reference parameter). Nh v y bi n tham chi u có cú pháp nh sau :
data_type & variable_name; Trong đó:
data_type: Ki u d li u c a bi n. variable_name: Tên c a bi n
Khi dùng bi n tham chi u cho tham s ch có đ a ch c a nó đ
c g i đi ch không ph i là toàn b c u trúc hay đ i t
ng đó nh hình 2.14, đi u này r t h u d ng khi chúng ta g i c u trúc và đ i t ng l n cho m t hàm.
Hình 2.14: M t tham s ki u tham chi u nh n m t tham chi u t i m t bi n đ c chuy n cho tham s c a hàm.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 27 Ví d 2.12: Ch
ng trình hoán đ i giá tr c a hai bi n. #include //prototype
void Swap(int &X,int &Y); int main() { int X = 10, Y = 5;
cout<<"Truoc khi hoan doi: X = "< Swap(X,Y);
cout<<"Sau khi hoan doi: X = "< return 0; }
void Swap(int &X,int &Y) { int Temp=X; X=Y; Y=Temp; }
Chúng ta ch y ví d 2.12, k t qu hình 2.15
Hình 2.15: K t qu c a ví d 2.12
Đôi khi chúng ta mu n g i m t tham s nào đó b ng bi n tham chi u cho hi u qu , m c dù chúng ta
không mu n giá tr c a nó b thay đ i thì chúng ta dùng thêm t khóa const nh sau :
int MyFunc(const int & X);
Hàm MyFunc() s ch p nh n m t tham s X g i b ng tham chi u nh ng const xác đ nh r ng X không th b thay đ i.
Bi n tham chi u có th s d ng nh m t bí danh c a bi n khác (bí danh đ n gi n nh m t tên khác c a
bi n g c), ch ng h n nh đo n mã sau : int Count = 1;
int & Ref = Count; //T o bi n Ref nh là m t bí danh c a bi n Count
++Ref; //Tĕng bi n Count lên 1 (s d ng bí danh c a bi n Count) Các bi n tham chi u ph i đ
c kh i đ ng trong ph n khai báo c a chúng và chúng ta không th gán l i
m t bí danh c a bi n khác cho chúng. Ch ng h n đo n mã sau là sai: int X = 1; int & Y; //L i: Y ph i đ c kh i đ ng. Khi m t tham chi u đ
c khai báo nh m t bí danh c a bi n khác, m i thao tác thực hi n trên bí danh
chính là thực hi n trên bi n g c c a nó. Chúng ta có th l y đ a ch c a bi n tham chi u và có th so sánh các
bi n tham chi u v i nhau (ph i t ng thích v ki u tham chi u).
Ví d 2.13: M i thao tác trên trên bí danh chính là thao tác trên bi n g c c a nó. #include int main() { int X = 3;
int &Y = X; //Y la bí danh của X int Z = 100; cout<<"X="< Y *= 3;
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 28 cout<<"X="< Y = Z;
cout<<"X="< return 0; }
Chúng ta ch y ví d 2.13, k t qu hình 2.16
Hình 2.16: K t qu c a ví d 2.13
Ví d 2.14: L y đ a ch c a bi n tham chi u #include int main() { int X = 3;
int &Y = X; //Y la bí danh của X
cout<<"Dia chi cua X = "<<&X< cout<<"Dia chi cua bi danh Y= "<<&Y< return 0; }
Chúng ta ch y ví d 2.14, k t qu hình 2.17
Hình 2.17: K t qu c a ví d 2.14
Chúng ta có th t o ra bi n tham chi u v i vi c kh i đ ng là m t h ng, ch ng h n nh đo n mã sau : int & Ref = 45; Trong tr
ng h p này, trình biên d ch t o ra m t bi n t m th i ch a tr h ng và bi n tham chi u chính là
bí danh c a bi n t m th i này. Đi u này g i là tham chi u đ c l p (independent reference).
Các hàm có th tr v m t tham chi u, nh ng đi u này r t nguy hi m. Khi hàm tr v m t tham chi u t i
m t bi n c c b c a hàm thì bi n này ph i đ
c khai báo là static, ng
c l i tham chi u t i nó thì khi hàm
k t thúc bi n c c b này s b b qua. Ch ng h n nh đo n ch ng trình sau: int & MyFunc() {
static int X = 200; //N u không khai báo là static thì đi u này r t nguy hi m. return X; }
Khi m t hàm tr v m t tham chi u, chúng ta có th g i hàm phía bên trái c a m t phép gán. Ví d 2.15: 1: #include 2: 3: int X = 4; 4: //prototype
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 29 5: int & MyFunc(); 6: 7: int main() 8: {
9: cout<<"X="<10: cout<<"X="<11: MyFunc() = 20; //Nghĩa là X = 20
12: cout<<"X="<13: return 0; 14: } 15: 16: int & MyFunc() 17: { 18: return X; 19: }
Chúng ta ch y ví d 2.15, k t qu hình 2.18
Hình 2.18: K t qu c a ví d 2.15 Chú ý:
M c dù bi n tham chi u trông gi ng nh là bi n con tr nh ng chúng không th là bi n con tr do đó chúng không th đ c dùng c p phát đ ng.
Chúng ta không th khai báo m t bi n tham chi u ch đ n bi n tham chi u ho c bi n con tr ch đ n
bi n tham chi u. Tuy nhiên chúng ta có th khai báo m t bi n tham chi u v bi n con tr nh đo n mã sau: int X; int *P = &X; int * & Ref = P;
II.13. Phép đa nĕng hóa (Overloading)
V i ngôn ng C++, chúng ta có th đa nĕng hóa các hàm và các toán t (operator). Đa nĕng hóa là ph
ng pháp cung c p nhi u h n m t đ nh nghƿa cho tên hàm đã cho trong cùng m t ph m vi. Trình biên
d ch s lựa ch n phiên b n thích h p c a hàm hay toán t dựa trên các tham s mà nó đ c g i.
II.13.1. Đa nĕng hóa các hàm (Functions overloading)
Trong ngôn ng C cũng nh m i ngôn ng máy tính khác, m i hàm đ u ph i có m t tên phân bi t. Đôi
khi đây là m t đi u phi n toái. Ch ng h n nh trong ngôn ng C, có r t nhi u hàm tr v tr tuy t đ i c a
m t tham s là s , vì c n thi t ph i có tên phân bi t nên C ph i có hàm riêng cho m i ki u d li u s , do v y
chúng ta có t i ba hàm khác nhau đ tr v tr tuy t đ i c a m t tham s : int abs(int i); long labs(long l); double fabs(double d);
T t c các hàm này đ u cùng thực hi n m t ch a nĕng nên chúng ta th y đi u này ngh ch lý khi ph i có
ba tên khác nhau. C++ gi i quy t đi u này b ng cách cho phép chúng ta t o ra các hàm khác nhau có cùng
m t tên. Đây chính là đa nĕng hóa hàm. Do đó trong C++ chúng ta có th đ nh nghƿa l i các hàm tr v tr
tuy t đ i đ thay th các hàm trên nh sau : int abs(int i); long abs(long l); double abs(double d);
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 30 Ví d 2.16: 1: #include 2: #include 3: 4: int MyAbs(int X); 5: long MyAbs(long X); 6: double MyAbs(double X); 7: 8: int main() 9: { 10: int X = -7; 11: long Y = 200000l; 12: double Z = -35.678;
13: cout<<"Tri tuyet doi cua so nguyen (int) "<14: <15: cout<<"Tri tuyet doi cua so nguyen (long int) "<16: <17: cout<<"Tri tuyet doi cua so thuc "<18: <19: return 0; 20: } 21: 22: int MyAbs(int X) 23: { 24: return abs(X); 25: } 26: 27: long MyAbs(long X) 28: { 29: return labs(X); 30: } 31: 32: double MyAbs(double X) 33: { 34: return fabs(X); 35: }
Chúng ta ch y ví d 2.16 , k t qu hình 2.19
Hình 2.19: K t qu c a ví d 2.16
Trình biên d ch dựa vào sự khác nhau v s các tham s , ki u c a các tham s đ có th xác đ nh chính
xác phiên b n cài đ t nào c a hàm MyAbs() thích h p v i m t l nh g i hàm đ c cho, ch ng h n nh :
MyAbs(-7); //G i hàm int MyAbs(int)
MyAbs(-7l); //G i hàm long MyAbs(long)
MyAbs(-7.5); //G i hàm double MyAbs(double) Quá trình tìm đ c hàm đ
c đa nĕng hóa cũng là quá trình đ c dùng đ gi i quy t các tr ng h p
nh p nh ng c a C++. Ch ng h n nh n u tìm th y m t phiên b n đ nh nghƿa nào đó c a m t hàm đ c đa
nĕng hóa mà có ki u d li u các tham s c a nó trùng v i ki u các tham s đã g i t i trong l nh g i hàm thì phiên b n hàm đó s đ
c g i. N u không trình biên d ch C++ s g i đ n phiên b n nào cho phép chuy n ki u d dàng nh t.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 31
MyAbs(‘c’); //G i int MyAbs(int)
MyAbs(2.34f); //G i double MyAbs(double)
Các phép chuy n ki u có s n s đ
c u tiên h n các phép chuy n ki u mà chúng ta t o ra (chúng ta s
xem xét các phép chuy n ki u tự t o ch ng 3).
Chúng ta cũng có th l y đ a ch c a m t hàm đã đ
c đa nĕng hóa sao cho b ng m t cách nào đó chúng
ta có th làm cho trình biên d ch C++ bi t đ
c chúng ta c n l y đ a ch c a phiên b n hàm nào có trong đ nh nghƿa. Ch ng h n nh : int (*pf1)(int); long (*pf2)(long); int (*pf3)(double);
pf1 = MyAbs; //Tr đ n hàm int MyAbs(int)
pf2 = MyAbs; //Tr đ n hàm long MyAbs(long)
pf3 = MyAbs; //L i!!! (không có phiên b n hàm nào đ đ i sánh)
Các gi i h n c a vi c đa nĕng hóa các hàm:
• B t kỳ hai hàm nào trong t p các hàm đã đa nĕng ph i có các tham s khác nhau.
• Các hàm đa nĕng hóa v i danh sách các tham s cùng ki u ch dựa trên ki u tr v c a hàm thì
trình biên d ch báo l i. Ch ng h n nh , các khai báo sau là không h p l : void Print(int X); int Print(int X);
Không có cách nào đ trình biên d ch nh n bi t phiên b n nào đ
c g i n u giá tr tr v b b qua. Nh
v y các phiên b n trong vi c đa nĕng hóa ph i có sự khác nhau ít nh t v ki u ho c s tham s mà chúng nh n đ c.
• Các khai báo b ng l nh typedef không đ nh nghƿa ki u m i. Chúng ch thay đ i tên g i c a ki u
đã có. Chúng không nh h ng t i c ch đa nĕng hóa hàm. Chúng ta hãy xem xét đo n mã sau: typedef char * PSTR; void Print(char * Mess); void Print(PSTR Mess);
Hai hàm này có cùng danh sách các tham s , do đó đo n mã trên s phát sinh l i.
• Đ i v i ki u m ng và con tr đ c xem nh đ ng nh t đ i v i sự phân bi t khác nhau gi a các
phiên b n hàm trong vi c đa nĕng hóa hàm. Ch ng h n nh đo n mã sau se phát sinh l i: void Print(char * Mess); void Print(char Mess[]);
Tuy nhiên, đ i v i m ng nhi u chi u thì có sự phân bi t gi a các phiên b n hàm trong vi c đa nĕng hóa
hàm, ch ng h n nh đo n mã sau h p l : void Print(char Mess[]); void Print(char Mess[][7]);
void Print(char Mess[][9][42]);
const và các con tr (hay các tham chi u) có th dùng đ phân bi t, ch ng h n nh đo n mã sau h p l :
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 32 void Print(char *Mess); void Print(const char *Mess);
II.13.2. Đa nĕng hóa các toán t (Operators overloading) :
Trong ngôn ng C, khi chúng ta tự t o ra m t ki u d li u m i, chúng ta thực hi n các thao tác liên quan
đ n ki u d li u đó th ng thông qua các hàm, đi u này tr nên không tho i mái. Ví d 2.17: Ch
ng trình cài đ t các phép toán c ng và tr s ph c 1: #include
2: /* Định nghĩa số phức */ 3: typedef struct 4: { 5: double Real; 6: double Imaginary; 7: }Complex; 8:
9: Complex SetComplex(double R,double I);
10: Complex AddComplex(Complex C1,Complex C2);
11: Complex SubComplex(Complex C1,Complex C2);
12: void DisplayComplex(Complex C); 13: 14: int main(void) 15: { 16: Complex C1,C2,C3,C4; 17: 18: C1 = SetComplex(1.0,2.0);
19: C2 = SetComplex(-3.0,4.0);
20: printf("\nSo phuc thu nhat:"); 21: DisplayComplex(C1);
22: printf("\nSo phuc thu hai:"); 23: DisplayComplex(C2);
24: C3 = AddComplex(C1,C2); //Hơi bất tiện !!! 25: C4 = SubComplex(C1,C2);
26: printf("\nTong hai so phuc nay:"); 27: DisplayComplex(C3);
28: printf("\nHieu hai so phuc nay:"); 29: DisplayComplex(C4); 30: return 0; 31: } 32:
33: /* Đặt giá trị cho một số phức */
34: Complex SetComplex(double R,double I) 35: { 36: Complex Tmp; 37: 38: Tmp.Real = R; 39: Tmp.Imaginary = I; 40: return Tmp; 41: }
42: /* Cộng hai số phức */
43: Complex AddComplex(Complex C1,Complex C2) 44: { 45: Complex Tmp; 46:
47: Tmp.Real = C1.Real+C2.Real;
48: Tmp.Imaginary = C1.Imaginary+C2.Imaginary; 49: return Tmp;
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 33 50: } 51:
52: /* Trừ hai số phức */
53: Complex SubComplex(Complex C1,Complex C2) 54: { 55: Complex Tmp; 56:
57: Tmp.Real = C1.Real-C2.Real;
58: Tmp.Imaginary = C1.Imaginary-C2.Imaginary; 59: return Tmp; 60: } 61:
62: /* Hi n thị số phức */
63: void DisplayComplex(Complex C) 64: {
65: printf("(%.1lf,%.1lf)",C.Real,C.Imaginary); 66: }
Chúng ta ch y ví d 2.17, k t qu hình 2.20
Hình 2.20: K t qu c a ví d 2.17 Trong ch
ng trình ví d 2.17, chúng ta nh n th y v i các hàm v a cài đ t dùng đ c ng và tr hai s ph c 1+2i và –3+4i; ng
i l p trình hoàn toàn không tho i mái khi s d ng b i vì thực ch t thao tác c ng và
tr là các toán t ch không ph i là hàm. Đ kh c ph c y u đi m này, trong C++ cho phép chúng ta có th
đ nh nghƿa l i ch c nĕng c a các toán t đã có s n m t cách ti n l i và tự nhiên h n r t nhi u. Đi u này g i
là đa nĕng hóa toán t . Khi đó ch ng trình ví d 2.17 đ c vi t nh sau: Ví d 2.18: 1: #include
2: // Định nghĩa số phức 3: typedef struct 4: { 5: double Real; 6: double Imaginary; 7: }Complex; 8:
9: Complex SetComplex(double R,double I);
10: void DisplayComplex(Complex C);
11: Complex operator + (Complex C1,Complex C2);
12: Complex operator - (Complex C1,Complex C2); 13: 14: int main(void) 15: { 16: Complex C1,C2,C3,C4; 17: 18: C1 = SetComplex(1.0,2.0);
19: C2 = SetComplex(-3.0,4.0);
20: cout<<"\nSo phuc thu nhat:"; 21: DisplayComplex(C1);
22: cout<<"\nSo phuc thu hai:"; 23: DisplayComplex(C2); 24: C3 = C1 + C2;
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 34 25: C4 = C1 - C2;
26: cout<<"\nTong hai so phuc nay:"; 27: DisplayComplex(C3);
28: cout<<"\nHieu hai so phuc nay:"; 29: DisplayComplex(C4); 30: return 0; 31: } 32:
33: //Đặt giá trị cho một số phức
34: Complex SetComplex(double R,double I) 35: { 36: Complex Tmp; 37: 38: Tmp.Real = R; 39: Tmp.Imaginary = I; 40: return Tmp; 41: } 42: 43: //Cộng hai số phức
44: Complex operator + (Complex C1,Complex C2) 45: { 46: Complex Tmp; 47:
48: Tmp.Real = C1.Real+C2.Real;
49: Tmp.Imaginary = C1.Imaginary+C2.Imaginary; 50: return Tmp; 51: } 52: 53: //Trừ hai số phức
54: Complex operator - (Complex C1,Complex C2) 55: { 56: Complex Tmp; 57:
58: Tmp.Real = C1.Real-C2.Real;
59: Tmp.Imaginary = C1.Imaginary-C2.Imaginary; 60: return Tmp; 61: } 62: 63: //Hi n thị số phức
64: void DisplayComplex(Complex C) 65: { 66: cout<<"("<67: }
Chúng ta ch y ví d 2.18, k t qu hình 2.21
Hình 2.21: K t qu c a ví d 2.18
Nh v y trong C++, các phép toán trên các giá tr ki u s ph c đ
c thực hi n b ng các toán t toán h c
chu n ch không ph i b ng các tên hàm nh trong C. Ch ng h n chúng ta có l nh sau:
C4 = AddComplex(C3, SubComplex(C1,C2));
thì trong C++, chúng ta có l nh t ng ng nh sau: C4 = C3 + C1 - C2;
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 35
Chúng ta nh n th y r ng c hai l nh đ u cho cùng k t qu nh ng l nh c a C++ thì d hi u h n. C++ làm
đ c đi u này b ng cách t o ra các hàm đ nh nghƿa cách thực hi n c a m t toán t cho các ki u d li u tự
đ nh nghƿa. M t hàm đ nh nghƿa m t toán t có cú pháp sau:
data_type operator operator_symbol ( parameters ) {
……………………………… }
Trong đó: data_type: Ki u tr v .
operator_symbol: Ký hi u c a toán t .
parameters: Các tham s (n u có). Trong ch
ng trình ví d 2.18, toán t + là toán t g m hai toán h ng (g i là toán t hai ngôi; toán t
m t ngôi là toán t ch có m t toán h ng) và trình biên d ch bi t tham s đ u tiên là bên trái toán t , còn
tham s th hai thì bên ph i c a toán t . Trong tr
ng h p l p trình viên quen thu c v i cách g i hàm,
C++ v n cho phép b ng cách vi t nh sau: C3 = operator + (C1,C2); C4 = operator - (C1,C2); Các toán t đ c đa nĕng hóa s đ
c lựa ch n b i trình biên d ch cũng theo cách th c t ng tự nh
vi c ch n lựa gi a các hàm đ
c đa nĕng hóa là khi g p m t toán t làm vi c trên các ki u không ph i là
ki u có s n, trình biên d ch s tìm m t hàm đ nh nghƿa c a toán t nào đó có các tham s đ i sánh v i các
toán h ng đ dùng. Chúng ta s tìm hi u k v vi c đa nĕng hóa các toán t trong ch ng 4.
Các gi i h n c a đa nĕng hóa toán t :
• Chúng ta không th đ nh nghƿa các toán t m i.
• H u h t các toán t c a C++ đ u có th đ c đa nĕng hóa. Các toán t sau không đ c đa nĕng hóa là : Toán t Ý nghƿa :: Toán t đ nh ph m vi. .* Truy c p đ n con tr là tr
ng c a struct hay thành viên c a class. . Truy c p đ n tr
ng c a struct hay thành viên c a class. ?: Toán t đi u ki n sizeof
và chúng ta cũng không th đa nĕng hóa b t kỳ ký hi u ti n x lý nào.
• Chúng ta không th thay đ i th tự u tiên c a m t toán t hay không th thay đ i s các toán h ng c a nó.
• Chúng ta không th thay đ i ý nghƿa c a các toán t khi áp d ng cho các ki u có s n.
• Đa nĕng hóa các toán t không th có các tham s có giá tr m c đ nh.
Các toán t có th đa nĕng hoá: + - * / % ^ ! = < > += -= ^= &= |= << >> <<= <= >= && || ++ -- () [] new delete & | ~ *= /= %= >>= == != , -> ->*
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 36 Các toán t đ c phân lo i nh sau :
Các toán t m t ngôi : * & ~ ! ++ -- sizeof (data_type) Các toán t này đ
c đ nh nghƿa ch có m t tham s và ph i tr v m t giá tr cùng ki u v i tham s c a
chúng. Đ i v i toán t sizeof ph i tr v m t giá tr ki u size_t (đ nh nghƿa trong stddef.h)
Toán t (data_type) đ
c dùng đ chuy n đ i ki u, nó ph i tr v m t giá tr có ki u là data_type.
Các toán t hai ngôi: * / % + - >> << > <
>= <= == != & | ^ && || Các toán t này đ
c đ nh nghƿa có hai tham s .
Các phép gán: = += -= *= /= %= >>= <<= ^= |= Các toán t gán đ
c đ nh nghƿa ch có m t tham s . Không có gi i h n v ki u c a tham s và ki u tr v c a phép gán.
Toán t l y thành viên : ->
Toán t l y ph n t theo ch s : []
Toán t g i hàm: () BÀI T P
Bài 1: Hãy vi t l i ch
ng trình sau b ng cách s d ng l i các dòng nh p/xu t trong C++. /* Ch
ng trình tìm m u chung nh nh t */ #include int main() { int a,b,i,min; printf("Nhap vao hai so:"); scanf("%d%d",&a,&b); min=a>b?b:a;
for(i = 2;iif (((a%i)==0)&&((b%i)==0)) break; if(i==min) {
printf("Khong co mau chung nho nhat"); return 0; }
printf("Mau chung nho nhat la %d\n",i); return 0; } Bài 2: Vi t ch
ng trình nh p vào s nguyên d
ng h (2chi u cao là h nh các hình sau:
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 37
Bài 3: M t tam giác vuông có th có t t c các c nh là các s nguyên. T p c a ba s nguyên c a
các c nh c a m t tam giác vuông đ
c g i là b ba Pitago. Đó là t ng bình ph ng c a hai c nh b ng bình ph
ng c a c nh huy n, ch ng h n b ba Pitago (3, 4, 5). Vi t ch ng trình tìm t t c
các b ba Pitago nh th sao cho t t c các c nh không quá 500. Bài 4: Vi t ch
ng trình in b ng c a các s t 1 đ n 256 d
i d ng nh phân, bát phân và th p l c phân t ng ng. Bài 5: Vi t ch
ng trình nh p vào m t s nguyên d
ng n. Ki m tra xem s nguyên n có thu c dãy Fibonacci không? Bài 6: Vi t ch
ng trình nhân hai ma trân Amxn và Bnxp. M i ma tr n đ c c p phát đ ng và
các giá tr c a chúng phát sinh ng u nhiên (V i m, n và p nh p t bàn phím). Bài 7: Vi t ch
ng trình t o m t m ng m t chi u đ ng có kích th
c là n (n nh p t bàn phím). Các giá tr c a m ng này đ
c phát sinh ng u nhiên trên đo n [a, b] v i a và b đ u nh p t bàn phím. Hãy tìm s d
ng nh nh t và s âm l n nh t trong m ng; n u không có s d ng nh nh t
ho c s âm l n nh t thì xu t thông báo "không có s d
ng nh nh t" ho c "không có s âm l n nh t".
Bài 8: Anh (ch ) hãy vi t m t hàm tính bình ph
ng c a m t s . Hàm s tr v giá tr bình ph
ng c a tham s và có ki u cùng ki u v i tham s .
Bài 9: Trong ngôn ng C, chúng ta có hàm chuy n đ i m t chu i sang s , tùy thu c vào d ng c a
chu i chúng ta có các hàm chuy n đ i sau : int atoi(const char *s);
Chuy n đ i m t chu i s thành s nguyên ki u int. long atol(const char *s);
Chuy n đ i m t chu i s thành s nguyên ki u long. double atof(const char *s);
Chuy n đ i m t chu i s thành s thực ki u double.
Anh (ch ) hãy vi t m t hàm có tên là aton (ascii to number) đ chuy n đ i chu i sang các d ng s t ng ng.
Bài 10: Anh ch hãy vi t các hàm sau:
Hàm ComputeCircle() đ tính di n tích s và chu vi c c a m t đ ng tròn bán kính
r. Hàm này có prototype nh sau:
void ComputeCircle(float & s, float &c, float r = 1.0);
Hàm ComputeRectangle() đ tính di n tích s và chu vi p c a m t hình ch nh t có
chi u cao h và chi u r ng w. Hàm này có prototype nh sau:
void ComputeRectangle(float & s, float &p, float h = 1.0, float w = 1.0);
Hàm ComputeTriangle() đ tính di n tích s và chu vi p c a m t tam giác có ba
c nh a,b và c. Hàm này có prototype nh sau:
void ComputeTriangle(float & s, float &p, float a = 1.0, float b = 1.0, float c = 1.0);
Hàm ComputeSphere() đ tính th tích v và di n tích b m t s c a m t hình c u có
bán kính r. Hàm này có prototype nh sau:
void ComputeSphere(float & v, float &s, float r = 1.0);
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 38
Hàm ComputeCylinder() đ tính th tích v và di n tích b m t s c a m t hình tr
có bán kính r và chi u cao h. Hàm này có prototype nh sau:
void ComputeCylinder(float & v, float &s, float r = 1.0 , float h = 1.0);
Bài 11: Anh (ch ) hãy vi t thêm hai toán t nhân và chia hai s ph c ví d 2.18 c a ch ng 2.
Bài 12: M t c u trúc Date ch a ngày, tháng và nĕm nh sau: struct Date {
int Day; //Có giá tr t 1 → 31
int Month; //Có giá tr t 1 → 12
int Year; //Bi u di n b ng 4 ch s . };
Anh (ch ) hãy vi t các hàm đ nh nghƿa các toán t : + - > >= < <= == != trên c u trúc Date này.
Bài 13: M t c u trúc Point3D bi u di n t a đ c a m t đi m trong không gian ba chi u nh sau: struct Point3D { float X; float Y; float Z; };
Anh (ch ) hãy vi t các hàm đ nh nghƿa các toán t : + - == != trên c u trúc Point3D này.
Bài 14: M t c u trúc Fraction dùng đ ch a m t phân s nh sau: struct Fraction { int Numerator; //T s int Denominator; //M u s };
Anh (ch ) hãy vi t các hàm đ nh nghƿa các toán t :
+ - * / > >= < <= == !=
trên c u trúc Fraction này.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 39 CHƯƠNG 3 L P VÀ Đ I T NG I. D N NH P
Bây gi chúng ta b t đ u tìm hi u v l p trình h ng đ i t
ng trong C++. Trong các ph n sau, chúng ta
cũng tìm hi u v các k thu t c a thi t k h ng đ i t
ng (Object-Oriented Design OOD): Chúng ta phân
tích m t v n đ c th , xác đ nh các đ i t
ng nào c n đ cài đ t h th ng, xác đ nh các thu c tính nào mà
đ i t ng ph i có, xác đ nh hành vi nào mà đ i t ng c n đ a ra, và ch rõ làm th nào các đ i t ng c n t ng tác v i đ i t
ng khác đ thực hi n các m c tiêu t ng th c a h th ng.
Chúng ta nh c l i các khái ni m và thu t ng chính c a đ nh h ng đ i t
ng. OOP đóng gói d li u
(các thu c tính) và các hàm (hành vi) thành gói g i là các đối tượng. D li u và các hàm c a đ i t ng có sự
liên h m t thi t v i nhau. Các đ i t
ng có các đ c tính c a vi c che d u thông tin. Đi u này nghƿa là m c dù các đ i t
ng có th bi t làm th nào liên l c v i đ i t
ng khác thông qua các giao di n hoàn toàn xác
đ nh, bình th ng các đ i t ng không đ c phép bi t làm th nào các đ i t ng khác đ c thực thi, các chi ti t c a sự thi hành đ c d u bên trong các đ i t ng.
Trong C và các ngôn ng l p trình th t c, l p trình có khuynh h ng đ nh h ng hành đ ng, trong khi ý t
ng trong l p trình C++ là đ nh h ng đ i t
ng. Trong C, đ n v c a l p trình là hàm; trong C++, đ n
v c a l p trình là lớp (class) .
Các l p trình viên C t p trung vào vi t các hàm. Các nhóm c a các hành đ ng mà thực hi n vài công vi c đ
c t o thành các hàm, và các hàm đ c nhóm thành các ch
ng trình. D li u thì r t quan tr ng trong
C, nh ng quan đi m là d li u t n t i chính trong vi c h tr các hành đ ng mà hàm thực hi n. Các đ ng t
trong m t h th ng giúp cho l p trình viên C xác đ nh t p các hàm mà s ho t đ ng cùng v i vi c thực thi h th ng.
Các l p trình viên C++ t p trung vào vi c t o ra "các ki u do ng
i dùng đ nh nghƿa" (user-defined
types) g i là các l p. Các l p cũng đ
c tham chi u nh "các ki u do l p trình viên đ nh nghƿa"
(programmer-defined types). M i l p ch a d li u cũng nh t p các hàm mà x lý d li u. Các thành ph n d li u c a m t l p đ
c g i là "các thành viên d li u" (data members). Các thành ph n hàm c a m t l p
đ c g i là "các hàm thành viên" (member functions). Gi ng nh thực th c a ki u có s n nh int đ c g i
là m t bi n, m t thực th c a ki u do ng
i dùng đ nh nghƿa (nghƿa là m t l p) đ c g i là m t đ i t ng.
Các danh t trong m t h th ng giúp cho l p trình viên C++ xác đ nh t p các l p. Các l p này đ c s d ng
đ t o các đ i t ng mà s s ho t đ ng cùng v i vi c thực thi h th ng. Các l p trong C++ đ
c ti n hóa tự nhiên c a khái ni m struct trong C. Tr c khi ti n hành vi c trình
bày các l p trong C++, chúng ta tìm hi u v c u trúc, và chúng ta xây dựng m t ki u do ng i dùng đ nh
nghƿa dựa trên m t c u trúc. II. CÀI Đ T M T KI U DO NG
I DÙNG Đ NH NGHƾA V I M T struct
Ví d 3.1: Chúng ta xây dựng ki u c u trúc Time v i ba thành viên s nguyên: Hour, Minutesecond. Ch
ng trình đ nh nghƿa m t c u trúc Time g i là DinnerTime. Ch ng trình in th i gian d i d ng gi quân đ i và d ng chu n. #include struct Time { int Hour; // 0-23 int Minute; // 0-59 int Second; // 0-59 };
void PrintMilitary(const Time &); //prototype
void PrintStandard(const Time &); //prototype int main() { Time DinnerTime;
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 40
//Thiet lap cac thanh vien voi gia tri hop le DinnerTime.Hour = 18; DinnerTime.Minute = 30; DinnerTime.Second = 0;
cout << "Dinner will be held at "; PrintMilitary(DinnerTime);
cout << " military time," << endl << "which is "; PrintStandard(DinnerTime);
cout << " standard time." << endl;
//Thiet lap cac thanh vien voi gia tri khong hop le DinnerTime.Hour = 29; DinnerTime.Minute = 73; DinnerTime.Second = 103;
cout << endl << "Time with invalid values: "; PrintMilitary(DinnerTime); cout << endl; return 0; }
//In thoi gian duoi dang gio quan doi
void PrintMilitary(const Time &T) {
cout << (T.Hour < 10 ? "0" : "") << T.Hour << ":"
<< (T.Minute < 10 ? "0" : "") << T.Minute << ":"
<< (T.Second < 10 ? "0" : "") << T.Second; }
//In thoi gian duoi dang chuan
void PrintStandard(const Time &T) {
cout << ((T.Hour == 12) ? 12 : T.Hour % 12)
<< ":" << (T.Minute < 10 ? "0" : "") << T.Minute
<< ":" << (T.Second < 10 ? "0" : "") << T.Second
<< (T.Hour < 12 ? " AM" : " PM"); }
Chúng ta ch y ví d 3.1, k t qu hình 3.1
Hình 3.1: K t qu c a ví d 3.1
Có m t vài h n ch khi t o các ki u d li u m i v i các c u trúc ph n trên. Khi vi c kh i t o không
đ c yêu c u, có th có d li u ch a kh i t o và các v n đ n y sinh. Ngay c n u d li u đ c kh i t o, nó
có th kh i t o không chính xác. Các giá tr không h p l có th đ
c gán cho các thành viên c a m t c u trúc b i vì ch
ng trình trực ti p truy c p d li u. Ch ng h n ví d 3.1 dòng 23 đ n dòng 25, ch ng
trình gán các giá tr không h p l cho đ i t
ng DinnerTime. N u vi c cài đ t c a struct thay đ i, t t c các ch
ng trình s d ng struct ph i thay đ i. Đi u này do l p trình viên trực ti p thao tác ki u d li u. Không
có "giao di n" đ b o đ m l p trình viên s d ng d li u chính xác và b o đ m d li u còn l i tr ng thái
thích h p. M t khác, c u trúc trong C không th đ c in nh m t đ n v , chúng đ c in khi các thành viên
đ c in. Các c u trúc trong C không th so sánh v i nhau, chúng ph i đ c so sánh thành viên v i thành viên.
Ph n sau cài đ t l i c u trúc Time ví d 3.1 nh m t l p và ch ng minh m t s thu n l i đ vi c t o ra
cái g i là các ki u d li u tr u t
ng (Abstract Data Types – ADT) nh các l p. Chúng ta s th y r ng các
l p và các c u trúc có th s d ng g n nh gi ng nhau trong C++. Sự khác nhau gi a chúng là thu c tính truy c p các thành viên.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 41 III. CÀI
Đ T M T KI U D LI U TR U T NG V I M T L P
Các l p cho phép l p trình viên mô hình các đ i t
ng mà có các thu c tính (bi u di n nh các thành
viên d li u – Data members) và các hành vi ho c các thao tác (bi u di n nh các hàm thành viên – Member
functions). Các ki u ch a các thành viên d li u và các hàm thành viên đ c đ nh nghƿa thông th ng trong
C++ s d ng t khóa class, có cú pháp nh sau: class { //Thân c a l p }; Trong đó: class-name: tên l p.
member-list: đ c t các thành viên d li u và các hàm thành viên.
Các hàm thành viên đôi khi đ c g i là các ph
ng th c (methods) trong các ngôn ng l p trình h ng
đ i t ng khác, và đ c đ a ra trong vi c đáp ng các message g i t i m t đ i t ng. M t message t ng
ng v i vi c g i hàm thành viên. Khi m t l p đ
c đ nh nghƿa, tên l p có th đ c s d ng đ khai báo đ i t ng c a l p theo cú pháp sau: ; Ch ng h n, c u trúc Time s đ c đ nh nghƿa d i d ng l p nh sau: class Time { public: Time(); void SetTime(int, int, int) void PrintMilitary(); void PrintStandard() private: int Hour; // 0 - 23 int Minute; // 0 - 59 int Second; // 0 - 59 };
Trong đ nh nghƿa l p Time ch a ba thành viên d li u là Hour, Minute và Second, và cũng trong l p
này, chúng ta th y các nhãn publicprivate đ
c g i là các thu c tính xác đ nh truy c p thành viên
(member access specifiers) g i t t là thu c tính truy c p.
B t kỳ thành viên d li u hay hàm thành viên khai báo sau public có th đ c truy c p b t kỳ n i nào mà ch
ng trình truy c p đ n m t đ i t
ng c a l p. B t kỳ thành viên d li u hay hàm thành viên khai báo
sau private ch có th đ
c truy c p b i các hàm thành viên c a l p. Các thu c tính truy c p luôn luôn k t
thúc v i d u hai ch m (:) và có th xu t hi n nhi u l n và theo th tự b t kỳ trong đ nh nghƿa l p. M c đ nh
thu c tính truy c p là private.
Đ nh nghƿa l p ch a các prototype c a b n hàm thành viên sau thu c tính truy c p public là Time(),
SetTime(), PrintMilitary() và PrintStandard(). Đó là các hàm thành viên public (public member function)
ho c giao di n (interface) c a l p. Các hàm này s đ
c s d ng b i các client (nghƿa là các ph n c a m t ch ng trình mà là các ng
i dùng) c a l p x lý d li u c a l p. Có th nh n th y trong đ nh nghƿa l p
Time, hàm thành viên Time() có cùng tên v i tên l p Time, nó đ
c g i là hàm xây dựng (constructor function) c a l p Time.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 42
M t constructor là m t hàm thành viên đ c bi t mà kh i đ ng các thành viên d li u c a m t đ i t ng
c a l p. M t constructor c a l p đ c g i tự đ ng khi đ i t ng c a l p đó đ c t o. Thông th
ng, các thành viên d li u đ
c li t kê trong ph n private c a m t l p, còn các hàm thành viên đ
c li t kê trong ph n public. Nh ng có th có các hàm thành viên private và thành viên d li u public. Khi l p đ
c đ nh nghƿa, nó có th s d ng nh m t ki u trong ph n khai báo nh sau: Time Sunset, // Đ i t ng c a l p Time
ArrayTimes[5], // M ng các đ i t ng c a l p Time
*PTime, // Con tr tr đ n m t đ i t ng c a l p Time
&DinnerTime = Sunset; // Tham chi u đ n m t đ i t ng c a l p Time
Ví d 3.2: Xây dựng l i l p Time ví d 3.1 1: #include 2: 3: class Time 4: { 5: public: 6: Time(); //Constructor
7: void SetTime(int, int, int); //Thiết l p Hour, Minute va Second
8: void PrintMilitary(); //In thời gian dưới dạng giờ quân đội
9: void PrintStandard(); //In thời gian dưới dạng chuẩn 10: private: 11: int Hour; // 0 - 23 12: int Minute; // 0 - 59 13: int Second; // 0 - 59 14: }; 15:
16: //Constructor khởi tạo mỗi thành viên DL với giá trị zero
17: //Bảo đảm tất cả các đối tượng bắt đầu ở một t.thái thích hợp 18: Time::Time() 19: {
20: Hour = Minute = Second = 0; 21: } 22:
23: //Thiết l p một giá trị Time mới sử dụng giờ quânđội
24: //Thực hiện việc ki m tra tính hợp lệ trên các giá trị dữ liệu
25: //Thiết l p các giá trị không hợp lệ thành zero
26: void Time::SetTime(int H, int M, int S) 27: {
28: Hour = (H >= 0 && H < 24) ? H : 0;
29: Minute = (M >= 0 && M < 60) ? M : 0;
30: Second = (S >= 0 && S < 60) ? S : 0; 31: } 32:
33: //In thời gian dưới dạng giờ quân đội
34: void Time::PrintMilitary() 35: {
36: cout << (Hour < 10 ? "0" : "") << Hour << ":"
37: << (Minute < 10 ? "0" : "") << Minute << ":"
38: << (Second < 10 ? "0" : "") << Second; 39: } 40:
41: //In thời gian dưới dạng chuẩn
42: void Time::PrintStandard()
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 43 43: {
44: cout << ((Hour == 0 || Hour == 12) ? 12 : Hour % 12)
44: << ":" << (Minute < 10 ? "0" : "") << Minute
45: << ":" << (Second < 10 ? "0" : "") << Second
46: << (Hour < 12 ? " AM" : " PM"); 48: } 49: 50: int main() 51: {
52: Time T; //Đối tượng T của lớp Time 53:
54: cout << "The initial military time is "; 55: T.PrintMilitary();
56: cout << endl << "The initial standard time is "; 57: T.PrintStandard(); 58: 59: T.SetTime(13, 27, 6);
60: cout << endl << endl << "Military time after SetTime is "; 61: T.PrintMilitary();
62: cout << endl << "Standard time after SetTime is "; 63: T.PrintStandard(); 64:
65: T.SetTime(99, 99, 99); //Thử thiết l p giá trị không hợp lệ
66: cout << endl << endl << "After attempting invalid settings:"
67: << endl << "Military time: "; 68: T.PrintMilitary();
69: cout << endl << "Standard time: "; 70: T.PrintStandard(); 71: cout << endl; 72: return 0; 73: }
Chúng ta ch y ví d 3.2, k t qu hình 3.2
Hình 3.2: K t qu c a ví d 3.2 Trong ví d 3.2, ch
ng trình thuy t minh m t đ i t
ng c a l p Time g i là T (dòng 52). Khi đó
constructor c a l p Time tự đ ng g i và rõ ràng kh i t o m i thành viên d li u private là zero. Sau đó th i gian đ c in d
i d ng gi quân đ i và d ng chu n đ xác nh n các thành viên này đ c kh i t o thích h p
(dòng 54 đ n 57). K t i th i gian đ
c thi t l p b ng cách s d ng hàm thành viên SetTime() (dòng 59) và th i gian l i đ
c in hai d ng (dòng 60 đ n 63). Cu i cùng hàm thành viên SetTime() (dòng 65) th thi t
l p các thành viên d li u v i các giá tr không h p l , và th i gian l i đ
c in hai d ng (dòng 66 đ n 70).
Chúng ta nh n th y r ng, t t c các thành viên d li u c a m t l p không th kh i t o t i n i mà chúng
đ c khai báo trong thân l p. Các thành viên d li u này ph i đ c kh i t o b i constructor c a l p hay
chúng có th gán giá tr b i các hàm thi t l p.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 44 Khi m t l p đ
c đ nh nghƿa và các hàm thành viên c a nó đ
c khai báo, các hàm thành viên này ph i
đ c đ nh nghƿa. M i hàm thành viên c a l p có th đ c đ nh nghƿa trực ti p trong thân l p (hi n nhiên bao
g m prototype hàm c a l p), ho c hàm thành viên có th đ
c đ nh nghƿa sau thân l p. Khi m t hàm thành viên đ
c đ nh nghƿa sau đ nh nghƿa l p t ng ng, tên hàm đ c đ t tr
c b i tên l p và toán t đ nh ph m
vi (::). Ch ng h n nh ví d 3.2 g m các dòng 18, 26, 34 và 42. B i vì các l p khác nhau có th có các tên
thành viên gi ng nhau, toán t đ nh ph m vi "ràng bu c" tên thành viên t i tên l p đ nh n d ng các hàm thành viên c a m t l p.
M c dù m t hàm thành viên khai báo trong đ nh nghƿa m t l p có th đ nh nghƿa bên ngoài đ nh nghƿa
l p này, hàm thành viên đó v n còn bên trong ph m vi c a l p, nghƿa là tên c a nó ch đ c bi t t i các
thành viên khác c a l p ngo i tr tham chi u thông qua m t đ i t
ng c a l p, m t tham chi u t i m t đ i t
ng c a l p, ho c m t con tr tr t i m t đ i t ng c a l p. N u m t hàm thành viên đ
c đ nh nghƿa trong đ nh nghƿa m t l p, hàm thành viên này chính là hàm
inline. Các hàm thành viên đ nh nghƿa bên ngoài đ nh nghƿa m t l p có th là hàm inline b ng cách s d ng t khóa inline.
Hàm thành viên cùng tên v i tên l p nh ng đ t tr
c là m t ký tự ngã (~) đ c g i là destructor c a l p
này. Hàm destructor làm "công vi c n i tr k t thúc" trên m i đ i t ng c a l p tr c khi vùng nh cho đ i t ng đ c ph c h i b i h th ng.
Ví d 3.3: L y l i ví d 3.2 nh ng hai hàm PrintMilitary() và PrintStandard() là các hàm inline. 1: #include 2: 3: class Time 4: { 5: public: 6: Time(); ; //Constructor
7: void SetTime(int, int, int); //Thiết l p Hour, Minute va Second
8: void PrintMilitary() // In thời gian dưới dạng giờ quânđội 9: {
10: cout << (Hour < 10 ? "0" : "") << Hour << ":"
11: << (Minute < 10 ? "0" : "") << Minute << ":"
12: << (Second < 10 ? "0" : "") << Second; 13: }
14: void PrintStandard(); // In thời gian dưới dạng chuẩn 15: private: 16: int Hour; // 0 - 23 17: int Minute; // 0 - 59 18: int Second; // 0 - 59 19: };
20: //Constructor khởi tạo mỗi thành viên dữ liệu với giá trị zero
21: //Bảo đảm t.cả các đối tượng bắt đầu ở một trạng thái thích hợp 22: Time::Time() 23: {
24: Hour = Minute = Second = 0; 25: } 26:
27: #9; //Thiết l p một giá trị Time mới sử dụng giờ quân đội
28: #9; //T.hiện việc k.tra tính hợp lệ trên các giá trị DL
29: #9; //Thiết l p các giá trị không hợp lệ thành zero
30: void Time::SetTime(int H, int M, int S) 31: {
32: Hour = (H >= 0 && H < 24) ? H : 0;
33: Minute = (M >= 0 && M < 60) ? M : 0;
34: Second = (S >= 0 && S < 60) ? S : 0;
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 45 35: } 36:
37: #9; //In thời gian dưới dạng chuẩn
38: inline void Time::PrintStandard() 39: {
40: cout << ((Hour == 0 || Hour == 12) ? 12 : Hour % 12)
41: << ":" << (Minute < 10 ? "0" : "") << Minute
42: << ":" << (Second < 10 ? "0" : "") << Second
43: << (Hour < 12 ? " AM" : " PM"); 44: } 45: 46: int main() 47: { 48: Time T; 49:
50: cout << "The initial military time is "; 51: T.PrintMilitary();
52: cout << endl << "The initial standard time is "; 53: T.PrintStandard(); 54: 55: T.SetTime(13, 27, 6);
56: cout << endl << endl << "Military time after SetTime is "; 57: T.PrintMilitary();
58: cout << endl << "Standard time after SetTime is "; 59: T.PrintStandard(); 60:
61: T.SetTime(99, 99, 99); //Thử thiết l p giá trị không hợp lệ
62: cout << endl << endl << "After attempting invalid settings:"
63: << endl << "Military time: "; 64: T.PrintMilitary();
65: cout << endl << "Standard time: "; 66: T.PrintStandard(); 67: cout << endl; 68: return 0; 69: }
Chúng ta ch y ví d 3.3, k t qu hình 3.3
Hình 3.3: K t qu c a ví d 3.3
IV. PH M VI L P VÀ TRUY C P CÁC THÀNH VIÊN L P
Các thành viên d li u c a m t l p (các bi n khai báo trong đ nh nghƿa l p) và các hàm thành viên (các
hàm khai báo trong đ nh nghƿa l p) thu c vào ph m vi c a l p.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 46
Trong m t ph m vi l p, các thành viên c a l p đ
c truy c p ngay l p t c b i t t c các hàm thành viên c a l p đó và có th đ
c tham chi u m t cách d dàng b i tên. Bên ngoài m t ph m vi l p, các thành viên c a l p đ
c tham chi u thông qua ho c m t tên đ i t
ng, m t tham chi u đ n m t đ i t ng, ho c m t con tr t i đ i t ng.
Các hàm thành viên c a l p có th đ
c đa nĕng hóa (overload), nh ng ch b i các hàm thành viên khác
c a l p. Đ đa nĕng hóa m t hàm thành viên, đ n gi n cung c p trong đ nh nghƿa l p m t prototype cho m i
phiên b n c a hàm đa nĕng hóa, và cung c p m t đ nh nghƿa hàm riêng bi t cho m i phiên b n c a hàm.
Các hàm thành viên có ph m vi hàm trong m t l p – các bi n đ nh nghƿa trong m t hàm thành viên ch
đ c bi t t i hàm đó. N u m t hàm thành viên đ nh nghƿa m t bi n cùng tên v i tên m t bi n trong ph m vi l p, bi n ph m vi l p đ
c d u b i bi n ph m vi hàm bên trong ph m vi hàm. Nh th m t bi n b d u có th đ
c truy c p thông qua toán t đ nh ph m vi. Các toán t đ
c s d ng đ truy c p các thành viên c a l p đ
c đ ng nh t v i các toán t s d ng đ
truy c p các thành viên c a c u trúc. Toán t lựa ch n thành viên d u ch m (.) đ c k t h p v i m t tên c a
đ i t ng hay v i m t tham chi u t i m t đ i t ng đ truy c p các thành viên c a đ i t ng. Toán t lựa
ch n thành viên mũi tên (->
c k t h p v i m t con tr tr t i m t truy c p đ truy c p các thành viên c a đ i t ng. Ví d 3.4: Ch
ng trình sau minh h a vi c truy c p các thành viên c a m t l p v i các toán t lựa ch n thành viên. 1: #include 2: 3: class Count 4: { 5: public: 6: int X; 7: void Print() 8: {
9: cout << X << endl; 10: } 11: }; 12: 13: int main() 14: {
15: Count Counter, //Tạo đối tượng Counter
16: *CounterPtr = &Counter, //Con trỏ trỏ tới Counter
17: &CounterRef = Counter; //Tham chiếu tới Counter 18:
19: cout << "Assign7 to X and Print using the object's name: ";
20: Counter.X = 7; //Gán 7 cho thành viên dữ liệu X
21: Counter.Print(); //Gọi hàm thành viên Print 22:
23: cout << "Assign 8 to X and Print using a reference: ";
24: CounterRef.X = 8; //Gán 8 cho thành viên dữ liệu X
25: CounterRef.Print(); //Gọi hàm thành viên Print 26:
27: cout << "Assign 10 to X and Print using a pointer: ";
28: CounterPtr->X = 10; // Gán 10 cho thành viên dữ liệu X
29: CounterPtr->Print(); //Gọi hàm thành viên Print 30: return 0; 31: }
Chúng ta ch y ví d 3.4, k t qu hình 3.4
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 47
Hình 3.4: K t qu c a ví d 3.4 V.
ĐI U KHI N TRUY C P T I CÁC THÀNH VIÊN
Các thu c tính truy c p public private (và protected chúng ta s xem xét sau) đ c s d ng đ đi u
khi n truy c p t i các thành viên d li u và các hàm thành viên c a l p. Ch đ truy c p m c đ nh đ i v i
l p là private vì th t t c các thành viên sau ph n header c a l p và tr
c nhãn đ u tiên là private. Sau m i nhãn, ch đ mà đ
c kéo theo b i nhãn đó áp d ng cho đ n khi g p nhãn k ti p ho c cho đ n khi g p d u
móc ph i (}) c a ph n đ nh nghƿa l p. Các nhãn public, private protected có th đ c l p l i nh ng cách
dùng nh v y thì hi m có và có th gây khó hi u.
Các thành viên private ch có th đ
c truy c p b i các hàm thành viên (và các hàm friend) c a l p đó.
Các thành viên public c a l p có th đ
c truy c p b i b t kỳ hàm nào trong ch ng trình.
M c đích chính c a các thành viên public là đ bi u th cho client c a l p m t cái nhìn c a các d ch v
(services) mà l p cung c p. T p h p này c a các d ch v hình thành giao di n public c a l p. Các client c a
l p không c n quan tâm làm th nào l p hoàn thành các thao tác c a nó. Các thành viên private c a l p
cũng nh các đ nh nghƿa c a các hàm thành viên public c a nó thì không ph i có th truy c p t i client c a
m t l p. Các thành ph n này hình thành sự thi hành c a l p. Ví d 3.5: Ch
ng trình sau cho th y r ng các thành viên private ch có th truy c p thông qua giao
di n public s d ng các hàm thành viên public. #include class MyClass { private: int X,Y; public: void Print(); }; void MyClass::Print() { cout <} int main() { MyClass M; M.X = 3; M.Y = 4; M.Print(); return 0; } Khi chúng ta biên d ch ch
ng trình này, compiler phát sinh ra hai l i t i hai dòng 20 và 21 nh sau:
Hình 3.5: Thông báo l i c a ví d 3.5
Thu c tính truy c p m c đ nh đ i v i các thành viên c a l p là private. Thu c tính truy c p các thành viên c a m t l p có th đ
c thi t l p rõ ràng là public, protected ho c private. Thu c tính truy c p m c
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 48
đ nh đ i v i các thành viên c a struct public. Thu c tính truy c p các thành viên c a m t struct cũng có th đ
c thi t l p rõ ràng là public, protected ho c private.
Truy c p đ n m t d li u private c n ph i đ
c đi u khi n c n th n b i vi c s d ng c a các hàm thành
viên, g i là các hàm truy c p (access functions).
VI. CÁC HÀM TRUY C P VÀ CÁC HÀM TI N ÍCH
Không ph i t t c các hàm thành viên đ u là public đ ph c v nh b ph n giao di n c a m t l p. M t
vài hàm còn l i là private và ph c v nh các hàm ti n ích (utility functions) cho các hàm khác c a l p.
Các hàm truy c p có th đ c hay hi n th d li u. S d ng các hàm truy c p đ ki m tra tính đúng ho c
sai c a các đi u ki n – các hàm nh th th ng đ
c g i là các hàm kh ng đ nh (predicate functions). M t ví
d c a hàm kh ng đ nh là m t hàm IsEmpty() c a l p container - m t l p có kh nĕng gi nhi u đ i t ng -
gi ng nh m t danh sách liên k t, m t stack hay m t hàng đ i. M t ch
ng trình s ki m tra hàm IsEmpty() tr
c khi th đ c m c khác t đ i t ng container.
M t hàm ti n ích không là m t ph n c a m t giao di n c a l p. H n n a nó là m t hàm thành viên
private mà h tr các thao tác c a các hàm thành viên public. Các hàm ti n ích không dự đ nh đ c s d ng b i các client c a l p.
Ví d 3.6: Minh h a cho các hàm ti n ích. 1: #include 2: #include 3: 4: class SalesPerson 5: { 6: public:
7: SalesPerson(); //constructor
8: void SetSales(int, double);//Ng.dùng cung cấp các hình của
9: #9; #9; //những hàng bán của một tháng 10: void PrintAnnualSales(); 11: 12: private:
13: double Sales[12]; //12 hình của những hàng bán hằng tháng
14: double TotalAnnualSales(); //Hàm tiện ích 15: }; 16:
17: //Hàm constructor khởi tạo mảng
18: SalesPerson::SalesPerson() 19: {
20: for (int I = 0; I < 12; I++) 21: Sales[I] = 0.0; 22: } 23:
24://Hàm th.l p một trong 12 hình của những hàng bán hằng tháng
25: void SalesPerson::SetSales(int Month, double Amount) 26: {
27: if (Month >= 1 && Month <= 12 && Amount > 0)
28: Sales[Month - 1] = Amount; 29: else
30: cout << "Invalid month or sales figure" << endl; 31: } 32:
33: //Hàm tiện íchđ tính tổng hàng bán hằng năm
34: double SalesPerson::TotalAnnualSales() 35: { 36: double Total = 0.0; 37:
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 49
38: for (int I = 0; I < 12; I++) 39: Total += Sales[I]; 40: return Total; 41: } 42:
43: //In tổng hàng bán hằng năm
44: void SalesPerson::PrintAnnualSales() 45: {
46: cout << setprecision(2)
47: << setiosflags(ios::fixed | ios::showpoint)
48: << endl << "The total annual sales are: $"
49: << TotalAnnualSales() << endl; 50: } 51: 52: int main() 53: { 54: SalesPerson S; 55: double salesFigure; 56:
57: for (int I = 1; I <= 12; I++) 58: {
59: cout << "Enter sales amount for month "<< I << ": "; 60: cin >> salesFigure;
61: S.SetSales(I, salesFigure); 62: } 63: S.PrintAnnualSales(); 64: return 0; 65: }
Chúng ta ch y ví d 3.6 , k t qu hình 3.6
Hình 3.6: K t qu c a ví d 3.6
VII. KH I Đ NG CÁC Đ I T
NG C A L P : CONSTRUCTOR Khi m t đ i t ng đ
c t o, các thành viên c a nó có th đ
c kh i t o b i m t hàm constructor. M t
constructor là m t hàm thành viên v i tên gi ng nh tên c a l p. L p trình viên cung c p constructor mà
đ c g i tự đ ng m i khi đ i t ng c a l p đó đ c t o. Các thành viên d li u c a m t l p không th đ c
kh i t o trong đ nh nghƿa c a l p. H n n a, các thành viên d li u ph i đ c kh i đ ng ho c trong m t
constructor c a l p ho c các giá tr c a chúng có th đ c thi t l p sau sau khi đ i t ng đ c t o. Các
constructor không th mô t các ki u tr v ho c các giá tr tr v . Các constructor có th đ c đa nĕng hóa
đ cung c p sự đa d ng đ kh i t o các đ i t ng c a l p.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 50
Constructor có th ch a các tham s m c đ nh. B ng cách cung c p các tham s m c đ nh cho
constructor, ngay c n u không có các giá tr nào đ
c cung c p trong m t constructor thì đ i t ng v n
đ c b o đ m đ trong m t tr ng thái phù h p vì các tham s m c đ nh. M t constructor c a l p trình viên
cung c p mà ho c t t c các tham s c a nó có giá tr m c đ nh ho c không có tham s nào đ c g i là
constructor m c đ nh (default constructor). Ch có th có m t constructor m c đ nh cho m i l p.
Ví d 3.7: Constructor v i các tham s m c đ nh #include class Time { public:
Time(int = 0, int = 0, int = 0); //Constructor mac dinh void SetTime(int, int, int); void PrintMilitary(); void PrintStandard(); private: int Hour; int Minute; int Second; };
//Ham constructor de khoi dong du lieu private //Cac gia tri mac dinh la 0
Time::Time(int Hr, int Min, int Sec) { SetTime(Hr, Min, Sec); }
//Thiet lap cac gia tri cua Hour, Minute va Second
//Gia tri khong hop le duoc thiet lap la 0
void Time::SetTime(int H, int M, int S) {
Hour = (H >= 0 && H < 24) ? H : 0;
Minute = (M >= 0 && M < 60) ? M : 0;
Second = (S >= 0 && S < 60) ? S : 0; }
//Hien thi thoi gian theo dang gio quan doi: HH:MM:SS void Time::PrintMilitary() {
cout << (Hour < 10 ? "0" : "") << Hour << ":"
<< (Minute < 10 ? "0" : "") << Minute << ":"
<< (Second < 10 ? "0" : "") << Second; }
//Hien thi thoi gian theo dang chuan: HH:MM:SS AM (hoac PM) void Time::PrintStandard() {
cout << ((Hour == 0 || Hour == 12) ? 12 : Hour % 12)
<< ":" << (Minute < 10 ? "0" : "") << Minute
<< ":" << (Second < 10 ? "0" : "") << Second
<< (Hour < 12 ? " AM" : " PM"); }
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 51 int main() {
Time T1,T2(2),T3(21,34),T4(12,25,42),T5(27,74,99);
cout << "Constructed with:" << endl << "all arguments defaulted:" << endl << " "; T1.PrintMilitary();
cout << endl << " "; T1.PrintStandard();
cout << endl << "Hour specified; Minute and Second defaulted:" << endl << " "; T2.PrintMilitary();
cout << endl << " "; T2.PrintStandard();
cout << endl << "Hour and Minute specified; Second defaulted:" << endl << " "; T3.PrintMilitary();
cout << endl << " ";
T3.PrintStandard(); cout << endl << "Hour, Minute, and Second specified:"< T4.PrintMilitary();
cout << endl << " ";
T4.PrintStandard(); cout << endl << "all invalid values specified:" << endl << " "; T5.PrintMilitary();
cout << endl << " ";
T5.PrintStandard(); cout << endl; return 0; } Ch
ng trình ví d 3.7 kh i t o nĕm đ i t
ng c a l p Time ( dòng 52). Đ i t ng T1 v i ba tham s l y giá tr m c đ nh, đ i t ng T2 v i m t tham s đ c mô t , đ i t ng T3 v i hai tham s đ c mô t , đ i t ng T4 v i ba tham s đ c mô t và đ i t
ng T5 v i các tham s có giá tr không h p l .
Chúng ta ch y ví d 3.7, k t qu hình 3.7
Hình 3.7: K t qu c a ví d 3.7
N u không có constructor nào đ
c đ nh nghƿa trong m t l p thì trình biên d ch t o m t constructor m c
đ nh. Constructor này không thực hi n b t kỳ sự kh i t o nào, vì v y khi đ i t ng đ c t o, nó không b o
đ m đ trong m t tr ng thái phù h p.
VIII. S D NG DESTRUCTOR
M t destructor là m t hàm thành viên đ c bi t c a m t l p. Tên c a destructor đ i v i m t l p là ký tự
ngã (~) theo sau b i tên l p.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 52 Destructor c a m t l p đ c g i khi đ i t ng đ
c h y b nghƿa là khi sự thực hi n ch ng trình r i
kh i ph m vi mà trong đó đ i t ng c a l p đó đ
c kh i t o. Destructor không thực sự h y b đ i t ng –
nó thực hi n "công vi c n i tr k t thúc" tr
c khi h th ng ph c h i không gian b nh c a đ i t ng đ nó có th đ c s d ng gi các đ i t ng m i.
M t destructor không nh n các tham s và không tr v giá tr . M t l p ch có duy nh t m t destructor –
đa nĕng hóa destructor là không cho phép.
N u trong m t l p không có đ nh nghƿa m t destructor thì trình biên d ch s t o m t destructor m c đ nh không làm gì c .
Ví d 3.8: L p có hàm destructor #include class Simple {private: int *X; public: Simple(); //Constructor ~Simple(); //Destructor void SetValue(int V); int GetValue(); }; Simple::Simple()
{ X = new int; //Cấp phát vùng nhớ cho X } Simple::~Simple() {
delete X; //Giải phóng vùng nhớ khi đối tượng bị hủy bỏ. } void Simple::SetValue(int V) { *X = V; } int Simple::GetValue() { return *X; } int main() { Simple S; int X;
cout<<"Enter a number:"; cin>>X; S.SetValue(X);
cout<<"The value of this number:"< return 0; }
Chúng ta ch y ví d 3.8, k t qu hình 3.8
Hình 3.8: K t qu c a ví d 3.8
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 53
IX. KHI NÀO CÁC CONSTRUTOR VÀ DESTRUCTOR Đ C G I ?
Các constructor và destructor đ
c g i m t cách tự đ ng. Th tự các hàm này đ c g i ph thu c vào
th tự trong đó sự thực hi n vào và r i kh i ph m vi mà các đ i t ng đ
c kh i t o. M t cách t ng quát, các destructor đ c g i theo th tự ng
c v i th tự c a các constructor đ c g i. Các constructor đ c g i c a các đ i t
ng khai báo trong ph m vi toàn c c tr c b t kỳ hàm nào (bao
g m hàm main()) trong file mà b t đ u thực hi n. Các destructor t ng ng đ
c g i khi hàm main() k t
thúc ho c hàm exit() đ c g i.
Các constructor c a các đ i t ng c c b tự đ ng đ
c g i khi sự thực hi n đ n đi m mà các đ i t ng
đ c khai báo. Các destructor t ng ng đ c g i khi các đ i t ng r i kh i ph m vi (nghƿa là kh i mà trong đó chúng đ
c khai báo). Các constructor và destructor đ i v i các đ i t ng c c b tự đ ng đ c g i m i khi các đ i t ng vào và r i kh i ph m vi. Các constructor đ c g i c a các đ i t
ng c c b tƿnh (static) khi sự thực hi n đ n đi m mà các đ i t ng đ
c khai báo l n đ u tiên. Các destructor t ng ng đ
c g i khi hàm main() k t thúc ho c hàm exit() đ c g i. Ví d 3.9: Ch
ng trình sau minh h a th tự các constructor và destructor đ c g i. #include class CreateAndDestroy { public: CreateAndDestroy(int); //Constructor
~CreateAndDestroy(); //Destructor private: int Data; };
CreateAndDestroy::CreateAndDestroy(int Value) { Data = Value;
cout << "Object " << Data << " constructor"; }
CreateAndDestroy::~CreateAndDestroy() {
cout << "Object " << Data << " destructor " << endl; }
void Create(void); //Prototype
CreateAndDestroy First(1); //Doi tuong toan cuc int main() {
cout << " (global created before main)" << endl;
CreateAndDestroy Second(2); //Doi tuong cuc bo
cout << " (local automatic in main)" << endl;
static CreateAndDestroy Third(3); //Doi tuong cuc bo
cout << " (local static in main)" << endl;
Create(); //Goi ham de tao cac doi tuong
CreateAndDestroy Fourth(4); //Doi tuong cuc bo
cout << " (local automatic in main)" << endl; return 0; } //Ham tao cac doi tuong void Create(void) { CreateAndDestroy Fifth(5);
cout << " (local automatic in create)" << endl;
static CreateAndDestroy Sixth(6);
cout << " (local static in create)" << endl;
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 54 CreateAndDestroy Seventh(7);
cout << " (local automatic in create)" << endl; } Ch
ng trình khai báo First ph m vi toàn c c. Constructor c a nó đ c g i khi ch ng trình b t đ u
thực hi n và destructor c a nó đ c g i lúc ch
ng trình k t thúc sau t t c các đ i t ng khác đ c h y b .
Hàm main() khai báo ba đ i t ng. Các đ i t
ng Second Fourth là các đ i t ng c c b tự đ ng và đ i t ng Third là m t đ i t
ng c c b tƿnh. Các constructor c a các đ i t ng này đ c g i khi ch ng trình
thực hi n đ n đi m mà m i đ i t ng đ
c khai báo. Các destructor c a các đ i t
ng Fourth Second
đ c g i theo th tự này khi k t thúc c a main() đ t đ n. Vì đ i t ng Third là tƿnh, nó t n t i cho đ n khi ch
ng trình k t thúc. Destructor c a đ i t ng Third đ c g i tr
c destructor c a First nh ng sau t t c các đ i t ng khác đ c h y b .
Hàm Create() khai báo ba đ i t
ng – Fifth Seventh là các đ i t
ng c c b tự đ ng và Sixth là m t
đ i t ng c c b tƿnh. Các destructor c a các đ i t ng Seventh và Fifth đ c g i theo th tự này khi k t
thúc c a create() đ t đ n. Vì đ i t
ng Sixth là tƿnh, nó t n t i cho đ n khi ch
ng trình k t thúc. Destructor c a đ i t ng Sixth đ c g i tr
c các destructor c a Third First nh ng sau t t c các đ i t ng khác đ c h y b .
Chúng ta ch y ví d 3.9, k t qu hình 3.9
Hình 3.9: K t qu c a ví d 3.9
X. S D NG CÁC THÀNH VIÊN D LI U VÀ CÁC HÀM THÀNH VIÊN
Các thành viên d li u private ch có th đ
c x lý b i các hàm thành viên (hay hàm friend) c a l p. Các l p th
ng cung c p các hàm thành viên public đ cho phép các client c a l p đ thi t l p (set) (nghƿa là
"ghi") ho c l y (get) (nghƿa là "đ c") các giá tr c a các thành viên d li u private. Các hàm này th ng không c n ph i đ
c g i "set" hay "get", nh ng chúng th
ng đ t tên nh v y. Ch ng h n, m t l p có thành
viên d li u private có tên InterestRate, hàm thành viên thi t l p giá tr có tên là SetInterestRate() và hàm
thành viên l y giá tr có tên là GetInterestRate(). Các hàm "Get" cũng th ng đ c g i là các hàm ch t v n (query functions).
N u m t thành viên d li u là public thì thành viên d li u có th đ
c đ c ho c ghi t i b t kỳ hàm nào trong ch
ng trình. N u m t thành viên d li u là private, m t hàm "get" public nh t đ nh cho phép các hàm
khác đ đ c d li u nh ng hàm get có th đi u khi n sự đ nh d ng và hi n th c a d li u. M t hàm "set"
public có th s xem xét c n th n b t kỳ c g ng nào đ thay đ i giá tr c a thành viên d li u. Đi u này s
b o đ m r ng giá tr m i thì t
ng thích đ i v i m c d li u. Ch ng h n, m t sự c g ng thi t l p ngày c a tháng là 37 s b lo i tr .
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 55
Các l i ích c a sự toàn vẹn d li u thì không tự đ ng đ n gi n b i vì các thành viên d li u đ c t o là
private – l p trình viên ph i cung c p sự ki m tra h p l . Tuy nhiên C++ cung c p m t khung làm vi c trong
đó các l p trình viên có th thi t k các ch ng trình t t h n. Client c a l p ph i đ
c thông báo khi m t sự c g ng đ
c t o ra đ gán m t giá tr không h p l cho
m t thành viên d li u. Chính vì lý do này, các hàm "set" c a l p th ng đ
c vi t tr v các giá tr cho bi t
r ng m t sự c g ng đã t o ra đ gán m t d li u không h p l cho m t đ i t ng c a l p. Đi u này cho
phép các client c a l p ki m tra các giá tr tr v đ xác đ nh n u đ i t
ng mà chúng thao tác là m t đ i t
ng h p l và đ b t gi ho t đ ng thích h p n u đ i t
ng mà chúng thao tác thì không ph i h p l . Ví d 3.10: Ch
ng trình m r ng l p Time ví d 3.2 bao g m hàm get và set đ i v i các thành viên
d li u private là hour, minute second. 1: #include 2: 3: class Time 4: { 5: public:
6: Time(int = 0, int = 0, int = 0); //Constructor 7: //Các hàm set
8: void SetTime(int, int, int); //Thiết l p Hour, Minute, Second
9: void SetHour(int); //Thiết l p Hour
10: void SetMinute(int); //Thiết l p Minute
11: void SetSecond(int); //Thiết l p Second 12: //Các hàm get
13: int GetHour(); //Trả v Hour
14: int GetMinute(); //Trả v Minute
15: int GetSecond(); //Trả v Second 16:
17: void PrintMilitary(); //Xuất thời gian theo dạng giờ quânđội
18: void PrintStandard(); //Xuất thời gian theo dạng chuẩn 19: 20: private: 21: int Hour; //0 - 23 22: int Minute; //0 - 59 23: int Second; //0 – 59 24: }; 25:
26: //Constructor khởiđộng dữ liệu private
27: //Gọi hàm thành viên SetTime() đ thiết l p các biến
24: //Các giá trị mặc định là 0
25: Time::Time(int Hr, int Min, int Sec) 26: { 27: SetTime(Hr, Min, Sec); 28: } 29:
30: //Thiết l p các giá trị của Hour, Minute, và Second
31: void Time::SetTime(int H, int M, int S) 32: {
33: Hour = (H >= 0 && H < 24) ? H : 0;
34: Minute = (M >= 0 && M < 60) ? M : 0;
35: Second = (S >= 0 && S < 60) ? S : 0; 36: } 37:
38: //Thiết l p giá trị của Hour 39: void Time::SetHour(int H) 40: {
41: Hour = (H >= 0 && H < 24) ? H : 0; 42: }
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 56 43:
44: //Thiết l p giá trị của Minute
45: void Time::SetMinute(int M) 46: {
47: Minute = (M >= 0 && M < 60) ? M : 0; 48: } 49:
50: //Thiết l p giá trị của Second
51: void Time::SetSecond(int S) 52: {
53: Second = (S >= 0 && S < 60) ? S : 0; 54: } 55:
56: //Lấy giá trị của Hour 57: int Time::GetHour() 58: { 59: return Hour; 60: } 61:
62: //Lấy giá trị của Minute 63: int Time::GetMinute() 64: { 65: return Minute; 66: } 67:
68: //Lấy giá trị của Second 69: int Time::GetSecond() 70: { 71: return Second; 72: } 73:
74: //Hi n thị thời gian dạng giờ quânđội: HH:MM:SS
75: void Time::PrintMilitary() 76: {
77: cout << (Hour < 10 ? "0" : "") << Hour << ":"
78: << (Minute < 10 ? "0" : "") << Minute << ":"
79: << (Second < 10 ? "0" : "") << Second; 80: } 81:
83: //Hi n thị thời gian dạng chuẩn: HH:MM:SS AM (hay PM)
84: void Time::PrintStandard() 85: {
86: cout << ((Hour == 0 || Hour == 12) ? 12 : Hour % 12) << ":"
87: << (Minute < 10 ? "0" : "") << Minute << ":"
88: << (Second < 10 ? "0" : "") << Second
89: << (Hour < 12 ? " AM" : " PM"); 90: } 91:
92: void IncrementMinutes(Time &, const int); //prototype 93: 94: int main() 95: { 96: Time T; 97: 99: T.SetHour(17); 100: T.SetMinute(34); 101: T.SetSecond(25);
102 cout << "Result of setting all valid values:" << endl
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 57
103: << " Hour: " << T.GetHour()
104: << " Minute: " << T.GetMinute()
105: << " Second: " << T.GetSecond() << endl << endl;
106: T.SetHour(234); //Hour không hợp lệđược thiết l p bằng 0 107: T.SetMinute(43);
108: T.SetSecond(6373); //Second không hợp lệđược thiết l p bằng 0
109: cout << "Result of attempting to set invalid Hour and"
110: << " Second:" << endl << " Hour: " << T.GetHour()
111: << " Minute: " << T.GetMinute()
112: << " Second: " << T.GetSecond() << endl << endl; 113: T.SetTime(11, 58, 0); 114: IncrementMinutes(T, 3); 115: return 0; 116: } 117:
118: void IncrementMinutes(Time &TT, const int Count) 119: {
120: cout << "Incrementing Minute " << Count
121: << " times:" << endl << "Start time: "; 122: TT.PrintStandard();
123: for (int I = 1; I <= Count; I++) 124: {
125: TT.SetMinute((TT.GetMinute() + 1) % 60); 126: if (TT.GetMinute() == 0)
127: TT.SetHour((TT.GetHour() + 1) % 24);
128: cout << endl << "Minute + 1: "; 129: TT.PrintStandard(); 130: } 131: cout << endl; 132: }
Trong ví d trên chúng ta có hàm IncrementMinutes() là hàm dùng đ tĕng Minite. Đây là hàm không
thành viên mà s d ng các hàm thành viên get và set đ tĕng thành viên Minite.
Chúng ta ch y ví d .10, k t qu hình 3.10
Hình 3.10: K t qu c a ví d 3.10
XI. TR V M T THAM CHI U T I M T THÀNH VIÊN D LI U PRIVATE M t tham chi u t i m t đ i t
ng là m t bí danh c a chính đ i t ng đó và do đó có th đ c s d ng
v trái c a phép gán. Trong khung c nh đó, tham chi u t o m t lvalue đ
c ch p nh n hoàn toàn mà có th
nh n m t giá tr . M t cách đ s d ng kh nĕng này (th t không may!) là có m t hàm thành viên public c a
l p tr v m t tham chi u không const t i m t thành viên d li u private c a l p đó.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 58 Ví d 3.11: Ch
ng trình sau s d ng m t phiên b n đ n gi n c a l p Time đ minh h a tr v m t
tham chi u t i m t d li u private. 1: #include 2: 3: class Time 4: { 5: public:
6: Time(int = 0, int = 0, int = 0);
7: void SetTime(int, int, int); 8: int GetHour();
9: int &BadSetHour(int); //Nguy hi m trả v tham chiếu !!! 10: private: 11: int Hour; 12: int Minute; 13: int Second; 14: }; 15:
16: //Constructor khởiđộng dữ liệu private
17: //Gọi hàm thành viên SetTime()đ thiết l p các biến
18: //Các giá trị mặcđịnh là 0
19: Time::Time(int Hr, int Min, int Sec) 20: { 21: SetTime(Hr, Min, Sec); 22: }
23: //Thiết l p các giá trị của Hour, Minute, và Second
24: void Time::SetTime(int H, int M, int S) 25: {
26: Hour = (H >= 0 && H < 24) ? H : 0;
27: Minute = (M >= 0 && M < 60) ? M : 0;
28: Second = (S >= 0 && S < 60) ? S : 0; 29: } 30:
31: //Lấy giá trị của Hour 32: int Time::GetHour() 33: { 34: return Hour; 35: } 36:
37: //KHÔNG NÊN L P TRÌNH THEO KI U NÀY !!!
38: //Trả v một tham chiếu tới một thành viên dữ liệu private
39: int &Time::BadSetHour(int HH) 40: {
41: Hour = (HH >= 0 && HH < 24) ? HH : 0;
42: return Hour; //Nguy hi m trả v tham chiếu !!! 43: } 44: 45: int main() 46: { 47: Time T;
48: int &HourRef = T.BadSetHour(20); 49:
50: cout << "Hour before modification: " << HourRef << endl;
51: HourRef = 30; //Thayđổi với giá trị không hợp lệ
52: cout << "Hour after modification: " << T.GetHour() << endl;
53: // Nguy hi m: Hàm trả v một tham chiếu
54: //có th được sử dụng như một lvalue 55: T.BadSetHour(12) = 74;
56: cout << endl << "*********************************" << endl
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 59
57: << "BAD PROGRAMMING PRACTICE!!!!!!!!!" << endl
58: << "BadSetHour as an lvalue, Hour: " 59: << T.GetHour()
60: << endl << "*********************************" << endl; 61: return 0; 62: } Trong ch
ng trình hàm BadSetHour() tr v m t tham chi u t i thành viên d li u Hour.
Chúng ta ch y ví d 3.11, k t qu hình 3.11
Hình 3.11: K t qu c a ví d 3.11
XII. PHÉP GÁN B I TOÁN T SAO CHÉP THÀNH VIÊN M C Đ NH Toán t gán (=) đ c s d ng đ gán m t đ i t ng cho m t đ i t
ng khác c a cùng m t ki u. Toán t gán nh th bình th ng đ
c thực hi n b i toán t sao chép thành viên (Memberwise copy) – M i thành viên c a m t đ i t ng đ
c sao chép riêng r t i cùng thành viên đ i t
ng khác (Chú ý r ng sao chép
thành viên có th phát sinh các v n đ nghiêm tr ng khi s d ng v i m t l p mà thành viên d li u ch a vùng nh c p phát đ ng). Các đ i t ng có th đ
c truy n cho các tham s c a hàm và có th đ c tr v t các hàm. Nh th vi c truy n và tr v đ
c thực hi n theo truy n giá tr – m t sao chép c a đ i t ng đ c truy n hay tr v .: Ví d 3.12: Ch
ng trình sau minh h a toán t sao chép thành viên m c đ nh 2: #include 3: //Lớp Date đơn giản 4: class Date 5: { 6: public:
7: Date(int = 1, int = 1, int = 1990); //Constructor mặc định 8: void Print(); 9: private: 10: int Month; 11: int Day; 12: int Year; 13: }; 14:
15: //Constructor Date đơn giản với việc không ki m tra mi n
16: Date::Date(int m, int d, int y) 17: { 18: Month = m; 19: Day = d; 20: Year = y; 21: } 22:
23: //In Date theo dạng mm-dd-yyyy 24: void Date::Print() 25: {
26: cout << Month << '-' << Day << '-' << Year; 27: }
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 60 28: 29: int main() 30: {
31: Date Date1(7, 4, 1993), Date2; //Date2 mặc định là 1/1/90 32: cout << "Date1 = "; 33: Date1.Print();
34: cout << endl << "Date2 = "; 35: Date2.Print();
36: Date2 = Date1; //Gán bởi toán tử sao chép thành viên mặc định
37: cout << endl << endl
38: << "After default memberwise copy, Date2 = "; 39: Date2.Print(); 40: cout << endl; 41: return 0; 42: }
Chúng ta ch y ví d 3.12, k t qu hình 3.12
Hình 3.12: K t qu c a ví d 3.12 XIII. CÁC Đ I T
NG HẰNG VÀ CÁC HÀM THÀNH VIÊN CONST M t vài đ i t ng c n đ
c thay đ i và m t vài đ i t
ng thì không. L p trình viên có th s d ng t
khóa const đ cho bi t đ i t ng không th thay đ i đ
c, và n u có c g ng thay đ i đ i t ng thì x y ra l i. Ch ng h n:
const Time Noon(12,0,0); //Khai báo m t đ i t ng const
Các trình biên d ch C++ l u ý đ n các khai báo const vì th các trình biên d ch c m hoàn toàn b t kỳ
hàm thành viên nào g i các đ i t
ng const (M t vài trình biên d ch ch cung c p m t c nh báo). Đi u này
thì kh c nghi t b i vì các client c a đ i t
ng h u nh ch c ch n s mu n s d ng các hàm thành viên "get" khác nhau v i đ i t
ng, và t t nhiên không th thay đ i đ i t
ng. Đ cung c p cho đi u này, l p trình viên
có th khai báo các hàm thành viên const; đi u này ch có th thao tác trên các đ i t
ng const. Dƿ nhiên các
hàm thành viên const không th thay đ i đ i t
ng - trình biên d ch c m đi u này. M t hàm đ
c mô t nh const khi c hai trong ph n khai báo và trong ph n đ nh nghƿa c a nó đ c
chèn thêm t khóa const sau danh sách các tham s c a hàm, và trong tr
ng h p c a đ nh nghƿa hàm tr c
d u ngo c móc trái ({) mà b t đ u thân hàm. Ch ng h n, hàm thành viên c a l p A nào đó: int A::GetValue() const { return PrivateDataMember; }
N u m t hàm thành viên const đ
c đ nh nghƿa bên ngoài đ nh nghƿa c a l p thì khai báo hàm và đ nh
nghƿa hàm ph i bao g m const m i ph n.
M t v n đ n y sinh đây đ i v i các constructor và destructor, m i hàm th ng c n thay đ i đ i t
ng. Khai báo const không yêu c u đ i v i các constructor và destructor c a các đ i t ng const. M t constructor ph i đ c phép thay đ i m t đ i t ng mà đ i t ng có th đ c kh i t o thích h p. M t
destructor ph i có kh nĕng thực hi n vai trò "công vi c k t thúc n i tr " tr c khi đ i t ng đ c h y.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 61 Ví d 3.13: Ch
ng trình sau s d ng m t l p Time v i các đ i t
ng const và các hàm thành viên const. 2: #include 3: class Time 4: { 5: public:
6: Time(int = 0, int = 0, int = 0); //Constructor mặc định 7: //Các hàm set
8: void SetTime(int, int, int); //Thiết l p thời gian
9: void SetHour(int); //Thiết l p Hour
10: void SetMinute(int); //Thiết l p Minute
11: void SetSecond(int); //Thiết l p Second 12: //Các hàm get
13: int GetHour() const; //Trả v Hour
14: int GetMinute() const; //Trả v Minute
15: int GetSecond() const; //Trả v Second 16: //Các hàm in
17: void PrintMilitary() const; //In t.gian theo dạng giờ quân đội
18: void PrintStandard() const; //In thời gian theo dạng giờ chuẩn 19: private: 20: int Hour; //0 - 23 21: int Minute; //0 - 59 22: int Second; //0 – 59 23: }; 24:
25: //Constructor khởi động dữ liệu private
26: //Các giá trị mặc định là 0
27: Time::Time(int hr, int min, int sec) 28: { 29: SetTime(hr, min, sec); 30: } 31:
32: //Thiết l p các giá trị của Hour, Minute, và Second
33: void Time::SetTime(int h, int m, int s) 34: {
35: Hour = (h >= 0 && h < 24) ? h : 0;
36: Minute = (m >= 0 && m < 60) ? m : 0;
37: Second = (s >= 0 && s < 60) ? s : 0; 38: } 39:
40: //Thiết l p giá trị của Hour 41: void Time::SetHour(int h) 42: {
43: Hour = (h >= 0 && h < 24) ? h : 0; 44: } 45:
46: //Thiết l p giá trị của Minute
47: void Time::SetMinute(int m) 48: {
49: Minute = (m >= 0 && m < 60) ? m : 0; 50: } 51:
52: //Thiết l p giá trị của Second
53: void Time::SetSecond(int s) 54: {
55: Second = (s >= 0 && s < 60) ? s : 0; 56: } 57:
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 62
58: //Lấy giá trị của Hour 59: int Time::GetHour() const 60: { 61: return Hour; 62: } 63:
64: //Lấy giá trị của Minute
65: int Time::GetMinute() const 66: { 67: return Minute; 68: } 69:
70: //Lấy giá trị của Second
71: int Time::GetSecond() const 72: { 73: return Second; 74: } 75:
76: //Hi n thị thời gian dạng giờ quân đội: HH:MM:SS
77: void Time::PrintMilitary() const 78: {
79: cout << (Hour < 10 ? "0" : "") << Hour << ":"
80: << (Minute < 10 ? "0" : "") << Minute << ":"
81: << (Second < 10 ? "0" : "") << Second; 82: } 83:
84: //Hi n thị thời gian dạng chuẩn: HH:MM:SS AM (hay PM)
85: void Time::PrintStandard() const 86: {
87: cout << ((Hour == 12) ? 12 : Hour % 12) << ":"
88: << (Minute < 10 ? "0" : "") << Minute << ":"
89: << (Second < 10 ? "0" : "") << Second
90: << (Hour < 12 ? " AM" : " PM"); 91: } 92: 93: int main() 94: {
95: const Time T(19, 33, 52); //Đối tượng hằng
96: T.SetHour(12); //ERROR: non-const member function
97: T.SetMinute(20); //ERROR: non-const member function
98: T.SetSecond(39); //ERROR: non-const member function 99: return 0; 100: } Ch
ng trình này khai báo m t đ i t
ng h ng c a l p Time và c g ng s a đ i đ i t ng v i các hàm
thành viên không h ng SetHour(), SetMinute() và SetSecond(). Các l i c nh báo đ c phát sinh b i trình
biên d ch (Borland C++) nh hình 3.13.
Hình 3.13: Các c nh báo c a ch ng trình ví d 3.13
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 63
L u ý: Hàm thành viên const có th đ
c đa nĕng hóa v i m t phiên b n non-const. Vi c lựa ch n hàm
thành viên đa nĕng hóa nào đ s d ng đ
c t o m t cách tự đ ng b i trình biên d ch dựa vào n i mà đ i t ng đ
c khai báo const hay không. M t đ i t ng const không th đ
c thay đ i b i phép gán vì th nó ph i đ c kh i đ ng. Khi m t
thành viên d li u c a m t l p đ
c khai báo const, m t b kh i t o thành viên (member initializer) ph i
đ c s d ng đ cung c p cho constructor v i giá tr ban đ u c a thành viên d li u đ i v i m t đ i t ng c a l p.
Ví d 3.14: C.trình sau s d ng m t b kh i t o thành viên đ kh i t o m t h ng c a ki u d li u có s n. 2: #include 3: class IncrementClass 4: { 5: public:
6: IncrementClass (int C = 0, int I = 1); 7: void AddIncrement() 8: { 9: Count += Increment; 10: } 11: void Print() const; 12: private: 13: int Count;
14: const int Increment; //Thành viên dữ liệu const 15: }; 16:
17: //Constructor của lớp IncrementClass
18: //Bộ khởi tạo với thành viên const
19: IncrementClass::IncrementClass (int C, int I) : Increment(I) 20: { 21: Count = C; 22: } 23: 24: //In dữ liệu
25: void IncrementClass::Print() const 26: {
27: cout << "Count = " << Count
28: # # << ", Increment = " << Increment << endl; 30: } 31: 32: int main() 33: {
34: IncrementClass Value(10, 5); 35:
36: cout << "Before incrementing: "; 37: Value.Print();
38: for (int J = 1; J <= 3; J++) 40: { 41: Value.AddIncrement();
42: cout << "After increment " << J << ": "; 43: Value.Print(); 44: } 45: return 0; 46: } Ch
ng trình này s d ng cú pháp b kh i t o thành viên đ kh i t o thành viên d li u const
Increment c a l p IncrementClass dòng 19.
Chúng ta ch y ví d 3.14, k t qu hình 3.14
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 64
Hình 3.14: K t qu c a ví d 3.14
Ký hi u : Increment(I) ( dòng 19 c a ví d 3.14) sinh ra Increment đ
c kh i đ ng v i giá tr là I. N u
nhi u b kh i t o thành viên đ
c c n, đ n gi n bao g m chúng trong danh sách phân cách d u ph y sau d u
hai ch m. T t c các thành viên d li u có th đ
c kh i t o s d ng cú pháp b kh i t o thành viên.
N u trong ví d 3.14 chúng ta c g ng kh i t o Increment v i m t l nh gán h n là v i m t b kh i t o thành viên nh sau:
IncrementClass::IncrementClass (int C, int I) { Count = C; Increment = I; }
Khi đó trình biên d ch (Borland C++) s có thông báo l i nh sau:
Hình 3.15: Thông báo l i khi c g ng kh i t o m t thành viên d li u const b ng phép gán
XIV. L P NH LÀ CÁC THÀNH VIÊN C A CÁC L P KHÁC M t l p có th có các đ i t
ng c a các l p khác nh các thành viên. Khi m t đ i t ng đi vào ph m vi, constructor c a nó đ
c g i m t cách tự đ ng, vì th chúng ta c n mô t các tham s đ c truy n nh th
nào t i các constructor c a đ i t ng thành viên. Các đ i t ng thành viên đ
c xây dựng theo th tự mà trong đó chúng đ
c khai báo (không theo th tự mà chúng đ
c li t kê trong danh sách b kh i t o thành viên c a constructor) và tr c các đ i t
ng c a l p ch a đựng chúng đ c xây dựng. Ví d 3.15: Ch
ng trình sau minh h a các đ i t
ng nh các thành viên c a các đ i t ng khác. 1: #include 2: #include 3: 4: class Date 5: { 6: public:
7: Date(int = 1, int = 1, int = 1900); //Constructor mặc định
8: void Print() const; //In ngày theo dạng Month/Day/Year 9: private: 10: int Month; //1-12 11: int Day; //1-31
12: int Year; //Năm bất kỳ
13://Hàm tiện ích đ ki m tra Day tương thích đối với Month và Year 14: int CheckDay(int); 15: }; 16: 17: class Employee 18: {
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 65 19: public:
20: Employee(char *, char *, int, int, int, int, int, int); 21: void Print() const; 22: private: 23: char LastName[25]; 24: char FirstName[25]; 25: Date BirthDate; 26: Date HireDate; 27: }; 28:
29: //Constructor: xác nh n giá trị tương thích của Month
30: //Gọi hàm CheckDay() đ xác nh n giá trị tương thích của Day
31: Date::Date(int Mn, int Dy, int Yr) 32: {
33: if (Mn > 0 && Mn <= 12) 34: Month = Mn; 35: else 36: { 37: Month = 1;
38: cout << "Month " << Mn << " invalid. Set to Month 1." 39: << endl; 40: } 41: Year = Yr; 42: Day = CheckDay(Dy);
43: cout << "Date object constructor for date "; 44: Print(); 45: cout << endl; 46: } 47:
48: //Hàm xác nh n giá trị Day tương thích đưa vào Month và Year
49: int Date::CheckDay(int TestDay) 50: {
51: static int DaysPerMonth[13] = {0, 31, 28, 31, 30, 31,
52: 9; 9; 9; 9; 9; 9; # # # # 30, 31, 31, 30,31, 30, 31}; 53:
54: if (TestDay > 0 && TestDay <= DaysPerMonth[Month]) 55: return TestDay;
56: if (Month == 2 && TestDay == 29 &&
57: ; ; (Year % 400 == 0 || (Year % 4 == 0 && Year % 100 != 0))) 58: return TestDay;
59: cout << "Day " << TestDay << "invalid. Set to Day 1." << endl; 60: return 1; 61: } 62:
63: //In đối tượng Date dạng Month/Day/Year 64: void Date::Print() const 65: {
66: cout << Month << '/' << Day << '/' << Year; 67: } 68:
69: Employee::Employee(char *FName, char *LName,
70: int BMonth, int BDay, int BYear,
71: int HMonth, int HDay, int HYear)
72: :BirthDate(BMonth, BDay, BYear), HireDate(HMonth, HDay, HYear) 73: {
74://Sao chép FName vào FirstName và phải chắc chắn rằng nó phù hợp
75: int Length = strlen(FName); 76:
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 66
77: Length = Length < 25 ? Length : 24;
78: strncpy(FirstName, FName, Length); 79: FirstName[Length] = '\0';
80: //Sao chép LName vào LastName và phải chắc chắn rằng nó phù hợp 81: Length = strlen(LName);
82: Length = Length < 25 ? Length : 24;
83: strncpy(LastName, LName, 24); 84: LastName[Length] = '\0';
85: cout << "Employee object constructor: "
86: << FirstName << ' ' << LastName << endl; 87: } 88:
89: void Employee::Print() const 90: {
91: cout << LastName << ", " << FirstName << endl << "Hired: "; 92: HireDate.Print();
93: cout << " Birthday: "; 94: BirthDate.Print(); 95: cout << endl; 96: } 97: 98: int main() 99: {
100: Employee E("Bob", "Jones", 7, 24, 49, 3, 12, 88); 101: 102 cout << endl; 103: E.Print();
104: cout << endl << "Test Date constructor with invalid values:" 105: << endl;
106: Date D(14, 35, 94); //Các giá trị Date không hợp lệ 107: return 0; 108: } Ch
ng trình g m l p Employee ch a các thành viên d li u private LastName, FirstName, BirthDate
HireDate. Các thành viên BirthDateHireDate là các đ i t
ng c a l p Date mà ch a các thành viên
d li u private Month, Day Year. Ch ng trình kh i t o m t đ i t
ng Employee, và các kh i t o và các
hi n th các thành viên d li u c a nó. Chú ý v cú pháp c a ph n đ u trong đ nh nghƿa constructor c a l p Employee:
Employee::Employee(char *FName, char *LName, int BMonth, int BDay, int BYear,
int HMonth, int HDay, int HYear)
:BirthDate(BMonth, BDay, BYear), HireDate(HMonth, HDay, HYear)
Constructor l y tám tham s (FName, LName, BMonth, BDay, BYear, HMonth, HDay, và HYear). D u
hai ch m trong ph n đ u phân tách các b kh i t o t danh sách các tham s . Các b kh i t o đ nh rõ các
tham s truy n chon constructor c a các đ i t
ng thành viên. Vì th BMonth, BDay BYear đ c truy n cho constructor c a đ i t
ng BirthDate, và HMonth, HDay, và HYear đ
c truy n cho constructor c a đ i t
ng HireDate. Nhi u b kh i t o đ c phân tách b i d u ph y.
Chúng ta ch y ví d 3.15, k t qu hình 3.16
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 67
Hình 3.16: K t qu c a ví d 3.15 M t đ i t ng thành viên không c n đ
c kh i t o thông qua m t b kh i t o thành viên. N u m t b
kh i t o thành viên không đ
c cung c p, constructor m c đ nh c a đ i t ng thành viên s đ c g i m t
cách tự đ ng. Các giá tr n u có thi t l p b i constructor m c đ nh thì có th đ c ghi đè b i các hàm set.
XV. CÁC HÀM VÀ CÁC L P friend
M t hàm friend c a m t l p đ
c đ nh nghƿa bên ngoài ph m vi c a l p đó, lúc này có quy n truy c p
đ n các thành viên private ho c protected c a m t l p. M t hàm hay toàn b l p có th đ c khai báo là
m t friend c a l p khác.
Đ khai báo m t hàm là m t friend c a m t l p, đ ng tr c prototype c a hàm trong đ nh nghƿa l p v i
t khóa friend. nh sau:
friend <function-declarator>;
Đ khai báo m t l p là friend c a l p khác nh sau:
friend <class-name>; Ví d 3.16: Ch
ng trình sau minh h a khai báo và s d ng hàm friend. 1: #include 2: 3: class Count 4: {
5: friend void SetX(Count &, int); //Khai báo friend 6: public: 7: Count()//Constructor 8: { 9: X = 0; 10: }
11: void Print() const //Xuất 12: {
13: cout << X << endl; 14: } 15: private: 16: int X; 17: }; 18:
19: //Có th thay đổi dữ liệu private của lớp Count vì
20: //SetX() khai báo là một hàm friend của lớp Count
21: void SetX(Count &C, int Val) 22: {
23: C.X = Val; //Hợp lệ: SetX() là một hàm friend của lớp Count 24: }
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 68 25: 26: int main() 27: { 28: Count Object; 29:
30: cout << "Object.X after instantiation: "; 31: Object.Print();
32: cout << "Object.X after call to SetX friend function: ";
33: SetX(Object, 8); //Thiết l p X với một friend 34: Object.Print(); 35: return 0; 36: }
Chúng ta ch y ví d 3.16, k t qu hình 3.17
Hình 3.17: K t qu c a ví d 3.16 Có th ch đ nh các hàm đ
c đa nĕng hóa là các friend c a l p. M i hàm đ c đa nĕng hóa ph i đ c khai báo t
ng minh trong đ nh nghƿa l p nh là m t friend c a l p. XVI. CON TR THIS
Khi m t hàm thành viên tham chi u thành viên khác c a l p cho đ i t ng c th c a l p đó, làm th nào C++ b o đ m r ng đ i t ng thích h p đ
c tham chi u? Câu tr l i là m i đ i t ng duy trì m t con
tr tr t i chính nó – g i là con tr this – Đó là m t tham s n trong t t c các tham chi u t i các thành viên bên trong đ i t
ng đó. Con tr this cũng có th đ c s d ng t ng minh. M i đ i t ng có th xác đ nh
đ a ch c a chính mình b ng cách s d ng t khóa this. Con tr this đ
c s d ng đ tham chi u c các thành viên d li u và hàm thành viên c a m t đ i t
ng. Ki u c a con tr this ph thu c vào ki u c a đ i t
ng và trong hàm thành viên con tr this đ c s
d ng là khai báo const. Ch ng h n, m t hàm thành viên không h ng c a l p Employee con tr this có ki u là:
Employee * const //Con tr h ng tr t i đ i t ng Employee
Đ i v i m t hàm thành viên h ng c a l p Employee con tr this có ki u là:
const Employee * const //Con tr h ng tr t i đ i t ng Employee mà là m t h ng Ví d 3.17: Ch
ng trình sau minh h a s d ng t
ng minh c a con tr this đ cho phép m t hàm thành
viên c a l p Test in d li u X c a m t đ i t ng Test. 1: #include 2: 3: class Test 4: { 5: public:
6: Test(int = 0); // Constructor mặc định 7: void Print() const; 8: private: 9: int X; 10: }; 11: 12: Test::Test(int A) 13: { 14: X = A; 15: } 16:
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 69 17: void Test::Print() const 18: {
19: cout << " X = " << X << endl
20: << " this->X = " << this->X << endl
21: << "(*this).X = " << (*this).X << endl; 22: } 23: 24: int main() 25: { 26: Test A(12); 27: 28: A.Print(); 29: return 0; 30: }
Chúng ta ch y ví d 3.17, k t qu hình 3.18
Hình 3.18: K t qu c a ví d 3.17
M t cách khác s d ng con tr this là cho phép móc vào nhau các l i g i hàm thành viên. Ví d 3.18: Ch
ng trình sau minh h a tr v m t tham chi u t i m t đ i t
ng Time đ cho phép các
l i g i hàm thành viên c a l p Time đ c móc n i vào nhau. 1: #include 2: 3: class Time 4: { 5: public:
6: Time(int = 0, int = 0, int = 0); // Constructor mặc định 7: // Các hàm set
8: Time &SetTime(int, int, int); // Thiết l p Hour, Minute va Second
9: Time &SetHour(int); // Thiết l p Hour
10: Time &SetMinute(int); // Thiết l p Minute
11: Time &SetSecond(int); // Thiết l p Second 12: // Các hàm get
13: int GetHour() const; // Trả v Hour
14: int GetMinute() const; // Trả v Minute
15: int GetSecond() const; // Trả v Second 16: // Các hàm in
17: void PrintMilitary() const; // In t.gian theo dạng giờ quân đội
18: void PrintStandard() const; // In thời gian theo dạng giờ chuẩn 19: private: 20: int Hour; // 0 - 23 21: int Minute; // 0 - 59 22: int Second; // 0 - 59 23: }; 24:
25: // Constructor khởi động dữ liệu private
26: // Gọi hàm thành viên SetTime() đ thiết l p các biến
27: // Các giá trị mặc định là 0
28: Time::Time(int Hr, int Min, int Sec) 29: { 30: SetTime(Hr, Min, Sec);
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 70 31: } 32:
33: // Thiết l p các giá trị của Hour, Minute, và Second
34: Time &Time::SetTime(int H, int M, int S) 35: {
36: Hour = (H >= 0 && H < 24) ? H : 0;
37: Minute = (M >= 0 && M < 60) ? M : 0;
38: Second = (S >= 0 && S < 60) ? S : 0;
39: return *this; // Cho phép móc nối 40: } 41:
42: // Thiết l p giá trị của Hour
43: Time &Time::SetHour(int H) 44: {
45: Hour = (H >= 0 && H < 24) ? H : 0;
46: return *this; // Cho phép móc nối 47: } 48:
49: // Thiết l p giá trị của Minute
50: Time &Time::SetMinute(int M) 51: {
52: Minute = (M >= 0 && M < 60) ? M : 0;
53: return *this; // Cho phép móc nối 54: } 55:
56: // Thiết l p giá trị của Second
57: Time &Time::SetSecond(int S) 58: {
59: Second = (S >= 0 && S < 60) ? S : 0;
60: return *this; // Cho phép móc nối 61: } 62:
63: // Lấy giá trị của Hour 64: int Time::GetHour() const 65: { 66: return Hour; 67: } 68:
69: // Lấy giá trị của Minute
70: int Time::GetMinute() const 71: { 72: return Minute; 73: } 74:
75: // Lấy giá trị của Second
76: int Time::GetSecond() const 77: { 78: return Second; 79: } 80:
81: // Hi n thị thời gian dạng giờ quân đội: HH:MM:SS
82: void Time::PrintMilitary() const 83: {
84: cout << (Hour < 10 ? "0" : "") << Hour << ":"
85: << (Minute < 10 ? "0" : "") << Minute << ":"
86: << (Second < 10 ? "0" : "") << Second; 87: } 88:
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 71
89: // Hi n thị thời gian dạng chuẩn: HH:MM:SS AM (hay PM)
90: void Time::PrintStandard() const 91: {
92: cout << ((Hour == 0 || Hour == 12) ? 12 : Hour % 12) << ":"
93: << (Minute < 10 ? "0" : "") << Minute << ":"
94: << (Second < 10 ? "0" : "") << Second
95: << (Hour < 12 ? " AM" : " PM"); 96: } 97: 100: int main() 101: { 102: Time T; 103:
104: // Các lời gọi móc nối vào nhau
105: T.SetHour(18).SetMinute(30).SetSecond(22);
106: cout << "Military time: "; 107: T.PrintMilitary();
108: cout << endl << "Standard time: "; 109: T.PrintStandard();
110: cout << endl << endl << "New standard time: ";
111: // Các lời gọi móc nối vào nhau
112: T.SetTime(20, 20, 20).PrintStandard(); 113: cout << endl; 114: return 0; 115: }
Các hàm thành viên SetTime(), SetHour(), SetMinute() và SetSecond() m i hàm đ u tr v *this v i ki u
tr v là Time &. Toán t ch m liên k t t trái sang ph i, vì v y bi u th c:
T.SetHour(18).SetMinute(30).SetSecond(22);
Đ u tiên g i T.SetHour(18) thì tr v m t tham chi u t i đ i t ng T là giá tr c a l i g i hàm này. Ph n còn l i c a bi u th c đ c hi u nh sau:
T.SetMinute(30).SetSecond(22);
T.SetMinute(30) g i thực hi n và tr v t ng đ
ng c a T. Ph n còn c a bi u th c là: T.SetSecond(22);
Chúng ta ch y ví d 3.18, k t qu hình 3.19
Hình 3.19: K t qu c a ví d 3.18 XVII. CÁC Đ I T NG Đ C C P PHÁT Đ NG Các đ i t ng có th đ
c c p phát đ ng gi ng nh các d li u khác b ng toán t new delete. Ch ng h n:
Time *TimePtr = new Time(1,20,26); …………….. delete TimePtr;
Toán t new tự đ ng g i hàm constructor ,và toán t delete tự đ ng g i destructor.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 72 XVIII.
CÁC THÀNH VIÊN TƾNH C A L P Bình th ng, m i đ i t
ng c a m t l p có b n sao chép c a chính nó c a t t c các thành viên d li u c a l p. Trong các tr
ng h p nh t đ nh ch có duy nh t m t b n chép thành viên d li u đ c bi t c n ph i
dùng chung b i t t c các đ i t
ng c a m t l p. M t thành viên d li u tƿnh đ c s d ng cho nh ng đi u
đó và các lý do khác. M t thành viên d li u tƿnh bi u di n thông tin toàn l p (class-wide). Khai báo m t
thành viên tƿnh b t đ u v i t khóa static.
M c dù các thành viên d li u tƿnh có th gi ng nh các bi n toàn c c, các thành viên d li u tƿnh có
ph m vi l p. Các thành viên tƿnh có th là public, private ho c protected. Các thành viên d li u tƿnh ph i
đ c kh i t o m t l n (và ch m t l n) t i ph m vi file. Các thành viên l p tƿnh public có th đ c truy c p thông qua b t kỳ đ i t
ng nào c a l p đó, ho c chúng có th đ
c truy c p thông qua tên l p s d ng toán
t đ nh ph m vi. Các thành viên l p tƿnh private protected ph i đ
c truy c p thông qua các hàm thành
viên public c a l p ho c thông qua các friend c a l p. Các thành viên l p tƿnh t n t i ngay c khi đ i t ng
c a l p đó không t n t i. Đ truy c p m t thành viên l p tƿnh public khi các đ i t ng c a l p không t n t i,
đ n gi n thêm vào đ u tên l p và toán t đ nh ph m vi cho thành viên d li u. Đ truy c p m t thành viên
l p tƿnh private ho c protected khi các đ i t
ng c a l p không t n t i, m t hàm thành viên public ph i
đ c cung c p và hàm ph i đ c g i b i thêm vào đ u tên c a nó v i tên l p và toán t đ nh ph m vi. Ví d 3.19: Ch
ng trình sau minh h a vi c s d ng thành viên d li u tƿnh private và m t hàm thành viên tƿnh public. 1: #include 2: #include 3: #include 4: 5: class Employee 6: { 7: public:
8: Employee(const char*, const char*); // Constructor 9: ~Employee(); // Destructor
10: char *GetFirstName() const; // Trả v first name
11: char *GetLastName() const; // Trả v last name
12: // Hàm thành viên tĩnh
13: static int GetCount(); // Trả v số đối tượng khởi tạo 14: private: 15: char *FirstName; 16: char *LastName; 17: // static data member
18: static int Count; // Số đối tượng khởi tạo 19: }; 20:
21: // Khởi tạo thành viên dữ liệu tĩnh 22: int Employee::Count = 0; 23:
24://Định nghĩa hàm thành viên tỉnh mà trả v số đối tượng khởi tạo 25: int Employee::GetCount() 26: { 27: return Count; 28: } 29:
30: // Constructor cấp phát động cho first name và last name
31: Employee::Employee(const char *First, const char *Last) 32: {
33: FirstName = new char[ strlen(First) + 1 ];
34: assert(FirstName != 0); // Bảo đảm vùng nhớ được cấp phát 35: strcpy(FirstName, First);
36: LastName = new char[ strlen(Last) + 1 ];
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 73
37: assert(LastName != 0); // Bảo đảm vùng nhớ được cấp phát 38: strcpy(LastName, Last);
39: ++Count; // Tăng số đối tượng lên 1
40: cout << "Employee constructor for " << FirstName
41: << ' ' << LastName << " called." << endl; 42: } 43:
44: // Destructor giải phóng vùng nhớ đã cấp phát 45: Employee::~Employee() 46: {
47: cout << "~Employee() called for " << FirstName
48: << ' ' << LastName << endl; 49: delete FirstName; 50: delete LastName;
51: --Count; // Giảm số đối tượng xuống 1 52: } 53: 54: // Trả v first name
55: char *Employee::GetFirstName() const 56: {
57: char *TempPtr = new char[strlen(FirstName) + 1];
58: assert(TempPtr != 0); // Bảo đảm vùng nhớ được cấp phát
59: strcpy(TempPtr, FirstName); 60: return TempPtr; 61: } 62: 63: // Trả v last name
64: char *Employee::GetLastName() const 65: {
66: char *TempPtr = new char[strlen(LastName) + 1];
67: assert(TempPtr != 0); // Bảo đảm vùng nhớ được cấp phát
68: strcpy(TempPtr, LastName); 69: return TempPtr; 70: } 71: 72: int main() 73: {
74: cout << "Number of employees before instantiation is "
75: << Employee::GetCount() << endl; // Sử dụng tên lớp
76: Employee *E1Ptr = new Employee("Susan", "Baker");
77: Employee *E2Ptr = new Employee("Robert", "Jones");
78: cout << "Number of employees after instantiation is "
79: << E1Ptr->GetCount() << endl;
80: cout << endl << "Employee 1: "
81: << E1Ptr->GetFirstName()
82: << " " << E1Ptr->GetLastName()
83: << endl << "Employee 2: "
84: << E2Ptr->GetFirstName()
85: << " " << E2Ptr->GetLastName() << endl << endl; 86: delete E1Ptr; 87: delete E2Ptr;
88: cout << "Number of employees after deletion is "
89: << Employee::GetCount() << endl; 90: return 0; 91: }
Thành viên d li u Count đ
c kh i t o là zero ph m vi file v i l nh: int Employee::Count = 0;
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 74
Thành viên d li u Count duy trì s các đ i t
ng c a l p Employee đã đ c kh i t o. Khi đ i t ng
c a l p Employee t n t i, thành viên Count có th đ
c tham chi u thông qua b t kỳ hàm thành viên nào c a m t đ i t
ng Employee – trong ví d này, Count đ
c tham chi u b i c constructor l n destructor. Khi các
đ i t ng c a l p Employee không t n t i, thành viên Count có th v n đ c tham chi u nh ng ch thông
qua m t l i g i hàm thành viên tƿnh public GetCount() nh sau: Employee::GetCount() Hàm GetCount() đ
c s d ng đ xác đ nh s các đ i t
ng c a Employee kh i t o hi n hành. Chú ý
r ng khi không có các đ i t ng trong ch
ng trình, l i g i hàm Employee::GetCount() đ c đ a ra. Tuy nhiên khi có các đ i t
ng kh i đ ng hàm GetCount() có th đ
c g i thông qua m t trong các đ i t ng nh sau: E1Ptr->GetCount() Trong ch
ng trình các dòng 34, 37, 58 và 67 s d ng hàm assert() (đ nh nghƿa trong assert.h). Hàm
này ki m tra giá tr c a bi u th c. N u giá tr c a bi u th c là 0 (false), hàm assert() in m t thông báo l i và
g i hàm abort() (đ nh nghƿa trong stdlib.h) đ k t thúc ch
ng trình thực thi. N u bi u th c có giá tr khác 0 (true) thì ch
ng trình ti p t c. Đi u này r t có ích cho công c debug đ i v i vi c ki m tra n u m t bi n có
giá tr đúng. Ch ng h n hàm dòng 34 hàm assert() ki m tra con tr FirstName đ xác đ nh n u nó không
b ng 0 (null). N u đi u ki n trong kh ng đ nh (assertion) cho tr c là đúng, ch ng trình ti p t c mà không
ng t. N u đi u ki n trong kh ng đ nh cho tr
c là sai, m t thông báo l i ch a s dòng, đi u ki n đ c ki m
tra, và tên file trong đó sự kh ng đ nh xu t hi n đ c in, và ch
ng trình k t thúc. Khi đó l p trình viên có
th t p trung vào vùng này c a đo n mã đ tìm l i.
Các kh ng đ nh không ph i xóa t ch
ng trình khi debug xong. Khi các kh ng đ nh không còn c n
thi t cho m c đích debug trong m t ch ng trình, dòng sau: #define NDEBUG
đ c thêm vào đ u file ch ng trình. Đi u này phát sinh ti n x lý b qua t t c các kh ng đ nh thay
th cho l p trình viên xóa m i kh ng đ nh b ng tay.
Chúng ta ch y ví d 3.19, k t qu hình 3.20
Hình 3.20: K t qu c a ví d 3.19
M t hàm thành viên có th đ
c khai báo là static n u nó không truy c p đ n các thành viên không tƿnh.
Không gi ng nh các thành viên không tƿnh, m t hàm thành viên tƿnh không có con tr this b i vì các thành
viên d li u tƿnh và các hàm thành viên tƿnh t n t i đ c l p v i b t kỳ đ i t ng nào c a l p.
Chú ý: Hàm thành viên d li u tƿnh không đ c là const.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 75 BÀI T P
Bài 1: Xây dựng l p Stack, d li u bao g m đ nh stack và vùng nh c a stack. Các thao tác g m: Kh i đ ng stack.
Ki m tra stack có r ng không?
Ki m tra stack có đ y không? Push và pop.
Bài 2: Xây dựng l p hình tr Cylinder, d li u bao g m bán kính và chi u cao c a hình tr . Các thao
tác g m hàm tính di n tích toàn ph n và th tích c a hình tr đó.
Bài 3: Hãy xây dựng m t l p Point cho các đi m trong không gian ba chi u (x,y,z). L p ch a m t
constructor m c đ nh, m t hàm Negate() đ bi n đ i đi m thành đ i l
ng có d u âm, m t hàm Norm() tr
v kho ng cách t g c và m t hàm Print().
Bài 4: Xây dựng m t l p Matrix cho các ma tr n bao g m m t constructor m c đ nh, hàm xu t ma
tr n, nh p ma tr n t bàn phím, c ng hai ma tr n, tr hai ma tr n và nhân hai ma tr n.
Bài 5: Xây dựng m t l p Matrix cho các ma tr n vuông bao g m m t constructor m c đ nh, hàm xu t
ma tr n, tính đ nh th c và tính ma tr n ngh ch đ o.
Bài 6: Xây dựng l p Person đ qu n lý h tên, nĕm sinh, đi m chín môn h c c a t t c các h c viên
c a l p h c. Cho bi t bao nhiêu h c viên trong l p đ
c phép làm lu n vĕn t t nghi p, bao nhiêu h c viên thi t t nghi p, bao nhiêu ng
i ph i thi l i và tên môn thi l i. Tiêu chu n đ xét:
Làm lu n vĕn ph i có đi m trung bình l n h n 7 trong đó không có môn nào d i 5.
Thi t t nghi p khi đi m trung bình không l n h n 7 và đi m các môn không d i 5. Thi l i có môn d i 5.
Bài 7: Xây dựng m t l p String. M i đ i t
ng c a l p String s đ i di n m t chu i ký tự. Các thành
viên d li u là chi u dài chu i và chu i ký tự thực. Ngoài constructor và destructor còn có các ph ng th c
nh t o m t chu i v i chi u dài cho tr
c, t o m t chu i t m t chu i đã có.
Bài 8: Xây dựng m t l p Vector đ l u tr vector g m các s thực. Các thành viên d li u g m: Kích th c vector.
M t m ng đ ng ch a các thành ph n c a vector.
Ngoài constructor và destructor, còn có các ph ng th c tính tích vô h
ng c a hai vector, tính chu n
c a vector (theo chu n b t kỳ nào đó).
Bài 9: Xây dựng l p Employee g m h tên và ch ng minh nhân dân. Ngoài constructor còn có ph
ng th c nh p, xu t h tên và ch ng minh nhân dân ra màn hình.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 76 CHƯƠNG 4 ĐA NĔNG HÓA TOÁN T I. D N NH P Trong ch
ng 3, chúng ta đã tìm hi u các đi u c b n c a các l p C++ và khái ni m ki u d li u tr u t
ng (ADTs). Các thao tác trên các đ i t
ng c a l p (nghƿa là các thực th c a ADTs) đ c thực hi n b i g i các thông đi p (d
i d ng các l i g i hàm thành viên) t i các đ i t
ng. Ký pháp g i hàm này thì c ng
k nh cho các lo i l p nh t đ nh, đ c bi t là các l p toán h c. Đ i v i các lo i l p này s là đẹp đ s d ng
t p các toán t có s n phong phú c a C++ đ ch rõ các thao tác c a đ i t ng. Trong ch ng này tìm hi u
làm th nào cho phép các toán t c a C++ làm vi c v i các đ i t ng c a l p. X lý này đ c g i là đa nĕng
hóa toán t (operator overloading). Toán t << đ
c s d ng nhi u m c đích trong C++ đó là toán t chèn dòng (stream-insertion) và toán
t d ch chuy n trái. Đây là m t ví d c a đa nĕng hóa toán t . T ng tự >> cũng đ c đa nĕng hóa. Nó đ c
s d ng v a toán t trích dòng (stream-extraction) và toán t d ch chuy n ph i.
C++ cho phép các l p trình viên đa nĕng hóa h u h t các toán t đ bi u th ng c nh mà trong đó chúng
đ c s d ng. Trình biên d ch phát sinh đo n mã thích h p dựa trên ki u mà trong đó toán t đ c s d ng. M t vài toán t đ c đa nĕng hóa th
ng xuyên, đ c bi t là toán t gán và các toán t s h c nh + và -.
Công vi c thực hi n b i đa nĕng hóa các toán t cũng có th đ
c thực hi n b i các l i g i hàm t ng minh, nh ng ký pháp th ng s d ng d dàng đ đ c. II.
CÁC NGUYÊN T C C B N C A ĐA NĔNG HÓA TOÁN T
L p trình viên có th s d ng các ki u có s n và có th đ nh nghƿa các ki u m i. Các ki u có th đ c s
d ng v i t p các toán t phong phú. Các toán t cung c p cho các l p trình viên v i ký pháp ng n ng n cho
vi c bi u th các thao tác c a đ i t ng c a các ki u có s n.
Các l p trình viên có th s d ng các toán t v i các ki u do ng
i dùng đ nh nghƿa. M c dù C++ không cho phép các toán t m i đ
c t o, nó cho phép các toán t đã t n t i đ
c đa nĕng hóa sao cho khi các toán t này đ c s d ng v i các đ i t
ng c a l p, các toán t có ý nghƿa thích h p các ki u m i. Đây chính là m t đ c đi m m nh c a C++. Các toán t đ
c đa nĕng hóa b ng cách vi t m t đ nh nghƿa hàm (bao g m ph n đ u và thân) nh khi
chúng ta vi t m t hàm bình th
ng, ngo i tr tên hàm bây gi tr thành t khóa operator theo sau b i ký hi u c a toán t đ
c đa nĕng hóa. Prototype c a nó có d ng nh sau:
type operator operator_symbol ( parameter_list );
Đ s d ng m t toán t m t các đ i t ng c a l p, toán t ph i đ c đa nĕng hóa ngo i tr hai đi u.
Đi u th nh t toán t gán có th s d ng v i m i l p mà không c n đa nĕng hóa. Cách c x m c đ nh c a
toán t gán là m t phép gán thành viên c a các thành viên d li u c a l p. Chúng ta nh n th y r ng sao chép
thành viên m c đ nh thì nguy hi m đ i v i các l p v i các thành viên mà đ
c c p phát đ ng. Chúng ta s đa nĕng hóa m t cách t
ng minh toán t gán đ i v i các l p nh th . Đi u th hai toán t đ a ch (&) cũng có th đ c s d ng v i các đ i t
ng c a b t kỳ l p nào mà không c n đa nĕng hóa; Nó tr v đ a ch c a đ i t
ng trong b nh . Toán t đ a ch cũng có th đ c đa nĕng hóa. III. CÁC
GI I H N C A ĐA NĔNG HÓA TOÁN T
Ph n l n các toán t c a C++ có th đ
c đa nĕng hóa. Hình 4.1 cho th y các toán t có th đ c đa
nĕng hóa và hình 4.1 là các toán t không th đa nĕng hóa. + - * / % ^ & | ~ ! = < > += -= *= Hình 4.1: /= %= ^= &= |= << >> >>= Các toán t có th đ c đa nĕng hóa <<= == != <= >= && || ++ -- ->* , -> [] () new delete
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 77 . .* :: ?: sizeof
Hình 4.2: Các toán t không th đa nĕng hóa
Chú ý r ng toán t ngo c tròn () trong b ng 4.1 là toán t g i hàm. Vì toán t này đ ng sau tên hàm có
th ch a trong nó nhi u tham s do đó toán t ngo c tròn là m t toán t nhi u ngôi.
Th tự u tiên c a m t toán t không th đ
c thay đ i b i đa nĕng hóa. Đi u này có th d n t i các
tình tr ng b t ti n trong đó m t toán t đ
c đa nĕng hóa theo m t cách đ i v i m c đ u tiên c đ nh c a
nó thì không thích h p. Tuy nhiên, các d u ngo c đ n có th đ c s d ng đ đ t th tự c l ng c a các
toán t đã đa nĕng hóa trong m t bi u th c.
Tính k t h p c a m t toán t không th đ
c thay đ i b i đa nĕng hóa. Các tham s m c đ nh không th
s d ng v i m t toán t đa nĕng hóa.
Không th thay đ i s các toán h ng mà m t toán t yêu c u: Đa nĕng hóa các toán t m t ngôi v n là
các toán t m t ngôi; đa nĕng hóa các toán t hai ngôi v n là các toán t hai ngôi. Toán t ba ngôi duy nh t
(?:) c a C++ không th đa nĕng hóa. Các toán t &, *, + m i toán t có các phiên b n m t và hai ngôi.;
Các phiên b n m t và hai ngôi này có th đ c đa nĕng hóa riêng bi t.
Ý nghƿa c a làm sao m t toán t làm vi c trên các đ i t
ng c a các ki u có s n không th thay đ i b i
vi c đa nĕng hóa toán t . Ch ng h n, l p trình viên không th thay đ i ý nghƿa c a làm sao toán t (+) c ng
hai s nguyên. Vi c đa nĕng hóa toán t ch làm vi c v i các đ i t ng c a các ki u do ng i dùng đ nh
nghƿa ho c v i m t sự pha tr n c a m t đ i t ng c a ki u do ng
i dùng đ nh nghƿa và m t đ i t ng c a m t ki u có s n.
Đa nĕng hóa m t toán t gán và m t toán t c ng đ cho phép các l nh nh là: object2 = object2 + object1
không bao hàm toán t += cũng đ
c đa nĕng hóa đ phép các l nh nh là: object2 += object1 Hành vi nh th có th đ
c thực hi n b i vi c đa nĕng hóa rõ ràng toán t += cho l p đó.
IV. CÁC HÀM TOÁN T CÓ TH LÀ CÁC THÀNH VIÊN C A L P HO C
KHÔNG LÀ CÁC THÀNH VIÊN

Các hàm toán t có th là các hàm thành viên ho c hàm không thành viên; hàm không thành viên th
ng là các hàm friend. Các hàm thành viên s d ng ng m con tr this đ ch a m t trong các tham s đ i t
ng l p c a chúng. Tham s l p đó ph i đ c li t kê m t cách t
ng minh trong l i g i hàm không thành viên.
Khi đa nĕng hóa (), [], -> ho c =, hàm đa nĕng hóa toán t ph i đ
c khai báo nh m t thành viên l p.
Đ i v i các toán t khác, các hàm đa nĕng hóa toán t có th là các hàm không thành viên (th ng là các hàm friend).
Li u có ph i m t hàm toán t đ
c cài đ t nh m t hàm thành viên ho c nh hàm không thành viên, toán t v n còn đ
c s d ng cùng cách trong bi u th c. Nh v y cách là cách cài đ t nào t t nh t? Khi m t hàm toán t đ
c cài đ t nh m t hàm thành viên, toán h ng cực trái ph i là m t đ i t ng l p
c a toán t . N u toán h ng bên trái ph i là m t đ i t
ng c a l p khác ho c m t ki u có s n thì hàm toán t này ph i đ
c cài đ t nh hàm không thành viên. M t hàm toán t cài đ t nh hàm không thành viêân c n là
m t friend n u hàm ph i truy c p đ n các thành viên private ho c protected. Các hàm thành viên ch đ
c g i khi toán h ng trái c a m t toán t hai ngôi là m t đ i t ng c th c a
l p đó, ho c khi toán h ng đ n c a m t toán t m t ngôi là m t đ i t ng c a l p đó.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 78
Ví d 4.1: Chúng ta xây dựng l p s ph c v i tên l p là Complex và đa nĕng hóa toán t + trên l p này. 1: #include 2: 3: class Complex 4: { 5: private: 6: double Real, Imaginary; 7: public:
8: Complex(double R=0.0,double I=0.0);// Constructor mặc định
9: void Print(); // Hi n thị số phức
10: Complex operator+(Complex Z); // Phép cộng giữa hai số phức
11: Complex operator+(double R); //cộng một số phức với một số thực 12: }; 13:
14: Complex::Complex(double R,double I) 15: { 16: Real = R; 17: Imaginary = I; 18: } 19: 20: void Complex::Print() 21: { 22: cout<<'('<23: } 24:
25: Complex Complex::operator + (Complex Z) 26: { 27: Complex Tmp; 28: Tmp.Real = Real + Z.Real;
29: Tmp.Imaginary = Imaginary + Z.Imaginary; 30: return Tmp; 31: } 32:
33: Complex Complex::operator + (double R) 34: { 35: Complex Tmp; 36: Tmp.Real = Real + R;
37: Tmp.Imaginary = Imaginary; 38: return Tmp; 39: } 40: 41: int main() 42: {
43: Complex X,Y(4.3,8.2),Z(3.3,1.1); 44: cout<<"X: "; 45: X.Print(); 46: cout<47: Y.Print(); 48: cout<49: Z.Print(); 50: X = Y + Z; 51: cout<52: X.Print(); 53: cout<<" = "; 54: Y.Print(); 55: cout<<" + "; 56: Z.Print();
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 79 57: X = Y + 3.5; 58: cout<59: X.Print(); 60: cout<<" = "; 61: Y.Print(); 62: cout<<" + 3.5"; 63: return 0; 64: }
Hàm thành viên toán t operator + () (t dòng 25 đ n 31 và t dòng 33 đ n 39) tr v m t đ i t ng có
ki u Complex là t ng c a hai s ph c ho c t ng c a m t s ph c v i m t s thực. Chú ý r ng đ i t ng tam th i Tmp đ
c dùng bên trong hàm operator + () đ gi k t qu , và đó là đ i t ng đ c tr v .
Chúng ta ch y ví d 4.1, k t qu hình 4.3
Hình 4.3: K t qu c a ví d 4.1
Do đa nĕng hóa toán t + trên l p Complex ví d 4.1, chúng ta có th vi t: X = Y + Z; Câu l nh này đ c trình biên d ch hi u: X = Y.operator + (Z);
Nh v y, trong bi u th c Y + Z đ i t
ng bên trái toán t + (là đ i t ng Y) là đ i t ng mà qua đó,
hàm thành viên toán t operator + () đ
c g i. Do đó hàm thành viên toán t + ch nh n m t tham s là đ i t
ng bên ph i toán t và đ i t
ng bên trái toán t là đ i t
ng t o l i g i cho hàm toán t và đ c truy n b i con tr this.
Hàm operator + () tr v m t đ i t
ng Complex. Do v y chúng ta có th vi t: (Y + Z).Print();
đ in trên màn hình s ph c c a đ i t ng đ c tr v . Đ i t ng do Y + Z sinh ra nh v y là m t đ i t
ng t m th i. Nó s không t n t i khi hàm thành Print() k t thúc. H n n a khi tr v m t đ i t
ng, toán t + cho phép m t chu i phép c ng. Nên chúng ta cũng có th vi t: X = X + Y + Z;
Tuy nhiên chúng ta không th nào vi t đ c câu l nh sau: X = 3.5 + Y; // L i !!!
Chính vì lý do này chúng ta ch n m t hàm không thành viên đ đa nĕng hóa m t toán t đ cho phép toán t đ
c giao hoán. Chú ý r ng hàm không thành viên không c n thi t ph i là hàm friend n u các hàm
set và get thích h p t n t i trong ph n giao di n public, và đ t bi t nh t n u các hàm set và get là các hàm inline.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 80
Đ đa nĕng hóa toán t << ph i có m t toán h ng trái c a ki u ostream & (nh là cout trong bi u th c
cout<ng tự, đa nĕng hóa toán t >> ph i có m t toán h ng
trái c a ki u istream & (nh là cin trong bi u th c cin>>X), vì th vì th nó cũng ph i là hàm không thành viên.
Ngo i tr đa nĕng hóa toán t >> << liên quan đ n dòng nh p/xu t d li u chúng ta có hình 4.4 v
cách đa nĕng hóa toán t nh sau: Bi u th c Hàm thành viên Hàm không thành viên
a#b a.operator#(b) operator#(a,b) #a a.operator() operator#(a) a=b a.operator=(b) a[b] a.operator[](b) a(b) a.operator()(b) a-> a.operator->()
a++ a.operator++(0) operator++(a,0)
a-- a.operator--(0) operator--(a,0)
Hình 4.4: Vi c cài đ t các hàm toán t V.
ĐA NĔNG HOÁ CÁC TOÁN T HAI NGÔI Các toán t hai ngôi đ
c đa nĕng hóa trong hình 4.5 sau: Toán t Ví d Toán t Ví d Toán t Ví d + a+b += a+=b <<= a<<=b - a-b -= a-=b == a==b * a*b *= a*=b != a!=b / a/b /= a/=b <= a<=b % a%b %= a%=b >= a>=b ^ a^b ^= a^=b && a&&b & a&b &= a&=b || a||b | a|b |= a|=b , a,b = a=b << a<[] a[b] < a>> a>>b ->* a->*b > a>b >>= a>>=b
Hình 4.5: Các toán t hai ngôi đ c đa nĕng hóa
M t toán t hai ngôi có th đ
c đa nĕng hóa nh là hàm thành viên không tƿnh v i m t tham s ho c
nh m t hàm không thành viên v i hai tham s (m t trong các tham s này ph i là ho c là m t đ i t ng l p
ho c là m t tham chi u đ n đ i t ng l p).
Ví d 4.2: Chúng ta xây dựng l p s ph c v i tên l p là Complex và đa nĕng hóa các toán t tính toán +
- += -= và các toán t so sánh == != > >= < <= v i các hàm toán t là các hàm thành viên. 1: #include 2: #include 3: 4: class Complex 5: { 6: private: 7: double Real, Imaginary; 8: public:
9: Complex(); // Constructor mặc định
10: Complex(double R,double I);
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 81
11: Complex (const Complex & Z); // Constructor sao chép
12: Complex (double R); // Constructor chuy n đổi
13: void Print(); // Hi n thị số phức
14: // Các toán tử tính toán
15: Complex operator + (Complex Z);
16: Complex operator - (Complex Z);
17: Complex operator += (Complex Z);
18: Complex operator -= (Complex Z);
19: // Các toán tử so sánh
20: int operator == (Complex Z);
21: int operator != (Complex Z);
22: int operator > (Complex Z);
23: int operator >= (Complex Z);
24: int operator < (Complex Z);
25: int operator <= (Complex Z); 26: private:
27: double Abs(); // Giá trị tuyệt đối của số phức 28: }; 29: 30: Complex::Complex() 31: { 32: Real = 0.0; 33: Imaginary = 0.0; 34: } 35:
36: Complex::Complex(double R,double I) 37: { 38: Real = R; 39: Imaginary = I; 40: } 41:
42: Complex::Complex(const Complex & Z) 43: { 44: Real = Z.Real; 45: Imaginary = Z.Imaginary; 46: } 47:
48: Complex::Complex(double R) 49: { 50: Real = R; 51: Imaginary = 0.0; 52: } 53: 54: void Complex::Print() 55: { 56: cout<<'('<57: } 58:
59: Complex Complex::operator + (Complex Z) 60: { 61: Complex Tmp; 62 63: Tmp.Real = Real + Z.Real;
64: Tmp.Imaginary = Imaginary + Z.Imaginary; 65: return Tmp; 66: } 67:
68: Complex Complex::operator - (Complex Z)
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 82 69: { 70: Complex Tmp; 71: 72: Tmp.Real = Real - Z.Real;
73: Tmp.Imaginary = Imaginary - Z.Imaginary; 74: return Tmp; 75: } 76:
77: Complex Complex::operator += (Complex Z) 78: { 79: Real += Z.Real; 80: Imaginary += Z.Imaginary; 81: return *this; 82: } 83:
84: Complex Complex::operator -= (Complex Z) 85: { 86: Real -= Z.Real; 87: Imaginary -= Z.Imaginary; 88: return *this; 89: } 90:
91: int Complex::operator == (Complex Z) 92: {
93: return (Real == Z.Real) && (Imaginary == Z.Imaginary); 94: } 95:
96: int Complex::operator != (Complex Z) 97: {
98: return (Real != Z.Real) || (Imaginary != Z.Imaginary); 99: } 100:
101: int Complex::operator > (Complex Z) 102: {
103: return Abs() > Z.Abs(); 104: } 105:
106: int Complex::operator >= (Complex Z) 107: {
108: return Abs() >= Z.Abs(); 109: } 110:
111: int Complex::operator < (Complex Z) 112: {
113: return Abs() < Z.Abs(); 114: } 115:
116: int Complex::operator <= (Complex Z) 117: {
118: return Abs() <= Z.Abs(); 119: } 120: 121: double Complex::Abs() 122: {
123: return sqrt(Real*Real+Imaginary*Imaginary); 124: } 125: 126: int main()
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 83 127: {
128: Complex X, Y(4.3,8.2), Z(3.3,1.1), T; 129 130: cout<<"X: "; 131: X.Print(); 132: cout<133: Y.Print(); 134: cout<135: Z.Print(); 136: cout<137: T.Print();
138: T=5.3;// Gọi constructor chuy n ki u
139: cout<140: cout<<"T: "; 141: T.Print(); 142: X = Y + Z; 143: cout<144: X.Print(); 145: cout<<" = "; 146: Y.Print(); 147: cout<<" + "; 148: Z.Print(); 149: X = Y - Z; 150: cout<151: X.Print(); 152: cout<<" = "; 153: Y.Print(); 154: cout<<" - "; 155: Z.Print(); 156: cout<157: Y.Print(); 158: cout<<" += "; 159: T.Print(); 160: Y += T; 161: cout<162: Y.Print(); 163: cout<164: Z.Print(); 165: cout<<" -= "; 166: T.Print(); 167: Z -= T; 168: cout<169: Z.Print();
170: Complex U(X);// Gọi constructor sao chép 171: cout<172: U.Print(); 173: cout<174: if (X==U)
175: cout<<"They are equal"<176: cout<<"Evaluating: Y!=Z"<177: if (Y!=Z)
178: cout<<"They are not equal => "; 179: if (Y>Z) 180: cout<<"Y>Z"; 181: else
182: cout<<"Y183: return 0; 184: }
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 84
Chúng ta ch y ví d 4.2, k t qu hình 4.6. Dòng th 10 c a ch
ng trình ví d 4.2: Complex(const Complex &Z);
là m t constructor sao chép (copy constructor). Nó kh i đ ng m t đ i t ng l p b ng cách t o m t sao chép c a m t đ i t
ng l p đó. Constructor sao chép thực hi n công vi c gi ng nh toán t sao chép nh ng
nó có m t vai trò đ c bi t. Constructor sao chép ch nh n tham s là m t tham chi u ch đ n đ i t ng thu c chính l p mà nó đ
c đ nh nghƿa. Các constructor sao chép đ
c dùng m i khi m t sự sao chép c a m t đ i t
ng c n thi t nh khi có sự truy n tham s b ng tr , khi tr v m t đ i t
ng t hàm, ho c khi kh i đ ng m t đ i t ng mà đ c sao chép t đ i t
ng khác c a cùng l p. Ch ng h n: Complex A(3.5, 4.5);
Complex B(A); // G i constructor sao chép
Complex C = B; // G i constructor sao chép …………………
Complex MyFunc(Complex Z) // G i constructor sao chép
{ rZ; // G i constructor sao chép }
Hình 4.6: K t qu c a ví d 4.2
Chúng ta chú ý r ng, d u = trong câu l nh trên ng v i constructor sao chép ch không ph i là toán t
gán . N u chúng ta không đ nh nghƿa constructor sao chép, trình biên d ch t o ra m t constructor sao chép
m c đ nh s sao chép t ng thành viên m t. dòng 12 c a ch ng trình ví d 4.2: Complex(double R);
là m t constructor chuy n đ i (conversion constructor). Constructor này l y m t tham s double và kh i t o đ i t
ng Complex mà ph n thực b ng giá tr tham s truy n vào và ph n o b ng 0.0 (t dòng 48 đ n
52). B t kỳ m t constructor nào có tham s đ n có th đ
c nghƿ nh m t constructor chuy n đ i.
Constructor chuy n đ i s đ i m t s thực thành m t đ i t
ng Complex r i gán cho đ i t ng đích Complex. Ch ng h n:
T = 3.5; // Ng m đ nh: T = Complex(3.5)
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 85
Trình biên d ch tự đ ng dùng constructor chuy n đ i đ t o m t đ i t
ng t m th i Complex, r i dùng toán t gán đ gán đ i t ng t m th i này cho đ i t
ng khác c a Complex. Ch ng h n câu l nh sau v n đúng:
X = Y + 3.5; // Ng m đ nh: X = Y + Complex(3.5);
Nh v y m t constructor chuy n đ i đ
c s d ng đ thực hi n m t sự chuy n đ i ng m đ nh.
Ví d 4.3: L y l i ví d 4.2 nh ng các hàm toán t +, - và các hàm toán t so sánh là hàm không thành viên. #include #include class Complex { private: double Real,Imaginary; public:
Complex();//Constructor mac dinh Complex(double R,double I);
Complex (const Complex & Z);//Constructor sao chep
Complex (double R);//Constructor chuyen doi
void Print();//Hien thi so phuc //Cac toan tu tinh toan
friend Complex operator + (Complex Z1,Complex Z2);
friend Complex operator - (Complex Z1,Complex Z2);
Complex operator += (Complex Z);
Complex operator -= (Complex Z); //Cac toan tu so sanh
friend int operator == (Complex Z1,Complex Z2);
friend int operator != (Complex Z1,Complex Z2);
friend int operator > (Complex Z1,Complex Z2);
friend int operator >= (Complex Z1,Complex Z2);
friend int operator < (Complex Z1,Complex Z2);
friend int operator <= (Complex Z1,Complex Z2); private:
double Abs();//Gia tri tuyet doi cua so phuc }; Complex::Complex() { Real = 0.0; Imaginary = 0.0; }
Complex::Complex(double R,double I) { Real = R; Imaginary = I; }
Complex::Complex(const Complex & Z) { Real = Z.Real; Imaginary = Z.Imaginary; } Complex::Complex(double R) { Real = R; Imaginary = 0.0; } void Complex::Print()
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 86 { cout<<'('<}
Complex operator + (Complex Z1,Complex Z2) { Complex Tmp;
Tmp.Real = Z1.Real + Z2.Real;
Tmp.Imaginary = Z1.Imaginary + Z2.Imaginary; return Tmp; }
Complex operator - (Complex Z1,Complex Z2) { Complex Tmp;
Tmp.Real = Z1.Real - Z2.Real;
Tmp.Imaginary = Z1.Imaginary - Z2.Imaginary; return Tmp; }
Complex Complex::operator += (Complex Z) { Real += Z.Real; Imaginary += Z.Imaginary; return *this; }
Complex Complex::operator -= (Complex Z) { Real -= Z.Real; Imaginary -= Z.Imaginary; return *this; }
int operator == (Complex Z1,Complex Z2) {
return (Z1.Real == Z2.Real) && (Z1.Imaginary == Z2.Imaginary); }
int operator != (Complex Z1,Complex Z2) {
return (Z1.Real != Z2.Real) || (Z1.Imaginary != Z2.Imaginary); }
int operator > (Complex Z1,Complex Z2) {
return Z1.Abs() > Z2.Abs(); }
int operator >= (Complex Z1,Complex Z2) {
return Z1.Abs() >= Z2.Abs(); }
int operator < (Complex Z1,Complex Z2) {
return Z1.Abs() < Z2.Abs(); }
int operator <= (Complex Z1,Complex Z2) {
return Z1.Abs() <= Z2.Abs(); } double Complex::Abs() { return
sqrt(Real*Real+Imaginary*Imaginary); } int main()
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 87 { Complex X,Y(4.3,8.2),Z(3.3,1.1); cout<<"X: "; X.Print();
cout< cout< X = Y + 3.6; cout< X.Print(); cout<<" = "; Y.Print(); cout<<" + 3.6 "; X = 3.6 + Y; cout< X.Print(); cout<<" = 3.6 + "; Y.Print(); X = 3.8 - Z; cout< X.Print(); cout<<" = 3.8 - "; Z.Print(); X = Z - 3.8; cout< X.Print(); cout<<" = "; Z.Print(); cout<<" - 3.8 "; return 0; }
Chúng ta ch y ví d 4.3, k t qu hình 4.7
Hình 4.7: K t qu c a ví d 4.3
VI. ĐA NĔNG HÓA CÁC TOÁN T M T NGÔI Các toán t m t ngôi đ
c đa nĕng hóa trong hình 4.8 sau: Toán t Ví d Toán t Ví d + +c ~ ~c - -c ! !a * *c ++ ++c, c++ & &c -- --c, c-- -> c->
Hình 4.8: Các toán t m t ngôi đ c đa nĕng hóa
M t toán t m t ngôi c a l p đ
c đa nĕng hóa nh m t hàm thành viên không tƿnh v i không có tham
s ho c nh m t hàm không thành viên v i m t tham s ; Tham s đó ph i ho c là m t đ i t ng l p ho c là m t tham chi u đ n đ i t ng l p.
Ví d 4.4: L y l i ví d 4.3 và thêm toán t d u tr m t ngôi. 1: #include 2: #include 3: 4: class Complex 5: {
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 88 6: private: 7: double Real,Imaginary; 8: public:
9: Complex(); // Constructor mặc định
10: Complex(double R,double I);
11: Complex (const Complex & Z); // Constructor sao chép
12: Complex (double R); // Constructor chuy n đổi
13: void Print(); // Hi n thị số phức
14: // Các toán tử tính toán
15: friend Complex operator + (Complex Z1,Complex Z2);
16: friend Complex operator - (Complex Z1,Complex Z2);
17: Complex operator += (Complex Z);
18: Complex operator -= (Complex Z);
19: // Toán tử trừ một ngôi 20: Complex operator – ();
21: // Các toán tử so sánh
22: friend int operator == (Complex Z1,Complex Z2);
23: friend int operator != (Complex Z1,Complex Z2);
24: friend int operator > (Complex Z1,Complex Z2);
25: friend int operator >= (Complex Z1,Complex Z2);
26: friend int operator < (Complex Z1,Complex Z2);
27: friend int operator <= (Complex Z1,Complex Z2); 28: private:
29: double Abs(); // Giá trị tuyệt đối của số phức 30: }; 31: 32: Complex::Complex() 33: { 34: Real = 0.0; 35: Imaginary = 0.0; 36: } 37:
38: Complex::Complex(double R,double I) 39: { 40: Real = R; 41: Imaginary = I; 42: } 43:
44: Complex::Complex(const Complex & Z) 45: { 46: Real = Z.Real; 47: Imaginary = Z.Imaginary; 48: } 49:
50: Complex::Complex(double R) 51: { 52: Real = R; 53: Imaginary = 0.0; 54: } 55: 56: void Complex::Print() 57: { 58: cout<<'('<59: } 60:
61: Complex operator + (Complex Z1,Complex Z2) 62: { 63: Complex Tmp;
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 89 64:
65: Tmp.Real = Z1.Real + Z2.Real;
66: Tmp.Imaginary = Z1.Imaginary + Z2.Imaginary; 67: return Tmp; 68: } 69:
70: Complex operator - (Complex Z1,Complex Z2) 71: { 72: Complex Tmp; 73:
74: Tmp.Real = Z1.Real - Z2.Real;
75: Tmp.Imaginary = Z1.Imaginary - Z2.Imaginary; 76: return Tmp; 77: } 78:
79: Complex Complex::operator += (Complex Z) 80: { 81: Real += Z.Real; 82: Imaginary += Z.Imaginary; 83: return *this; 84: } 85:
86: Complex Complex::operator -= (Complex Z) 87: { 88: Real -= Z.Real; 89: Imaginary -= Z.Imaginary; 90: return *this; 91: } 92:
93: Complex Complex::operator - () 94: { 95: Complex Tmp; 96: 97: Tmp.Real = -Real;
98: Tmp.Imaginary = -Imaginary; 99: return Tmp; 100: } 101
102: int operator == (Complex Z1,Complex Z2) 103: {
104: return (Z1.Real == Z2.Real) && (Z1.Imaginary == Z2.Imaginary); 105: } 106:
107: int operator != (Complex Z1,Complex Z2) 108: {
109: return (Z1.Real != Z2.Real) || (Z1.Imaginary != Z2.Imaginary); 110: } 111:
112: int operator > (Complex Z1,Complex Z2) 113: {
114: return Z1.Abs() > Z2.Abs(); 115: } 116:
117: int operator >= (Complex Z1,Complex Z2) 118: {
119: return Z1.Abs() >= Z2.Abs(); 120: } 121:
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 90
122: int operator < (Complex Z1,Complex Z2) 123: {
124: return Z1.Abs() < Z2.Abs(); 125: } 126:
127: int operator <= (Complex Z1,Complex Z2) 128: {
129: return Z1.Abs() <= Z2.Abs(); 130: } 131: 132: double Complex::Abs() 133: {
134: return sqrt(Real*Real+Imaginary*Imaginary); 135: } 136: 137: int main() 138: {
139: Complex X, Y(4.3,8.2), Z(3.3,1.1); 140: 141: cout<<"X: "; 142: X.Print(); 143: cout<144: Y.Print(); 145: cout<146: Z.Print(); 147: X = -Y + 3.6; 148: cout<149: X.Print(); 150: cout<<" = "; 151: (-Y).Print(); 152: cout<<" + 3.6 "; 153: X = -Y + -Z; 154: cout<155: X.Print(); 156: cout<<" = "; 157: (-Y).Print(); 158: cout<<" + "; 159: (-Z).Print(); 160: return 0; 161: }
Chúng ta ch y ví d 4.4, k t qu hình 4.9
Hình 4.9: K t qu c a ví d 4.4
VII. ĐA NĔNG HÓA M T S TOÁN T Đ C BI T
Trong ph n này chúng ta s tìm hi u cách cài đ t m t vài toán t đ c bi t nh () [] ++ -- , = ->
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 91 VII.1. Toán t []
Khi cài đ t các l p vector ho c chu i ký tự, chúng ta c n ph i truy c p đ n t ng ph n t c a chúng,
trong ngôn ng C/C++ đã có toán t [] đ truy c p đ n m t ph n t c a m ng. Đây là toán t hai ngôi, có
d ng a[b] và khi đa nĕng toán t này thì hàm toán t t
ng ng ph i là thành viên c a m t l p.
Ví d 4.5: Đa nĕng hóa toán t [] đ truy c p đ n m t ph n t c a vector. 1: #include 2: 3: class Vector 4: { 5: private: 6: int Size; 7: int *Data; 8: public: 9: Vector(int S=2,int V=0); 10: ~Vector(); 11: void Print() const;
12: int & operator [] (int I); 13: }; 14:
15: Vector::Vector(int S,int V) 16: { 17: Size = S; 18: Data=new int[Size];
19: for(int I=0;I20: Data[I]=V; 21: } 22: 23: Vector::~Vector() 24: { 25: delete []Data; 26: }
27: void Vector::Print() const 28: { 29: cout<<"Vector:(";
30: for(int I=0;I31: cout<32: cout<33: } 34:
35: int & Vector::operator [](int I) 36: { 37: return Data[I]; 38: } 39: 40: int main() 41: { 42: Vector V(5,1); 43: V.Print(); 44: for(int I=0;I<5;++I) 45: V[I]*=(I+1); 46: V.Print(); 47: V[0]=10; 48: V.Print(); 49: return 0; 50: }
Chúng ta ch y ví d 4.5, k t qu hình 4.10
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 92
Hình 4.10: K t qu c a ví d 4.5 Trong ch
ng trình ví d 4.5, hàm toán t c a toán t [] l p Vector tr v m t tham chi u vì toán t
này có th dùng v trái c a phép gán. VII.2. Toán t () Toán t () đ
c dùng đ g i hàm, toán t này g m hai toán h ng: toán h ng đ u tiên là tên hàm, toán
h ng th hai là danh sách các tham s c a hàm. Toán t này có d ng gi ng nh toán t [] và khi đa nĕng
toán t này thì hàm toán t t
ng ng ph i là thành viên c a m t l p.
Ví d 4.6: L y l i ví d 4.5 nh ng đa nĕng hóa toán t () đ truy c p đ n m t ph n t c a vector. 1: #include 2: 3: class Vector 4: { 5: private: 6: int Size; 7: int *Data; 8: public: 9: Vector(int S=2,int V=0); 10: ~Vector(); 11: void Print() const;
12: int & operator () (int I); 13: }; 14:
15: Vector::Vector(int S,int V) 16: { 17: Size = S; 18: Data=new int[Size];
19: for(int I=0;I20: Data[I]=V; 21: } 22: 23: Vector::~Vector() 24: { 25: delete []Data; 26: }
27: void Vector::Print() const 28: { 29: cout<<"Vector:(";
30: for(int I=0;I31: cout<32: cout<33: } 34:
35: int & Vector::operator ()(int I) 36: { 37: return Data[I]; 38: } 39: 40: int main() 41: { 42: Vector V(5,1);
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 93 43: V.Print(); 44: for(int I=0;I<5;++I) 45: V(I)*=(I+1); 46: V.Print(); 47: V(0)=10; 48: V.Print(); 49: return 0; 50: }
Chúng ta ch y ví d 4.6, k t qu hình 4.11
Hình 4.11: K t qu c a ví d 4.6
Ví d 4.7: Đa nĕng hóa toán t () đ truy c p đ n ph n t c a ma tr n. 1: #include 2: 3: class Matrix 4: { 5: private: 6: int Rows,Cols; 7: int **Data; 8: public:
9: Matrix(int R=2,int C=2,int V=0); 10: ~Matrix(); 11: void Print() const;
12: int & operator () (int R,int C); 13: }; 14:
15: Matrix::Matrix(int R,int C,int V) 16: { 17: int I,J; 18: Rows=R; 19: Cols=C; 20: Data = new int *[Rows];
21: int *Temp=new int[Rows*Cols]; 22: for(I=0;I23: { 24: Data[I]=Temp; 25: Temp+=Cols; 26: }
27: for(I=0;I28: for(J=0;J29: Data[I][J]=V; 30: } 31: 32: Matrix::~Matrix() 33: { 34: delete [] Data[0]; 35: delete [] Data; 36: } 37:
38: void Matrix::Print() const 39: { 40: int I,J;
41: for(I=0;IBiên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 94 42: { 43: for(J=0;J44: {
45: cout.width(5); // Hi n thị canh l phải với chi u dài 5 ký tự 46: cout<47: } 48: cout<49: } 50: } 51:
52: int & Matrix::operator () (int R,int C) 53: { 54: return Data[R][C]; 55: } 56: 57: int main() 58: { 59: int I,J; 60: Matrix M(2,3,1);
61: cout<<"Matrix:"<62: M.Print(); 63: for(I=0;I<2;++I) 64: for(J=0;J<3;++J) 65: M(I,J)*=(I+J+1);
66: cout<<"Matrix:"<67: M.Print(); 68: return 0; 69: }
Chúng ta ch y ví d 4.7, k t qu hình 4.12
Hình 4.12: K t qu c a ví d 4.7
VIII. TOÁN T CHUY N Đ I KI U Ph n l n các ch
ng trình x lý thông tin sự đa d ng c a các ki u. Đôi khi t t c các thao tác "d ng l i
bên trong m t ki u". Ch ng h n, m t s nguyên v i m t s nguyên t o thành m t s nguyên (mi n là k t qu không quá l n đ đ
c bi u di n nh m t s nguyên). Nh ng th t c n thi t đ chuy n đ i d li u c a m t
ki u t i d li u c a ki u khác. Đi u này có th x y ra trong các phép gán, các k t qu tính toán, trong vi c
chuy n các giá tr t i hàm, và trong vi c tr v tr t hàm. Trình biên d ch bi t làm th nào đ thực hi n các
chuy n đ i nào đó trong s các ki u có s n. Các l p trình viên có th ép bu c các chuy n đ i trong s các ki u có s n b i ép ki u. Nh ng đ i v i các ki u do ng
i dùng đ nh nghƿa thì trình biên d ch không th tự đ ng bi t làm th nào
chuy n đ i trong s các ki u d li u do ng
i dùng đ nh nghƿa và các ki u có s n. L p trình viên ph i ch rõ
làm sao các chuy n đ i nh v y s xu t hi n. Các chuy n đ i nh th có th đ c thực hi n v i constructor chuy n đ i.
M t toán t chuy n đ i ki u có th đ
c s d ng đ chuy n đ i m t đ i t ng c a m t l p thành đ i t
ng c a m t l p khác ho c thành m t đ i t
ng c a m t ki u có s n. Toán t chuy n đ i ki u nh th ph i
là hàm thành viên không tƿnh và không là hàm friend. Prototype c a hàm thành viên này có cú pháp:
operator <data type> ();
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 95
Ví d 4.14: Toán t chuy n đ i ki u 1: #include 2: 3: class Number 4: { 5: private: 6: float Data; 7: public: 8: Number(float F=0.0) 9: { 10: Data=F; 11: } 12: operator float() 13: { 14: return Data; 15: } 16: operator int() 17: { 18: return (int)Data; 19: } 20: }; 21: 22: int main() 23: { 24: Number N1(9.7), N2(2.6);
25: float X=(float)N1; //Gọi operator float()
26: cout<27: int Y=(int)N2; //Gọi operator int() 28: cout<29: return 0; 30: }
Chúng ta ch y ví d 4.14, k t qu hình 4.19
Hình 4.19: K t qu c a ví d 4.14 IX. TOÁN T NEW VÀ DELETE
Các toán t new delete toàn c c có th đ
c đa nĕng hóa. Đi u này cho phép các l p trình viên C++
có kh nĕng xây dựng m t h th ng c p phát b nh theo ý ng
i dùng, cói cùng giao ti p nh h th ng c p phát m c đ nh.
Có hai cách đa nĕng hóa các toán t newdelete:
• Có th đa nĕng hóa m t cách toàn c c nghƿa là thay th h n các toán t new delete m c đ nh.
• Chúng ta đa nĕng hóa các toán t newdelete v i t cách là hàm thành viên c a l p n u mu n các
toán t newdelete áp d ng đ i v i l p đó. Khi chúng ta dùng newdelete đ i v i l p nào đó, trình
biên d ch s ki m tra xem newdelete có đ
c đ nh nghƿa riêng cho l p đó hay không; n u không thì dùng
newdelete toàn c c (có th đã đ c đa nĕng hóa).
Hàm toán t c a toán t newdelete có prototype nh sau:
void * operator new(size_t size);
void operator delete(void * ptr);
Trong đó tham s ki u size_t đ
c trình biên d ch hi u là kích th c c a ki u d li u đ c trao cho toán t new.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 96
IX.1. Đa nĕng hóa toán t new và delete toàn c c
Ví d 4.15: Đa nĕng hóa toán t newdelete toàn c c đ ng th i ch ng t r ng toán t newdelete
do đa nĕng hóa thay th toán t newdelete m c đ nh. 1: #include 2: #include 3: 4: class Point 5: { 6: private: 7: int X, Y; 8: public: 9: Point(int A=0,int B=0) 10: { 11: X=A; 12: Y=B;
13: cout<<"Constructor!"<14: } 15: ~Point() 16: {
17: cout<<"Destructor!"<18: } 19: void Print() const 20: { 21: cout<<"X="<22: } 23: }; 24:
25: void * operator new(size_t Size) 26: { 27: return malloc(Size); 28: } 29:
30: void operator delete(void *Ptr) 31: { 32: free(Ptr); 33: } 34: 35: int main() 36: { 37: Point *P1,*P2; 38: P1= new Point(10,20); 39: if (P1==NULL) 40: {
41: cout<<"Out of memory!"<42: return 1; 43: } 44: P2= new Point(-10,-20); 45: if (P2==NULL) 46: {
47: cout<<"Out of memory!"<48: return 1; 49: } 50: int *X=new int; 51: if (X==NULL) 52: {
53: cout<<"Out of memory!"<54: return 1;
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 97 55: } 56: *X=10;
57: cout<<"X="<<*X<58: cout<<"Point 1:"; 59: P1->Print(); 60: cout<<"Point 2:"; 61: P2->Print(); 62: delete P1; 63: delete P2; 64: delete X; 65: return 0; 66: }
Chúng ta ch y ví d 4.15, k t qu hình 4.20
Hình 4.20: K t qu c a ví d 4.15
IX.2. Đa nĕng hóa toán t new và delete cho m t l p
N u mu n toán t newdelete có tính ch t đ c bi t ch khi áp d ng cho đ i t ng c a l p nào đó,
chúng ta có th đa nĕng hóa toán t newdelete v i t cách là hàm thành viên c a l p đó. Vi c này không
khác l m so v i cách đa nĕng hóa toán t newdelete m t cách toàn c c.
Ví d 4.16: Đa nĕng hóa toán t newdelete cho m t l p. 1: #include 2: #include 3: class Number 4: { 5: private: 6: int Data; 7: public: 8: Number(int X=0) 9: { 10: Data=X; 11: } 12:
13: void * operator new(size_t Size) 14: {
15: cout<<"Toan tu new cua lop!"<16: return ::new unsigned char[Size]; 17: } 18:
19: void operator delete(void *Ptr) 20: {
21: cout<<"Toan tu delete cua lop!"<22: ::delete Ptr; 23: } 24: 25: void Print() const 26: {
27: cout<<"Data:"<28: }
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 98 29: 30: }; 31: 32: int main() 33: { 34: Number *N; 35: N= new Number(10); 36: if (N==NULL) 37: {
38: cout<<"Out of memory!"<39: return 1; 40: } 41: int *X=new int; 42: if (X==NULL) 43: {
44: cout<<"Out of memory!"<45: return 1; 46: } 47: *X=10;
48: cout<<"X="<<*X<49: N->Print(); 50: delete N; 51: delete X; 52: return 0; 53: }
Chúng ta ch y ví d 4.16, k t qu hình 4.21
Hình 4.21: K t qu c a ví d 4.16 X.
ĐA NĔNG HÓA CÁC TOÁN T CHÈN DÒNG << VÀ TRÍCH DÒNG >>
Chúng ta có th đa nĕng hóa các toán t chèn dòng << (stream insertion) và trích dòng >> (stream
extraction). Hàm toán t c a toán t << đ
c đa nĕng hóa có prototype nh sau:
ostream & operator << (ostream & stream, ClassName Object);
Hàm toán t << tr v tham chi u ch đ n dòng xu t ostream. Tham s th nh t c a hàm toán t <<
m t tham chi u ch đ n dòng xu t ostream, tham s th hai là đ i t ng đ
c chèn vào dòng. Khi s d ng,
dòng trao cho toán t << (tham s th nh t) là toán h ng bên trái và đ i t ng đ c đ a vào dòng (tham s
th hai) là toán h ng bên ph i. Đ b o đ m cách dùng toán t << luôn nh t quán, chúng ta không th đ nh
nghƿa hàm toán t << nh là hàm thành viên c a l p đang xét, thông th
ng nó chính là hàm friend.
Còn hàm toán t c a toán t >> đ
c đa nĕng hóa có prototype nh sau:
istream & operator >> (istream & stream, ClassName Object);
Hàm toán t >> tr v tham chi u ch đ n dòng nh p istream. Tham s th nh t c a hàm toán t này là
m t tham chi u ch đ n dòng nh p istream, tham s th hai là đ i t
ng c a l p đang xét mà chúng ta mu n
t o dựng nh vào d li u l y t dòng nh p. Khi s d ng, dòng nh p đóng vai toán h ng bên trái, đ i t ng
nh n d li u đóng vai toán h ng bên ph i. Cũng nh tr
ng h p toán t <<, hàm toán t >> không là hàm
thành viên c a l p, thông th
ng nó chính là hàm friend.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 99 Ví d 4.17: 1: #include 2: 3: class Point 4: { 5: private: 6: int X,Y; 7: public: 8: Point();
9: friend ostream & operator << (ostream & Out,Point & P);
10: friend istream & operator >> (istream & In,Point & P); 11: }; 12: 13: Point::Point() 14: { 15: X=Y=0; 16: } 17:
18: ostream & operator << (ostream & Out,Point & P) 19: {
20: Out<<"X="<21: return Out; //Cho phép cout<22: } 23:
24: istream & operator >> (istream &In,Point & P) 25: { 26: cout<<"X:"; 27: In>>P.X; 28: cout<<"Y:"; 29: In>>P.Y;
30: return In; //Cho phép cin>>a>>b>>c; 31: } 32: 33: int main() 34: { 35: Point P; 36: cin>>P;
37: cout<<"Point:"<

38: return 0; 39: }
Chúng ta ch y ví d 4.17, k t qu hình 4.22
Hình 4.22: K t qu c a ví d 4.17 XI. M T S VÍ D XI.1. L p String
Ví d 4.18: Chúng ta s xây dựng m t l p x lý vi c t o và thao tác trên các chu i (string). C++ không
cài s n ki u d li u chu i. Nh ng C++ cho phép chúng ta thêm ki u chu i nh m t l p thông qua c ch đa nĕng hóa. #include #include #include
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 100 #include class String { private:
char *Ptr; //Con tro tro den diem bat dau cua chuoi int Length; //Chieu dai chuoi public:
String(const char * = ""); //Constructor chuyen doi
String(const String &); //Constructor sao chep ~String(); //Destructor
const String &operator=(const String &); //Phep gan
String &operator+=(const String &); //Phep noi int operator!() const; //Kiem tra chuoi rong
int operator==(const String &) const;
int operator!=(const String &) const;
int operator<(const String &) const;
int operator>(const String &) const;
int operator>=(const String &) const;
int operator<=(const String &) const;
char & operator[](int); //Tra ve ky tu tham chieu
String &operator()(int, int); //Tra ve mot chuoi con int GetLength() const;
friend ostream &operator<<(ostream &, const String &);
friend istream &operator>>(istream &, String &); };
//Constructor sao chep: Chuyen doi char * thanh String String::String(const char *S) {
cout << "Conversion constructor: " << S << endl; Length = strlen(S); Ptr = new char[Length + 1]; assert(Ptr != 0); strcpy(Ptr, S); }
String::String(const String &Copy) {
cout << "Copy constructor: " << Copy.Ptr << endl; Length = Copy.Length; Ptr = new char[Length + 1]; assert(Ptr != 0); strcpy(Ptr, Copy.Ptr); } //Destructor String::~String() {
cout << "Destructor: " << Ptr << endl; delete [] Ptr; }
const String &String::operator=(const String &Right) {
cout << "operator= called" << endl; if (&Right != this) { delete [] Ptr; Length = Right.Length; Ptr = new char[Length + 1]; assert(Ptr != 0); strcpy(Ptr, Right.Ptr); } else
cout << "Attempted assignment of a String to itself" << endl; return *this; }
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 101
String &String::operator+=(const String &Right) { char *TempPtr = Ptr; Length += Right.Length; Ptr = new char[Length + 1]; assert(Ptr != 0); strcpy(Ptr, TempPtr); strcat(Ptr, Right.Ptr); delete [] TempPtr; return *this; } int String::operator!() const { return Length == 0; }
int String::operator==(const String &Right) const {
return strcmp(Ptr, Right.Ptr) == 0; }
int String::operator!=(const String &Right) const {
return strcmp(Ptr, Right.Ptr) != 0; }
int String::operator<(const String &Right) const {
return strcmp(Ptr, Right.Ptr) < 0; }
int String::operator>(const String &Right) const {
return strcmp(Ptr, Right.Ptr) > 0; }
int String::operator>=(const String &Right) const {
return strcmp(Ptr, Right.Ptr) >= 0; }
int String::operator<=(const String &Right) const {
return strcmp(Ptr, Right.Ptr) <= 0; }
char &String::operator[](int Subscript) {
assert(Subscript >= 0 && Subscript < Length); return Ptr[Subscript]; }
String &String::operator()(int Index, int SubLength) {
assert(Index >= 0 && Index < Length && SubLength >= 0); String *SubPtr = new String; assert(SubPtr != 0);
if ((SubLength == 0) || (Index + SubLength > Length))
SubPtr->Length = Length - Index + 1; else
SubPtr->Length = SubLength + 1; delete SubPtr->Ptr;
SubPtr->Ptr = new char[SubPtr->Length]; assert(SubPtr->Ptr != 0);
strncpy(SubPtr->Ptr, &Ptr[Index], SubPtr->Length);
SubPtr->Ptr[SubPtr->Length] = '\0'; return *SubPtr; } int String::GetLength() const { return Length;
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 102 }
ostream &operator<<(ostream &Output, const String &S) { Output << S.Ptr; return Output; }
istream &operator>>(istream &Input, String &S) { char Temp[100];
Input >> setw(100) >> Temp; S = Temp; return Input; } int main() {
String S1("happy"), S2(" birthday"), S3;
cout << "S1 is \"" << S1 << "\"; S2 is \"" << S2
<< "\"; S3 is \"" << S3 << '\"' << endl
<< "The results of comparing S2 and S1:" << endl
<< "S2 == S1 yields " << (S2 == S1) << endl
<< "S2 != S1 yields " << (S2 != S1) << endl
<< "S2 > S1 yields " << (S2 > S1) << endl
<< "S2 < S1 yields " << (S2 < S1) << endl
<< "S2 >= S1 yields " << (S2 >= S1) << endl
<< "S2 <= S1 yields " << (S2 <= S1) << endl;
cout << "Testing !S3:" << endl; if (!S3) {
cout << "S3 is empty; assigning S1 to S3;" << endl; S3 = S1;
cout << "S3 is \"" << S3 << "\"" << endl; }
cout << "S1 += S2 yields S1 = "; S1 += S2;
cout << S1 << endl;
cout << "S1 += \" to you\" yields" << endl; S1 += " to you";
cout << "S1 = " << S1 << endl;
cout << "The substring of S1 starting at" << endl
<< "location 0 for 14 characters, S1(0, 14), is: "
<< S1(0, 14) << endl;
cout << "The substring of S1 starting at" << endl
<< "location 15, S1(15, 0), is: " << S1(15, 0) <
String *S4Ptr = new String(S1);
cout << "*S4Ptr = " << *S4Ptr <
cout << "assigning *S4Ptr to *S4Ptr" << endl; *S4Ptr = *S4Ptr;
cout << "*S4Ptr = " << *S4Ptr << endl; delete S4Ptr; S1[0] = 'H'; S1[6] = 'B';
cout <<"S1 after S1[0] = 'H' and S1[6] = 'B' is: "<< S1 << endl;
cout << "Attempt to assign 'd' to S1[30] yields:" << endl;
S1[30] = 'd'; //Loi: Chi so vuot khoi mien!!! return 0; }
Chúng ta ch y ví d 4.18, k t qu hình 4.23
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 103
Hình 4.23: K t qu c a ví d 4.18 XI.2. L p Date Ví d 4.19: #include class Date { private: int Month; int Day; int Year;
static int Days[]; //Mang chua so ngay trong thang
void HelpIncrement(); //Ham tang ngay len mot public:
Date(int M = 1, int D = 1, int Y = 1900);
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 104 void SetDate(int, int, int); Date operator++(); //Tien to
Date operator++(int); //Hau to const Date &operator+=(int);
int LeapYear(int); //Kiem tra nam nhuan
int EndOfMonth(int); //Kiem tra cuoi thang
friend ostream &operator<<(ostream &, const Date &); };
int Date::Days[] = {31, 28, 31, 30, 31, 30,31, 31, 30, 31, 30, 31};
Date::Date(int M, int D, int Y) { SetDate(M, D, Y); }
void Date::SetDate(int MM, int DD, int YY) {
Month = (MM >= 1 && MM <= 12) ? MM : 1;
Year = (YY >= 1900 && YY <= 2100) ? YY : 1900;
if (Month == 2 && LeapYear(Year))
Day = (DD >= 1 && DD <= 29) ? DD : 1; else
Day = (DD >= 1 && DD <= Days[Month-1]) ? DD : 1; } Date Date::operator++() { HelpIncrement(); return *this; } Date Date::operator++(int) { Date Temp = *this; HelpIncrement(); return Temp; }
const Date &Date::operator+=(int AdditionalDays) {
for (int I = 1; I <= AdditionalDays; I++) HelpIncrement(); return *this; } int Date::LeapYear(int Y) {
if (Y % 400 == 0 || (Y % 100 != 0 && Y % 4 == 0) ) return 1; //Nam nhuan return 0; //Nam khong nhuan } int Date::EndOfMonth(int D) {
if (Month == 2 && LeapYear(Year)) return D == 29; return D == Days[Month-1]; } void Date::HelpIncrement() {
if (EndOfMonth(Day) && Month == 12) //Het nam { Day = 1; Month = 1; ++Year; } else
if (EndOfMonth(Day)) //Het thang {
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 105 Day = 1; ++Month; } else ++Day; }
ostream &operator<<(ostream &Output, const Date &D) { static
char*MonthName[12]={"January","February","March","April","May", "June","July", "August","September", "October","November", "December" };
Output << MonthName[D.Month-1] << ' '<< D.Day << ", " << D.Year; return Output; } int main() {
Date D1, D2(12, 27, 1992), D3(0, 99, 8045);
cout << "D1 is " << D1 << endl
<< "D2 is " << D2 << endl
<< "D3 is " << D3 << endl << endl;
cout << "D2 += 7 is " << (D2 += 7) << endl << endl; D3.SetDate(2, 28, 1992);
cout << " D3 is " << D3 << endl;
cout << "++D3 is " << ++D3 << endl << endl; Date D4(3, 18, 1969);
cout << "Testing the preincrement operator:" << endl
<< " D4 is " << D4 << endl;
cout << "++D4 is " << ++D4 << endl;
cout << " D4 is " << D4 << endl << endl;
cout << "Testing the postincrement operator:" << endl
<< " D4 is " << D4 << endl;
cout << "D4++ is " << D4++ << endl;
cout << " D4 is " << D4 << endl; return 0; }
Chúng ta ch y ví d 4.19, k t qu hình 4.24
Hình 4.24: K t qu c a ví d 4.19
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 106 BÀI T P
Bài 1: Xây dựng l p Complex ch a các s ph c g m các phép toán: +, -, *, /, +=, -=, *=, /=, ==, !=, >, >=, <, <=.
Bài 2: Xây dựng l p String đ thực hi n các thao tác trên các chu i, trong l p này có các phép toán:
Phép toán + đ n i hai chu i l i v i nhau.
Phép toán = đ gán m t chu i cho m t chu i khác.
Phép toán [] truy c p đ n m t ký tự trong chu i.
Các phép toán so sánh: ==, !=, >, >=, <, <=
Bài 3: Xây dựng l p ma tr n Matrix g m các phép toán c ng, tr và nhân hai ma tr n b t kỳ.
Bài 4: Xây dựng l p Rational ch a các s h u t g m các phép toán +, - , *, /, ==, !=, >, >=, <, <=.
Bài 5: Xây dựng l p Time đ l u tr gi , phút, giây g m các phép toán:
Phép c ng gi a d li u th i gian và m t s nguyên là s giây, k t qu là m t d li u th i gian.
Phép tr gi a hai d li u th i gian, k t qu là m t s nguyên chính là s giây.
++ và – đ tĕng hay gi m th i gian xu ng m t giây. Các phép so sánh.
Bài 6: Xây dựng l p Date đ l u tr ngày, tháng, nĕm g m các phép toán:
Phép c ng gi a d li u Date và m t s nguyên là s ngày, k t qu là m t d li u Date.
Phép tr gi a hai d li u Date, k t qu là m t s nguyên chính là s ngày.
++ và – đ tĕng hay gi m th i gian xu ng m t ngày. Các phép so sánh.
Bài 7: Các s nguyên 32 bit có th bi u di n trong ph m vi t 2147483648 đ n 2147483647. Hãy
xây dựng l p HugeInt đ bi u di n các s nguyên 32 bit g m các phép toán +, -, *, /
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 107 CHƯƠNG 5 TÍNH K TH A I. D N NH P Trong ch ng này và ch
ng k , chúng ta tìm hi u hai kh nĕng mà l p trình h ng đ i t ng cung c p
là tính k th a (inheritance) và tính đa hình (polymorphism). Tính k th a là m t hình th c c a vi c s d ng
l i ph n m m trong đó các l p m i đ
c t o t các l p đã có b ng cách "hút" các thu c tính và hành vi c a
chúng và tô đi m thêm v i các kh nĕng mà các l p m i đòi h i. Vi c s d ng l i ph n m m ti t ki m th i gian trong vi c phát tri n ch
ng trình. Nó khuy n khích s d ng l i ph n m m ch t l ng cao đã th thách
và g l i, vì th gi m thi u các v n đ sau khi m t h tr thành chính th c. Tính đa hình cho phép chúng ta vi t các ch
ng trình trong m t ki u cách chung đ x lý các l p có liên h nhau. Tính k th a và tính đa
hình các k thu t có hi u lực đ i v i sự chia v i sự ph c t p c a ph n m m.
Khi t o m t l p m i, thay vì vi t các thành viên d li u và các hàm thành viên, l p trình viên có th thi t k mà l p m i đ
c k th a các thành viên d li u và các hàm thành viên c a l p tr c đ nh nghƿa là l p c s (base class). L p m i đ
c tham chi u là l p d n xu t (derived class). M i l p d n xu t tự nó tr thành
m t ng c là m t l p c s cho l p d n xu t t ng lai nào đó. Bình th
ng m t l p d n xu t thêm các thành viên d li u và các hàm thành viên, vì th m t l p d n xu t thông th
ng r ng h n l p c s c a nó. M t l p d n xu t đ
c ch đ nh h n m t l p c s và bi u di n m t nhóm c a các đ i t ng nh h n. V i đ i t
ng đ n, l p d n xu t, l p d n xu t b t đ u bên ngoài
thực ch t gi ng nh l p c s . S c m nh thực sự c a sự k th a là kh nĕng đ nh nghƿa trong l p d n xu t
các ph n thêm, thay th ho c tinh l c các đ c tính k th a t l p c s . M i đ i t
ng c a m t l p d n xu t cũng là m t đ i t
ng c a l p c s c a l p d n xu t đó. Tuy nhiên
đi u ng c l i không đúng, các đ i t ng l p c s không là các đ i t ng c a các l p d n xu t c a l p c
s đó. Chúng ta s l y m i quan h "đ i t ng l p d n xu t là m t đ i t
ng l p c s " đ thực hi n các thao
tác quan tr ng nào đó. Ch ng h n, chúng ta có th lu n m t sự đa d ng c a các đ i t ng khác nhau có liên
quan thông qua s k th a thành danh sách liên k t c a các đ i t
ng l p c s . Đi u này cho phép sự đa d ng c a các đ i t
ng đ x lý m t cách t ng quát.
Chúng ta phân bi t gi a "là m t" (is a) quan h và "có m t" (has a) quan h . "là m t" là sự k th a.
Trong m t "là m t" quan h , m t đ i t
ng c a ki u l p d n xu t cũng có th đ c x lý nh m t đ i t ng
c a ki u l p c s . "có m t" là sự ph c h p (composition). Trong m t "có m t" quan h , m t đ i t ng l p có m t hay nhi u đ i t
ng c a các l p khác nh là các thành viên, do đó l p bao các đ i t ng này g i là
l p ph c h p (composed class). II. K TH A Đ N II.1. Các
l p c s và các l p d n xu t Th ng m t đ i t
ng c a m t l p th t sự là m t đ i t ng c a l p khác cũng đ c. M t hình ch nh t
là m t t giác, vì th l p Rectangle có th k th a t l p Quadrilateral. Trong khung c nh này, l p
Quadrilateral g i là m t l p c s và l p Rectangle g i là m t l p d n xu t. Hình 5.1 cho chúng ta m t vài ví d v k th a đ n. Các ngôn ng l p trình h ng đ i t
ng nh SMALLTALK s d ng thu t ng khác: Trong k th a, l p c s đ
c g i là l p cha (superclass), l p d n xu t đ c g i là l p con (subclass). L p c s L p d n xu t Student GraduateStudent UndergraduateStudent Shape Circle Triangle Rectangle Loan CarLoan
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 108 HomeImprovementLoan MortgageLoan Employee FacultyMember StaffMember Acount CheckingAcount SavingsAcount
Hình 5.1: M t vài k th a đ n.
Sự k th a hình thành các c u trúc phân c p gi ng cây (còn g i là cây ph h ). M t l p c s t n t i
trong m t phân c p quan h v i l p d n xu t c a nó. M t l p có th t n t i ch c ch n b i chính nó, nh ng khi m t l p đ
c s d ng v i c ch c a sự k th a thì l p tr thành ho c là m t l p c s mà cung c p các
thu c tính và các hành vi cho các l p khác, ho c là l p tr thành m t l p d n xu t mà k th a các thu c tính và các hành vi.
Chúng ta phát tri n m t phân c p k th a đ n. M t tr
ng đ i h c c ng đ ng đ c thù có hàng ngàn ng
i mà là các thành viên c ng đ ng. Nh ng ng i này g m các ng
i làm công và các sinh viên. Nh ng ng
i làm công ho c là các thành viên khoa ho c các thành viên nhân viên. Các thành viên khoa ho c là các
nhà qu n lý ho c gi ng viên. Đi u này tr thành phân c p k th a nh hình 5.2
Hình 5.2: M t phân c p k th a cho các thành viên c a tr ng đ i h c c ng đ ng.
Phân c p k th a quan tr ng khác là phân c p Shape hình 5.3.
Hình 5.3: Phân c p l p Shape
Đ ch đ nh l p CommissionWorker đ c d n xu t t l p Employee, l p CommissionWorker đ c đ nh nghƿa nh sau:
class CommissionWorker: public Employee {…………. };
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 109
Đi u này đ c g i là k th a public và là lo i mà ph n l n đ c s d ng. Ngoài ra chúng ta còn có k
th a private và k th a protected. V i k th a public, các thành viên public protected c a l p c s
đ c k th a nh là các thành viên public protected c a l p d n xu t t ng ng. Nên nh r ng các thành
viên private c a l p c s không th truy c p t các l p d n xu t c a l p đó. X lý các đ i t ng l p c s và các đ i t ng l p d n xu t t ng tự; ph bi n là đ c bi u di n b ng
các thu c tính và các hành vi c a l p c s . Các đ i t
ng c a b t kỳ l p nào d n xu t t m t l p c s chung có th t t c đ c x lý nh các đ i t ng c a l p c s đó.
II.2. Các thành viên protected
Các thành viên public c a m t l p c s đ
c truy c p b i t t c các hàm trong ch ng trình. Các thành
viên private c a m t l p c s ch đ
c truy c p b i các hàm thành viên và các hàm friend c a l p c s .
Truy c p protected ph c v nh m t m c trung gian c a sự b o v gi a truy c p public và truy c p
private. Các thành viên protected c a m t l p c s có th ch đ
c truy c p b i các hàm thành viên và các
hàm friend c a l p c s và b i các hàm thành viên và các hàm friend c a l p d n xu t.
Các thành viên l p d n xu t k th a public có th tham kh o t i các thành viên public protected
b ng cách s d ng các tên thành viên. II.3. Ép
ki u các con tr l p c s t i các con tr l p d n xu t M t đ i t
ng c a m t l p d n xu t k th a public cũng có th đ c x lý nh m t đ i t ng c a l p c s c a nó t ng ng. Nh ng ng
c l i không đúng: m t đ i t
ng l p c s cũng không tự đ ng là m t đ i t ng l p d n xu t.
Tuy nhiên, có th s d ng ép ki u đ chuy n đ i m t con tr l p c s thành m t con tr l p d n xu t. Ví d 5.1: Ch ng trình sau s đ
c chia thành nhi u file (g m các file .H và .CPP) và t o m t project
có tên là CT5_1.PRJ g m các file .cpp File POINT.H: 1: //POINT.H
2: //Định nghĩa lớp Point 3: #ifndef POINT_H 4: #define POINT_H 5: 6: class Point 7: { 8: protected: 9: float X,Y; 10: public:
11: Point(float A= 0, float B= 0);
12: void SetPoint(float A, float B); 13: float GetX() const 14: { 15: return X; 16: } 17: float GetY() const 18: { 19: return Y; 20: }
21: friend ostream & operator <<(ostream &Output, const Point &P); 22: }; 23: 24: #endif File POINT.CPP 1: //POINT.CPP
2: //Định nghĩa các hàm thành viên của lớp Point 3: #include 4: #include "point.h"
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 110 5:
6: Point::Point(float A, float B) 7: { 8: SetPoint(A, B); 9: } 10:
11: void Point::SetPoint(float A, float B) 12: { 13: X = A; 14: Y = B; 15: } 16:
17: ostream & operator <<(ostream &Output, const Point &P) 18: {
19: Output << '[' << P.X << ", " << P.Y << ']'; 20: return Output; 21: } File CIRCLE.H 1: //CIRCLE.H
2: //Định nghĩa lớp Circle 3: #ifndef CIRCLE_H 4: #define CIRCLE_H 5: 6: #include "point.h"
7: class Circle : public Point 8: { 9: protected: 10: float Radius; 11: public:
12: Circle(float R = 0.0, float A = 0, float B = 0); 13: void SetRadius(float R); 14: float GetRadius() const; 15: float Area() const;
16: friend ostream & operator <<(ostream &Output, const Circle &C); 17: }; 18: 19: #endif File CIRCLE.CPP 1: //CIRCLE.CPP
2: //Định nghĩa các hàm thành viên của lớp Circle 3: #include 4: #include 5: #include "circle.h" 6:
7: Circle::Circle(float R, float A, float B): Point(A, B) 8: { 9: Radius = R; 10: } 11:
12: void Circle::SetRadius(float R) 13: { 14: Radius = R; 15: } 16:
17: float Circle::GetRadius() const 18: {
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 111 19: return Radius; 20: } 21:
22: float Circle::Area() const 23: {
24: return 3.14159 * Radius * Radius; 25: } 26:
27: //Xuất một Circle theo dạng: Center = [x, y]; Radius = #.##
28: ostream & operator <<(ostream &Output, const Circle &C) 29: {
30: Output << "Center = [" << C.X << ", " << C.Y
31: << "]; Radius = " << setiosflags(ios::showpoint)
32: << setprecision(2) << C.Radius; 33: return Output; 34: } File CT5_1.CPP: 1: //CT5_1.CPP
2: //Chương trình 5.1: Ép các con trỏ lớp cơ sở tới các con trỏ lớp d n xuất 3: #include 4: #include 5: #include "point.h" 6: #include "circle.h" 7: 8: int main() 9: {
10: Point *PointPtr, P(3.5, 5.3);
11: Circle *CirclePtr, C(2.7, 1.2, 8.9);
12: cout << "Point P: "<

13 //Xử lý một Circle như một Point (chỉ xem một phần lớp cơ sở) 14: PointPtr = &C;
15: cout << endl << "Circle C (via *PointPtr): "<<*PointPtr<16 //Xử lý một Circle như một Circle 17: PointPtr = &C;
18: CirclePtr = (Circle *) PointPtr;
19: cout << endl << "Circle C (via *CirclePtr): " << endl
20: <<*CirclePtr<< endl << "Area of C (via CirclePtr): "
21: << CirclePtr->Area() << endl;
22: //Nguy hi m: Xem một Point như một Circle 23: PointPtr = &P;
24: CirclePtr = (Circle *) PointPtr;
25: cout << endl << "Point P (via *CirclePtr): "<< endl
26: <<*CirclePtr<< endl << "Area of object CirclePtr points to: " 27: <Area() << endl; 28: return 0; 29: }
Chúng ta ch y ví d 5.1, k t qu hình 5.4
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 112
Hình 5.4: K t qu c a ví d 5.1
Trong đ nh nghƿa l p Point, các thành viên d li u X Y đ
c ch đ nh là protected, đi u này cho phép
các l p d n xu t t l p Point truy c p trực ti p các thành viên d li u k th a. N u các thành viên d li u này đ
c ch đ nh là private, các hàm thành viên public c a Point ph i đ c s d ng đ truy c p d li u, ngay c b i các l p d n xu t. L p Circle đ
c k th a t l p Point v i k th a public ( dòng 7 file CIRCLE.H), t t c các thành viên c a l p Point đ
c k th a thành l p Circle. Đi u này có nghƿa là giao di n public bao g m các hàm
thành viên public c a Point cũng nh các hàm thành viên Area(), SetRadius()GetRadius().
Constructor l p Circle ph i bao g m constructor l p Point đ kh i đ ng ph n l p c s c a đ i t ng
l p Circle dòng 7 file CIRCLE.CPP, dòng này có th đ c vi t l i nh sau:
Circle::Circle(float R, float A, float B)
: Point(A, B) //G i constructor c a l p c s
Các giá tr A B đ
c chuy n t constructor l p Circle t i constructor l p Point đ kh i đ ng các
thành viên X Y c a l p c s . N u constructor l p Circle không bao g m constructor l p Point thì
constructor l p Point g i v i các giá tr m c đ nh cho X Y (nghƿa là 0 và 0). N u l p Point không cung c p
m t constructor m c đ nh thì trình biên d ch phát sinh l i. Trong ch
ng trình chính (file CT5_1.CPP) gán m t con tr l p d n xu t (đ a ch c a đ i t ng C) cho
con tr l p c s PointPtr và xu t đ i t
ng C c a Circle b ng toán t chèn dòng c a l p Point ( dòng 14
và 15). Chú ý r ng ch ph n Point c a đ i t
ng C c a Circle đ
c hi n th . Nó luôn luôn đúng đ gán m t
con tr l p d n xu t cho con tr l p c s b i vì m t đ i t ng l p d n xu t là m t đ i t ng l p c s . Con
tr l p c s ch trông th y ph n l p c s c a đ i t
ng l p d n xu t. Trình biên d ch thực hi n m t chuy n
đ i ng m c a con tr l p d n xu t cho m t con tr l p c s . Sau đó ch
ng trình gán m t con tr l p d n xu t (đ a ch c a đ i t
ng C) cho con tr l p c s
PointPtr và ép PointPtr tr v ki u Circle *. K t qu c a ép ki u đ
c gán cho CirclePtr. Đ i t ng C c a Circle đ
c xu t b ng cách s d ng toán t chèn dòng c a Circle. Di n tích c a đ i t ng C đ c xu t
thông qua CirclePtr. Các k t qu này là giá tr di n tích đúng b i vì các con tr luôn luôn đ c tr t i m t
đ i t ng Circle (t dòng 17 đ n 22). K ti p, ch
ng trình gán m t con tr l p c s (đ a ch c a đ i t
ng P) cho con tr l p c s PointPtr
và ép PointPtr tr v ki u Circle *. K t qu c a ép ki u đ
c gán cho CirclePtr. Đ i t ng P đ c xu t s
d ng toán t chèn dòng c a l p Circle. Chú ý r ng giá tr xu t c a thành viên Radius "kỳ l ". Vi c xu t m t
Point nh m t Circle đ a đ n m t giá tr không h p l cho Radius b i vì các con tr luôn đ c tr đ n m t
đ i t ng Point. M t đ i t ng Point không có m t thành viên Radius. Vì th , ch ng trình xu t giá tr "rác"
đ i v i thành viên d li u Radius. Chú ý r ng giá tr c a di n tích là 0.0 b i vì tính toàn này dựa trên giá tr
không t n t i c a Radius (t dòng 23 đ n 27).Rõ ràng, truy c p các thành viên d li u mà không ph i đó
thì nguy hi m. G i các hàm thành viên mà không t n t i có th phá h y ch ng trình.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 113
II.4. Đ nh nghƿa l i các thành viên l p c s trong m t l p d n xu t
M t l p d n xu t có th đ nh nghƿa l i m t hàm thành viên l p c s . Đi u này đ c g i là overriding. Khi hàm đó đ
c đ c p b i tên trong l p d n xu t, phiên b n c a l p d n xu t đ c ch n m t cách tự đ ng.
Toán t đ nh ph m vi có th s d ng đ truy c p phiên b n c a l p c s t l p d n xu t. II.5. Các
l p c s public, protected và private
Khi d n xu t m t l p t m t l p c s , l p c s có th đ
c k th a là public, protectedprivate.
class <drived_class_name> : <type_of_inheritance> <base_class_name> {……………….. };
Trong đó type_of_inheritancepublic, protected ho c private. M c đ nh là private.
Khi d n xu t m t l p t m t l p c s public, các thành viên public c a l p c s tr thành các thành
viên public c a l p d n xu t, và các thành viên protected c a l p c s tr thành các thành viên protected
c a l p d n xu t. Các thành viên private c a l p c s không bao gi đ
c truy c p trực ti p t m t l p d n xu t.
Khi d n xu t m t l p t m t l p c s protected, các thành viên public protected c a l p c s tr
thành các thành viên protected c a l p d n xu t. Khi d n xu t m t l p t m t l p c s private, các thành
viên public protected c a l p c s tr thành các thành viên private c a l p d n xu t.
B ng sau (hình 5.6)t ng k t kh nĕng truy c p các thành viên l p c s trong m t l p d n xu t dựa trên
thu c tính xác đ nh truy c p thành viên c a các thành viên trong l p c s và ki u k th a. Ki u k th a K th a public K th a protected K th a private
public trong l p d n xu t. protected trong l p d n xu t. private trong l p d n
Có th truy c p trực ti p b i Có th truy c p trực ti p b i xu t. các hàm thành viên không các hàm thành viên không Có th truy c p trực ti p public
tƿnh, các hàm friend và các
tƿnh, các hàm friend. b i các hàm thành viên hàm không thành viên. không tƿnh, các hàm friend.
protected trong l p d n
protected trong l p d n xu t. private trong l p d n xu t.
Có th truy c p trực ti p b i xu t.
Có th truy c p trực ti p b i các hàm thành viên không Có th truy c p trực ti p protected các hàm thành viên không
tƿnh, các hàm friend. b i các hàm thành viên
tƿnh, các hàm friend. không tƿnh, các hàm friend. D u trong l p d n xu t. D u trong l p d n xu t. D u trong l p d n xu t.
Có th truy c p trực ti p b i Có th truy c p trực ti p b i Có th truy c p trực ti p các hàm thành viên không các hàm thành viên không b i các hàm thành viên
tƿnh, các hàm friend thông
tƿnh, các hàm friend thông không tƿnh, các hàm private qua các hàm thành viên qua các hàm thành viên friend thông qua các
public protected c a l p public protected c a l p hàm thành viên public c s . c s .
protected c a l p c s .
Hình 5.7: T ng k t kh nĕng truy c p thành viên l p c s trong l p d n xu t.
II.6. Các contructor và destructor l p d n xu t
B i vì m t l p d n xu t k t th a các thành viên l p c s c a nó (ngo i tr constructor và destructor), khi m t đ i t ng c a l p d n xu t đ
c kh i đ ng, constructor l p c s ph i đ c g i đ kh i đ ng các
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 114
thành viên l p c s c a đ i t
ng l p d n xu t. M t b kh i t o l p c s (s d ng cú pháp gi ng nh b
kh i t o thành viên) có th đ
c cung c p trong constructor l p d n xu t đ g i t ng minh constructor l p
c s , m t khác constructor l p d n xu t s g i constructor m c đ nh l p c s .
Các constructor l p c s và các toán t gán l p c s không đ
c k th a b i l p d n xu t.Tuy nhiên,
các constructor và các toán t gán l p d n xu t có th g i các constructor và các toán t gán l p c s .
M t constructor l p d n xu t luôn g i constructor l p c s c a nó đ u tiên đ kh i t o các thành viên
l p c s c a l p d n xu t. N u constructor l p d n b b qua, constructor m c đ nh l p d n g i constructor l p c s . Các destructor đ c g i theo th tự ng
c l i th tự g i các constructor, vì th destructor l p d n xu t đ c g i tr c destructor l p c s c a nó.
Ví d 5.4: Minh h a th tự các contructor và destructor l p c s và l p d n xu t đ c g i và project có tên là CT5_4.PRJ File POINT.H 1: //POINT.H
2: //Định nghĩa lớp Point 3: #ifndef POINT_H 4: #define POINT_H 5: 6: class Point 7: { 8: public:
9: Point(float A= 0.0, float B= 0.0); 10: ~Point(); 11: protected: 12: float X, Y; 13: }; 14: 15: #endif File POINT.CPP 1: //POINT.CPP
2: //Định nghĩa các hàm thành viên lớp Point 3: #include 4: #include "point.h" 5:
6: Point::Point(float A, float B) 7: { 8: X = A; 9: Y = B;
10: cout << "Point constructor: "
11: << '[' << X << ", " << Y << ']' << endl; 12: } 13: 14: Point::~Point() 15: {
16: cout << "Point destructor: "
17: << '[' << X << ", " << Y << ']' << endl; 18: } File CIRCLE.H 1: //CIRCLE.H
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 115
2: //Định nghĩa lớp Circle 3: #ifndef CIRCLE_H 4: #define CIRCLE_H 5: 6: #include "point.h" 7: #include 8:
9: class Circle : public Point 10: { 11: public:
12: Circle(float R = 0.0, float A = 0, float B = 0); 13: ~Circle(); 14: private: 15: float Radius; 16: }; 17: 18: #endif File CIRCLE.CPP 1: //CIRCLE.CPP
2: //Định nghĩa các hàm thành viên lớp Circle 3: #include "circle.h" 4:
5: Circle::Circle(float R, float A, float B): Point(A, B) 6: { 7: Radius = R;
8: cout << "Circle constructor: Radius is "
9: << Radius << " [" << A << ", " << B << ']' << endl; 10: } 11: 12: Circle::~Circle() 13: {
14: cout << "Circle destructor: Radius is "
15: << Radius << " [" << X << ", " << Y << ']' << endl; 16: } File CT5_4.CPP 1: //CT5_4.CPP 2: //Chương trình 5.4 3: #include 4: #include "point.h" 5: #include "circle.h" 6: int main() 7: { 8: { 9: Point P(1.1, 2.2); 10: } 11: cout << endl; 12: Circle C1(4.5, 7.2, 2.9); 13: cout << endl; 14: Circle C2(10, 5, 5); 15: cout << endl; 16: return 0; 17: }
Chúng ta ch y ví d 5.4, k t qu hình 5.8
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 116
Hình 5.8: K t qu c a ví d 5.4
II.7. Chuy n đ i ng m đ nh đ i t
ng l p d n xu t sang đ i t ng l p c s M c dù m t đ i t
ng l p d n xu t cũng là m t đ i t
ng l p c s , ki u l p d n xu t và ki u l p c s thì khác nhau. Các đ i t ng l p d n xu t có th đ c x lý nh các đ i t
ng l p c s . Đi u này có ý
nghƿa b i vì l p d n xu t có các thành viên t
ng ng v i m i thành viên c a l p c s . Phép gán theo chi u h ng ng
c l i là không cho phép b i vì gán m t đ i t ng l p c s cho đ i t ng l p d n xu t s cho
phép thêm các thành viên l p d n xu t không xác đ nh. M t con tr tr t i m t đ i t ng l p d n xu t có th đ
c chuy n đ i ng m đ nh thành m t con tr tr t i m t đ i t ng l p c s b i vì m t đ i t ng l p d n xu t là m t đ i t ng l p c s .
Có b n cách đ tr n và đ i sánh các con tr l p c s và các con tr l p d n xu t v i các đ i t ng l p c s và các đ i t ng l p d n xu t:
• Tham chi u t i m t đ i t ng l p c s v i m t con tr l p c s thì không ph c t p.
• Tham chi u t i m t đ i t ng l p d n xu t v i m t con tr l p d n xu t thì không ph c t p.
• Tham chi u t i đ i t ng l p d n xu t v i m t con tr l p c s thì an toàn b i vì đ i t ng l p d n xu t cũng là m t đ i t
ng l p c s c a nó. Nh v y đo n mã ch có th tham chi u t i các thành
viên l p c s . N u đo n mã tham chi u t i các thành viên l p d n xu t thông qua con tr l p c s ,
trình biên d ch s báo m t l i v cú pháp.
• Tham chi u t i m t đ i t ng l p c s v i m t con tr l p d n xu t thì có l i cú pháp. Đ u tiên con tr l p d n xu t ph i đ c ép sang con tr l p c s .
III. ĐA K TH A (MULTIPLE INHERITANCE) M t l p có th đ
c d n xu t t nhi u l p c s , sự d n xu t nh v y đ
c g i là đa k th a. Đa k th a
có nghƿa là m t l p d n xu t k th a các thành viên c a các l p c s khác nhau. Kh nĕng m nh này
khuy n khích các d ng quan tr ng c a vi c s d ng l i ph n m m, nh ng có th sinh ra các v n đ nh p nh ng.
Ví d 5.7: L p Circle và project có tên là CT5_8.PRJ (g m các file DIRIVED.CPP, CT5_8.CPP). File BASE1.H 1: //BASE1.H
2: //Định nghĩa lớp Base1 3: #ifndef BASE1_H 4: #define BASE1_H 5: 6: class Base1 7: { 8: protected:
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 117 9: int Value; 10: public: 11: Base1(int X) 12: { 13: Value = X; 14: } 15: int GetData() const 16: { 17: return Value; 18: } 19: }; 20: 21: #endif File BASE2.H 1: //BASE2.H
2: //Định nghĩa lớp Base2 3: #ifndef BASE2_H 4: #define BASE2_H 5: 6: class Base2 7: { 8: protected: 9: char Letter; 10: public: 11: Base2(char C) 12: { 13: Letter = C; 14: } 15: char GetData() const 16: { 17: return Letter; 18: } 19: }; 20: 21: #endif File DERIVED.H 1: //DERIVED.H
2: //Định nghĩa lớp Derived mà kế thừa từ nhi u lớp cơ sở (Base1 & Base2) 3: #ifndef DERIVED_H 4: #define DERIVED_H 5: 6: #include "base1.h" 7: #include "base2.h" 8:
9: class Derived : public Base1, public Base2 10: { 11: private: 12: float Real; 13: public:
14: Derived(int, char, float); 15: float GetReal() const;
16: friend ostream & operator <<(ostream &Output, const Derived &D); 17: }; 18: 19: #endif
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 118 File DERIVED.CPP 1: //DERIVED.H
2: //Định nghĩa lớp Derived kế thừa từ nhi u lớp cơ sở (Base1 & Base2) 3: #ifndef DERIVED_H 4: #define DERIVED_H 5: 6: #include "base1.h" 7: #include "base2.h" 8:
9: class Derived : public Base1, public Base2 10: { 11: private: 12: float Real; 13: public:
14: Derived(int, char, float); 15: float GetReal() const;
16: friend ostream & operator <<(ostream &Output, const Derived &D); 17: }; 18: 19: #endif File CT5_8.CPP 1: //CT5_8.CPP 2: //Chương trình 5.8 3: #include 4: #include "base1.h" 5: #include "base2.h" 6: #include "derived.h" 7: 8: int main() 9: { 10: Base1 B1(10), *Base1Ptr; 11: Base2 B2('Z'), *Base2Ptr; 12: Derived D(7, 'A', 3.5);
13: cout << "Object B1 contains integer "
14: << B1.GetData() << endl
15: << "Object B2 contains character "
16: << B2.GetData() << endl
17: << "Object D contains:" << endl << D << endl << endl;
18: cout << "Data members of Derived can be"
19: << " accessed individually:" << endl
20: << " Integer: " << D.Base1::GetData() << endl
21: << " Character: " << D.Base2::GetData() << endl
22: << "Real number: " << D.GetReal() << endl << endl;
23: cout << "Derived can be treated as an "
24: << "object of either base class:" << endl; 25: Base1Ptr = &D;
26: cout << "Base1Ptr->GetData() yields "
27: << Base1Ptr->GetData() << endl ; 28: Base2Ptr = &D;
29: cout << "Base2Ptr->GetData() yields "
30: << Base2Ptr->GetData() << endl; 31: return 0; 32: }
Chúng ta ch y ví d 5.8, k t qu hình 5.13
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 119
Hình 5.13: K t qu c a ví d 5.8
Vi c k th a nhi u l p c s t o ra m t lo t các đi m nh p nh ng trong các ch ng trình C++. Ch ng h n, trong các ch
ng trình c a ví d 5.8, n u thực hi n l nh: D.GetData();
thì trình biên d ch (Borland C++ 3.1) s báo l i:
Member is ambiguous: ‘Base1::GetData’ and ‘Base1::GetData’
B i vì l p Derived k th a hai hàm khác nhau có cùng tên là GetData() t hai l p c s c a nó.
Base1::GetData() là hàm thành viên public c a l p c s public, và nó tr thành m t hàm thành viên public
c a Derived. Base2::GetData() là hàm thành viên public c a l p c s public, và nó tr thành m t hàm
thành viên public c a Derived. Do đó trình biên d ch không th xác đ nh hàm thành viên GetData() c a l p
c s nào đ g i thực hi n. Vì v y, chúng ta ph i s d ng tên l p c s và toán t đ nh ph m vi đ xác đ nh
hàm thành viên c a l p c s lúc g i hàm GetData().
Cú pháp c a m t l p k th a nhi u l p c s :
class <drived_class_name> : <type_of_inheritance> <base_class_name1> ,
<type_of_inheritance> <base_class_name2>, … { ……………….. };
Trình tự thực hi n constructor trong đa k th a: constructor l p c s xu t hi n tr c s thực hi n tr c
và cu i cùng m i t i constructor l p d n xu t. Đ i v i destructor có trình tự thực hi n theo th tự ng c l i. IV. CÁC
L P C S O (VIRTUAL BASE CLASSES)
Chúng ta không th khai báo hai l n cùng m t l p trong danh sách c a các l p c s cho m t l p d n
xu t. Tuy nhiên v n có th có tr ng h p cùng m t l p c s đ
c đ c p nhi u h n m t l n trong các l p t
tiên c a m t l p d n xu t. Đi u này phát sinh l i vì không có cách nào đ phân bi t hai l p c s g c. Ví d 5.9: 1: //Chương trình 5.9 2: #include 3: class A 4: { 5: public: 6: int X1;
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 120 7: }; 8: 9: class B : public A 10: { 11: public: 12: float X2; 13: }; 14: 15: class C : public A 16: { 17: public: 18: double X3; 19: }; 20:
21: class D : public B,public C 22: { 23: public: 24: char X4; 25: }; 26: 27: int main() 28: { 29: D Obj; 30: Obj.X2=3.14159F; 31: Obj.X1=0; //Nh p nhằng 32: Obj.X4='a'; 33: Obj.X3=1.5;
34: cout<<"X1="<35: cout<<"X2="<36: cout<<"X3="<37: cout<<"X4="<38: return 0; 39: } Khi biên d ch ch
ng trình ví d 5.9, trình biên d ch s báo l i dòng 31 và 34:
Member is ambiguous: ‘A::X1’ and ‘A::X1’ Hình 5.14
đây chúng ta th y có hai l p c s A cho l p D, và trình biên d ch không th nào nh n bi t đ c vi c truy c p X1 đ
c k th a thông qua B ho c truy c p X1 đ
c k th a thông qua C. Đ kh c ph c đi u này, chúng ta ch đ nh m t cách t
ng minh trong l p D nh sau: Obj.C::X1=0;
Tuy nhiên, đây cũng ch là gi i pháp có tính ch p vá, b i thực ch t X1 nào trong tr ng h p nào cũng
đ c. Gi i pháp cho v n đ này là khai báo A nh l p c s ki u virtual cho c B C. Khi đó ch ng trình ví d 5.9 đ c vi t l i nh sau:
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 121 Ví d 5.10: #include class A { public: int X1; }; class B : virtual public A { public: float X2; }; class C : virtual public A { public: double X3; }; class D : public B,public C { public: char X4; }; int main() { D Obj; Obj.X2=3.14159F; Obj.X1=0; //OK Obj.X4='a'; Obj.X3=1.5; cout<<"X1="<//OK
cout<<"X2="< cout<<"X3="< cout<<"X4="< return 0; }
Chúng ta ch y ví d 5.10, k t qu hình 5.15
Hình 5.15: K t qu c a ví d 5.10
Các l p c s ki u virtual, có cùng m t ki u l p, s đ c k t h p đ t o m t l p c s duy nh t
có ki u đó cho b t kỳ l p d n xu t nào k th a chúng. Hai l p c s A trên b t gi s tr thành m t l p c
s A duy nh t cho b t kỳ l p d n xu t nào t B và C. Đi u này có nghƿa là D ch có m t c s c a l p A, vì v y tránh đ c sự nh p nh ng. BÀI T P
Bài 1: Xây dựng l p Stack v i các thao tác c n thi t. T đó hãy d n xu t t l p Stack đ đ i m t s nguyên d ng sang h đ m b t kỳ.
Bài 2: Hãy xây dựng các l p c n thi t trong phân c p hình 5.2
Bài 3: Hãy xây dựng các l p c n thi t trong phân c p hình 5.3 đ tính di n tích (ho c di n
tích xung quanh) và th tích.
Bài 4: Vi t m t phân c p k th a cho các l p Quadrilateral (hình t giác), Trapezoid (hình
thang), Parallelogram (hình bình hành), Rectangle (hình ch nh t), và Square (hình vuông). Trong
đó Quadrilateral là l p c s c a phân c p.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 122 CHƯƠNG 6 TÍNH ĐA HÌNH I. D N NH P
Tính đa hình (polymorphism) là kh nĕng thi t k và cài đ t các h th ng mà có th m r ng d dàng h n. Các ch ng trình có th đ
c vi t đ x lý t ng quát – nh các đ i t ng l p c s – các đ i t ng c a
t t c các l p t n t i trong m t phân c p. Kh nĕng cho phép m t ch
ng trình sau khi đã biên d ch có th có
nhi u di n bi n x y ra là m t trong nh ng th hi n c a tính đa hình – tính muôn màu muôn vẻ – c a ch ng trình h ng đ i t ng, m t thông đi p đ c g i đi (g i đ n đ i t ng) mà không c n bi t đ i t ng nh n
thu c l p nào. Đ thực hi n đ
c tính đa hình, các nhà thi t k C++ cho chúng ta dùng c ch k t n i đ ng
(dynamic binding) thay cho c ch k t n i tƿnh (static binding) ngay khi ch ng trình biên d ch đ c dùng
trong các ngôn ng c đi n nh C, Pascal, … II. PH
NG TH C O (VIRTUAL FUNCTION)
Khi xây dựng các l p c a m t ch ng trình h ng đ i t
ng đ t o nên m t c u trúc phân c p ho c cây ph h , ng
i l p trình ph i chu n b các hành vi giao ti p chung c a các l p đó. Hành vi giao ti p chung s
đ c dùng đ th hi n cùng m t hành vi, nh ng có các hành đ ng khác nhau, đó chính là ph ng th c o.
Đây là m t ph ng th c t n t i đ có hi u lực nh ng không có thực trong l p c s , còn trong các l p d n xu t. Nh v y ph ng th c o ch đ
c xây dựng khi có m t h th ng cây ph h . Ph ng th c này s đ c
g i thực hi n t thực th c a l p d n xu t nh ng mô t v chúng trong l p c s . Chúng ta khai báo ph
ng th c o b ng thêm t khóa virtual phía tr c. Khi đó các ph ng th c có cùng tên v i ph
ng th c này trong các l p d n xu t cũng là ph ng th c o. Ví d 6.1: 1: //Chương trình 6.1 2: #include 3: 4: class Base 5: { 6: public: 7: virtual void Display() 8: {
9: cout<<"class Base"<10: } 11: }; 12:
13: class Derived : public Base 14: { 15: public: 16: virtual void Display() 17: {
18: cout<<"class Derived"<19: } 20: }; 21: 21: void Show(Base *B) 22: {
23: B->Display(); //Con trỏ B chỉ đến phương thức Display() nào (của lớp Base
24 //hoặc lớp Derived) tùy vào lúc chạy chương trình. 25: } 26: int main() 27: { 28: Base *B=new Base; 29: Derived *D=new Derived;
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 123
30: B->Display(); //Base::Display()
31: D->Display(); //Derived::Display()
32: Show(B); //Base::Display()
33: Show(D); //Derived::Display() 34: return 0; 35: }
Chúng ta ch y ví d 6.1, k t qu hình 6.1
Hình 6.1: K t qu c a ví d 6.1
Trong ví d 6.1, l p c s Base có ph ng th c Display() đ c khai báo là ph ng th c o. Ph ng
th c này trong l p d n xu t Derived đ
c đ nh nghƿa l i nh ng cũng là m t ph ng th c o. Th t ra, không
ra không có khai báo virtual cho ph
ng th c Display() c a l p Derived cũng ch ng sao, trình biên d ch v n hi u đó là ph
ng th c o. Tuy nhiên, khai báo virtual rõ ràng các l p d n xu t làm cho ch ng trình
trong sáng, d hi u h n. Hai dòng 30 và 31, chúng ta bi t ch c ph
ng th c Display() c a l p nào đ c g i
(c a l p Base ho c l p Derived). Nh ng hai dòng 32 và 33, n u không có c ch k t n i đ ng, chúng ta đoán
r ng vi c g i hàm Show() s luôn luôn kéo theo ph
ng th c Base::Display(). Qu v y, b đi khai báo virtual cho ph
ng th c Base::Display(), khi đó dòng l nh: Show(D);
g i đ n Base::Display() vì đ i t
ng l p d n xu t cũng là đ i t
ng l p c s (nghƿa là tdb tự đ ng chuy n đ i ki u: đ i t
ng D ki u Derived chuy n thành ki u Base.
Nh khai báo virtual cho ph
ng th c Base::Display() nên s không thực hi n g i ph ng th c
Base::Display() m t cách c ng nh c trong hàm Show() mà chu n b m t c ch m m dẻo cho vi c g i ph
ng th c Display() tùy thu c vào sự xác đ nh ki u c a tham s vào lúc ch y ch ng trình.
C ch đó ra sao? Khi nh n th y có khai báo virtual trong l p c s , trình biên d ch s thêm vào m i
đ i t ng c a l p c s và các l p d n xu t c a nó m t con tr ch đ n b ng ph ng th c o (virtual
function table). Con tr đó có tên là vptr (virtual pointer). B ng ph
ng th c o là n i ch a các con tr ch
đ n đo n ch ng trình đã biên d ch ng v i các ph ng th c o. M i l p có m t b ng ph ng th c o. Trình biên d ch ch l p b ng ph
ng th c o khi b t đ u có vi c t o đ i t ng c a l p. Đ n khi ch ng trình ch y, ph ng th c o c a đ i t ng m i đ
c n i k t và thi hành thông qua con tr vptr.
Trong ví d 6.1, l nh g i hàm: Show(D);
Đ i t ng D thu c l p Derived tuy b chuy n đ i ki u thành m t đ i t ng thu c l p Base nh ng nó
không hoàn toàn gi ng m t đ i t
ng c a Base chính c ng nh B. N u nh con tr vptr trong B ch đ n v trí trên b ng ph ng th c o ng v i ph
ng th c Base::Display(), thì con tr vptr trong D v n còn ch đ n ph
ng th c Derived::Display() cho dù D b chuy n ki u thành Base. Đó là lý do t i sao l nh: Show(D); g i đ n ph
ng th c Derived::Display().
Các đặc trưng của phương thức ảo: Ph
ng th c o không th là các hàm thành viên tƿnh. M t ph ng th c o có th đ
c khai báo là friend trong m t l p khác nh ng các hàm friend c a l p thì không th là ph ng th c o.
Không c n thi t ph i ghi rõ t khóa virtual khi đ nh nghƿa m t ph
ng th c o trong l p d n xu t (đ cũng ch ng nh h ng gì).
Đ sự k t n i đ ng đ c thực hi n thích h p cho t ng l p d c theo cây ph h , m t khi ph ng th c nào đó đã đ
c xác đ nh là o, t l p c s đ n các l p d n xu t đ u ph i đ nh nghƿa th ng nh t v tên, ki u
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 124
tr v và danh sách các tham s . N u đ i v i ph
ng th c o l p d n xu t, chúng ta l i s su t đ nh nghƿa
các tham s khác đi m t chút thì trình biên d ch s xem đó là ph
ng th c khác. Đây chính là đi u ki n đ k t n i đ ng. Ví d 6.2: 2: #include 3: 4: class Base 5: { 6: public:
7: virtual void Print(int A,int B); 8: }; 9:
10: class Derived : public Base 11: { 12: public:
13: virtual void Print(int A,double D); 14: }; 15:
16: void Base::Print(int A,int B) 17: { 18: cout<<"A="<19: } 20:
21: void Derived::Print(int A,double D) 22: { 23: cout<<"A="<24: } 25: 26: void Show(Base *B) 27: { 28: B->Print(3,5); 29: } 30: 31: int main() 32: { 33: Base *B=new Base; 34: Derived *D=new Derived; 35: Show(B); //Base::Print() 36: Show(D); //Base::Print() 37: return 0; 38: }
Chúng ta ch y ví d 6.2, k t qu hình 6.2
Hình 6.2: K t qu c a ví d 6.2
Trong ví d 6.2, trong l p c s Base và l p d n xu t Derived đ u có ph
ng th c o Print(). Nh ng quan sát k chúng ta, ph
ng th c Print() trong l p Derived có tham s th hai khác ki u v i ph ng th c
Print() trong l p Base. Vì th , chúng ta không th ch đ i l nh dòng 36 s g i đ n ph ng th c
Derived::Print(int,double). Ph
ng th c Derived::Print(int,double) n m ngoài đ ng dây ph ng th c o
nên hàm Show() ch luôn g i đ n ph
ng th c Derived::Print(int,int) mà thôi. Do có khai báo virtual đ i v i ph
ng th c Derived::Print(int,double), chúng ta có th nói ph
ng th c này s m đ u cho m t đ ng dây ph
ng th c o Print(int,double) m i n u sau l p Derived còn có các l p d n xu t c a nó.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 125 III. L P TR U T NG (ABSTRACT CLASS) Trong quá trình thi t k ch ng trình theo h ng đ i t
ng, đ t o nên m t h th ng ph h mang tính k th a cao, ng i l p trình ph i đoán tr
c sự phát tri n c a c u trúc, t đó ch n lựa nh ng thành viên phù
h p cho các l p trên cùng. Rõ ràng đây là m t công vi c vô cùng khó khĕn. Đ tránh tình tr ng ng i l p trình xây dựng các đ i t
ng lãng phí b nh , ngôn ng C++ cho phép chúng ta thi t k các l p có các không ph
ng th c o không làm gì c , và cũng không th t o ra đ i t
ng thu c l p đó. Nh ng l p nh v y g i là l p tr u t ng.
Trong c u trúc trên hình 6.3, không ph i l p nào cũng thực sự c n đ n ph
ng th c Print(), nh ng nó có
m t kh p n i đ t o ra b m t chung cho m i l p trong c u trúc cây. Ph
ng th c c a l p trên cùng nh A::Print() th ng là ph ng th c o đ có đ c tính đa hình. Hình 6.3 Nh đó, v i hàm sau: void Show(A* a) { a->Print(); } chúng ta có th truy n đ i t
ng đ ki u cho nó (A, B, C, D ho c E) mà v n g i đ n đúng phu ng th c
Print() phù h p dù ki u c a đ i t
ng lúc biên d ch v n còn ch a bi t. V i vai trò "lót đ ng" nh v y, ph
ng th c A::Print() có th ch ng có n i dung gì c class A { public: virtual void Print() { } }; Khi đó ng i ta g i ph
ng th c A::Print() là ph
ng th c o r ng (null virtual function), nó ch ng làm
gì h t. Tuy nhiên l p A v n là m t l p bình th
ng, chúng ta có th t o ra m t đ i t ng thu c nó, có th truy c p t i ph
ng th c A::Print(). Đ tránh trình tr ng vô tình t o ra đ i t ng thu c l p này, ng i ta th ng xây dựng l p tr u t
ng, trình biên d ch cho phép t o ra l p có các ph ng th c thu n o (pure virtual function) nh sau: class A { public: virtual void Print() = 0; };
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 126 Ph
ng th c o Print() bây gi là ph ng th c thu n o – ph ng th c có tên đ c gán b i giá tr zero. L p A ch a ph ng th c thu n o đ c g i là l p tr u t ng. Ví d 6.3: 1: //Chương trình 6.3 2: #include 3: 4: class A 5: { 6: public:
7: virtual void Print()=0; //Phương thức thuần ảo 8: }; 9: 10: class B : public A 11: { 12: public: 13: virtual void Print() 14: {
15: cout<<"Class B"<16: } 17: }; 18: 19: class C : public B 20: { 21: public: 22: virtual void Print() 23: {
24: cout<<"Class C"<25: } 26: }; 27: 28: void Show(A *a) 29: { 30: a->Print(); 31: } 32: 33: int main() 34: { 35: B *b=new B; 36: C *c=new C; 37: Show(b); //B::Print() 38: Show(c); //C::Print() 39: return 0; 40: }
Chúng ta ch y ví d 6.3, k t qu hình 6.4
Hình 6.4: K t qu c a ví d 6.3 L p A đ
c t o ra đ làm c s cho vi c hình thành các l p con cháu (B C). Nh có Ph ng th c o
Print() t l p A cho t i l p C, tính đa hình đ c th hi n. L u ý:
Chúng ta không th t o ra m t đ i t ng c a l p tr u t
ng, nh ng hoàn toàn có th t o ra m t con
tr tr đ n l p này (vì con tr không ph i là đ i t
ng thu c l p) ho c là m t tham chi u.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 127
N u trong l p k th a t l p tr u t
ng chúng ta không đ nh nghƿa ph ng th c thu n o, do tính k th a nó s bao hàm ph
ng th c thu n o c a l p c s , nên l p d n xu t này s tr thành l p tr u t ng. Theo đ nh nghƿa l p tr u t
ng, n u trong l p d n xu t (t l p c s tr u t ng) chúng ta đ nh nghƿa thêm m t ph
ng th c thu n o khác, l p này cũng s tr thành l p tr u t ng.
IV. CÁC THÀNH VIÊN O C A M T L P IV.1. Toán t o
Toán t thực ch t cũng là m t hàm nên chúng ta có th t o ra các toán t o trong m t l p. Tuy nhiên do
đa nĕng hóa khi t o m t toán t c n chú ý đ n các ki u c a các toán h ng ph i s d ng ki u c a l p c s g c có toán t o.
Ví d 6.4: Đa nĕng hóa toán t v i hàm toán t là ph ng th c o.
1: //Chương trình 6.4: Toán tử ảo 2: #include 3: 4: class A 5: { 6: protected: 7: int X1; 8: public: 9: A(int I) 10: { 11: X1=I; 12: }
13: virtual A& operator + (A& T);
14: virtual A& operator = (A& T); 15: virtual int GetA() 16: { 17: return X1; 18: } 19: virtual int GetB() 20: { 21: return 0; 22: } 23: virtual int GetC() 24: { 25: return 0; 26: } 27: void Print(char *St) 28: { 29: cout<30: } 31: }; 32: 33: class B : public A 34: { 35: protected: 36: int X2; 37: public: 38: B(int I,int J):A(I) 39: { 40: X2=J; 41: }
42: virtual A& operator + (A& T);
43: virtual A& operator = (A& T); 44: virtual int GetB()
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 128 45: { 46: return X2; 47: } 48: void Print(char *St) 49: { 50: cout<51: } 52: }; 53: 54: class C : public B 55: { 56: protected: 57: int X3; 58: public:
59: C(int I,int J,int K):B(I,J) 60: { 61: X3=K; 62: }
63: virtual A& operator + (A& T);
64: virtual A& operator = (A& T); 65: virtual int GetC() 66: { 67: return X3; 68: } 69: void Print(char *St) 70: { 71: cout<72: } 73: }; 74:
75: A& A::operator + (A& T) 76: { 77: X1+=T.GetA(); 78: return *this; 79: } 80:
81: A& A::operator = (A& T) 82: { 83: X1=T.GetA(); 84: return *this; 85: } 86:
87: A& B::operator + (A& T) 88: { 89: X1+=T.GetA(); 90: X2+=T.GetB(); 91: return *this; 92: } 93:
94: A& B::operator = (A& T) 95: { 96: X1=T.GetA(); 97: X2=T.GetB(); 98: return *this; 99: } 100:
101:A& C::operator + (A& T) 102: {
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 129 103: X1+=T.GetA(); 104: X2+=T.GetB(); 105: X3+=T.GetC(); 106: return *this; 107 } 108:
109: A& C::operator = (A& T) 110: { 111: X1=T.GetA(); 112: X2=T.GetB(); 113: X3=T.GetC(); 114: return *this; 115: } 116:
117: void AddObject(A& T1,A& T2) 118: { 119: T1=T1+T2; 120: } 121: 122: int main() 123: { 124: A a(10); 125: B b(10,20); 126: C c(10,20,30); 127: a.Print("a"); 128: b.Print("b"); 129: c.Print("c"); 130: AddObject(a,b); 131: a.Print("a"); 132: AddObject(b,c); 133: b.Print("b"); 134: AddObject(c,a); 135: c.Print("c"); 136: a=b+c; 137: a.Print("a"); 138: c=c+a; 139: c.Print("c"); 140: return 0; 141: }
Chúng ta ch y ví d 6.4, k t qu hình 6.5
Hình 6.5: K t qu c a ví d 6.4
IV.2. Có constructor và destructor o hay không? Khi m t đ i t ng thu c l p có ph
ng th c o, đ thực hi n c ch k t n i đ ng, trình biên d ch s t o
thêm m t con tr vptr nh m t thành viên c a l p, con tr này có nhi m v qu n lý đ a ch c a ph ng th c o. M t l p ch có m t b ng ph
ng th c o, trong khi đó có th có nhi u đ i t ng thu c l p, nên khi m t
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 130
đ i t ng khác thu c cùng l p t o ra thì con tr vptr đã còn t i. Chính vì v y b ng ph ng th c o ph i đ c t o ra tr
c khi g i thực hi n constructor, nên constructor không th là ph ng th c o. Ng c l i do m t l p ch có m t b ng ph ng th c o nên khi m t đ i t ng thu c l p b h y b , b ng ph ng th c o v n
còn đó, và con tr vptr v n còn đó. H n n a, destructor đ c g i thực hi n tr c khi vùng nh dành cho đ i t
ng b thu h i, do đó destructor có th là ph
ng th c o. Tuy nhiên, constructor c a m t l p có th g i ph
ng th c o khác. Đi u này hoàn toàn không có gì mâu thu n v i c ch k t n i đ ng. Ví d 6.5:
1: //Chương trình 6.5: Destructor ảo 2: #include 3: 4: class Base 5: { 6: public: 7: virtual ~Base() 8: {
9: cout<<"~Base"<10: } 11: }; 12: 13: class Derived:public Base 14: { 15: public: 16: virtual ~Derived() 17: {
18: cout<<"~Derived"<18: } 19: }; 20: 21: int main() 22: { 23: Base *B; 24: B = new Derived; 25: delete B; 26: return 0; 27: }
Chúng ta ch y ví d 6.5, k t qu hình 6.6
Hình 6.6: K t qu c a ví d 6.5 N u destructor không là ph
ng th c o thì khi gi i phóng đ i t
ng B ch có destructor c a l p c s
đ c g i mà thôi nh ng khi destructor là ph ng th c o thì khi gi i phóng đ i t ng B ( dòng 25) destructor c a l p d n xu t đ
c g i thực hi n r i đ n destructor c a l p c s .
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 131 BÀI T P
Bài 1: Hãy xây dựng các l p c n thi t trong phân c p hình 5.3 đ tính di n tích (ho c di n tích xung
quanh) và th tích trong đó l p Shape là l p c s tr u t ng.
Bài 2: Hãy s a đ i h th ng l ng c a ch
ng trình ví d 6.6 b ng thêm các thành viên d li u BrithData (m t đ i t
ng ki u Date) và DepartmentCode (ki u int) vào l p Employee. Gi s l ng này
đ c x lý m t l n trên m t tháng. Sau đó, ch ng trình tính b ng l ng cho m i Employee (tính đa hình), c ng thêm 100.00$ ti n th ng vào t ng s l ng c a m i ng
i n u đây là tháng mà ngày sinh c a Employee x y ra.
Bài 3: Cài đ t các l p trong cây ph h l p sau:
Trong đó các l p Person, Student và Staff là các l p tr u t
ng, các l p còn l i là các l p d n xu t thực.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 132 CHƯƠNG 7 THI T K CH NG TRÌNH THEO H NG Đ I T NG I. D N NH P Trong ch
ng này, chúng ta tìm hi u m t ít v cách thi t k ch ng trình theo h ng đ i t ng, các b
c c b n c n thi t khi b t tay vào vi t ch
ng trình trên quan đi m thi t k và th o ch ng. II. CÁC GIAI
ĐO N PHÁT TRI N H TH NG
Có nĕm giai đo n đ phát tri n h th ng ph n m m theo h ng đ i t ng:
Phân tích yêu c u (Requirement analysis) Phân tích (Analysis) Thi t k (Design) L p trình (Programming) Ki m tra (Testing) Phân tích yêu c u B ng vi c tìm hi u các tr
ng h p s d ng (use case) đ n m b t các yêu c u c a khách hàng,
c a v n đ c n gi i quy t. Qua tr
ng h p s d ng này, các nhân t bên ngoài có tham gia vào h th ng cũng đ
c mô hình hóa b ng các tác nhân. M i tr ng h p s d ng đ c mô t b ng vĕn b n,
đ c t yêu c u c a khách hàng. Phân tích
T các đ c t yêu c u trên, h th ng s b c đ u đ
c mô hình hóa b i các khái ni m l p, đ i t
ng và các c ch đ di n t ho t đ ng c a h th ng.
Trong giai đo n phân tích chúng ta ch mô t các l p trong lƿnh vực c a v n đ c n gi i quy t
ch chúng ta không đi sâu vào các chi ti t k thu t. Thi t k
Trong giai đo n thi t k , các k t qu c a quá trình phân tích đ
c m r ng thành m t gi i pháp k thu t. M t s các l p đ
c thêm vào đ cung c p c s h t ng k thu t nh l p giao di n, l p c s d li u, l p ch c nĕng, … L p trình
Đây còn g i là b c xây dựng, giai đo n này s đ c t chi ti t k t qu c a giai đo n thi t k . Các l p c a b c thi t k s đ
c chuy n thành mã ngu n theo m t ngôn ng l p trình theo h ng đ i t ng nào đó. Ki m tra
Trong giai đo n ki m tra, có b n hình th c ki m tra h th ng:
Ki m tra t ng đ n th (unit testing) đ
c dùng ki m tra các l p ho c các nhóm đ n.
Ki m tra tính tích h p (integration testing), đ
c k t h p v i các thành ph n và các l p đ
ki m tra xem chúng ho t đ ng v i nhau có đúng không.
Ki m tra h th ng (system testing) ch đ ki m tra xem h th ng có đáp ng đ c ch c nĕng mà ng i dùng yêu c u không. Ki m tra tính ch p nh n đ
c(acceptance testing), vi c ki m tra này đ c thực hi n b i khách
hàng, vi c ki m tra cũng thực hi n gi ng nh ki m tra h th ng.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 133 III. CÁCH TÌM L P L p nên đ
c tìm t ph m vi bài toán c n gi i quy t, vì v y tên c a l p cũng nên đ t tên các đ i t ng
thực mà chúng ta bi u di n. Đ tìm ra l p cho bài toán, chúng ta c n tr l i các câu h i sau:
Có thông tin nào c n l u tr hay phân tích không? N u có b t kỳ thông tin nào c n ph i l u tr ,
bi n đ i, phân tích ho c x lý thì đó chính là m t l p dự đ nh c n xây dựng.
Có h th ng bên ngoài bên ngoài hay không? H th ng ngoài có th đ c xem nh các l p mà
h th ng c a chúng ta ch a ho c t ng tác v i nó.
Có các m u thi t k , th vi n l p, thành ph n, … hay không? Các thành ph n này đã đ c xây dựng t các project tr
c đó, t các đ ng nghi p ho c các nhà s n xu t?
Có thi t b nào mà h th ng ph i đáp ng? B t c thi t b nào đ c n i v i h th ng có th chuy n thành l p dự tuy n.
Tác nhân đóng vai trò nh th nào trong h th ng? Các vai di n này nên đ c xem là l p nh ng i s d ng, khách hang, ng i đi u khi n h th ng,… IV. CÁC B
C C N THI T Đ THI T K CH NG TRÌNH
Đ thi t k m t ch ng trình theo h ng đ i t ng, chúng ta ph i tr i qua b n b c sau, t đó chúng ta xây dựng đ
c m t cây ph h mang tính k th a và các m i quan h gi a các đ i t ng: Xác đ nh các d ng đ i t
ng (l p) c a bài toán (đ nh dang các đ i t ng).
Tìm ki m các đ c tính chung (d li u chung) trong các d ng đ i t
ng này, nh ng gì chúng cùng nhau chia xẻ. Xác đ nh đ
c l p c s dựa trên c s các đ c tính chung c a các d ng đ i t ng.
T l p c s , s d ng quan h t ng quát hóa đ đ c t trong vi c đ a ra các l p d n xu t ch a các
thành ph n, nh ng đ c tính không chung còn l i c a d ng đ i t
ng. Bên c nh đó, chúng ta còn đ a ra
các l p có quan h v i các l p c s và l p d n xu t; các quan h này có th là quan h k t h p, quan h t p h p l i, quan h ph thu c. V i các b c trên chúng ta có đ
c cây ph h và quan h gi a các l p. Đ i v i h th ng ph c t p h n,
chúng ta c n ph i phân tích đ gi i quy t đ
c v n đ đ t ra theo tr t tự sau:
Phân tích m t cách c n th n v các đ i t
ng c a bài toán theo tr t tự t d i lên (bottom up).
Tìm ra nh ng gì t n t i chung gi a các đ i t
ng, nhóm các đ c tính này l i đ đ c các l p c s nh hình 7.1 Hình 7.1 Ti p t c theo h ng t d i lên, chúng ta thi t k đ c các đ i t ng phù h p nh hình 7.2
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 134 Hình 7.2
B ng cách này, chúng ta ti p t c tìm các đ c tính chung cho đ n t t cùng c a các đ i t ng. Sau đó cài đ t theo h ng đ i t
ng t trên xu ng b ng cách cài đ t l p c s chung nh t.
Ti p t c cài đ t các l p d n xu t trên c s các đ c tính chung c a t ng nhóm đ i t ng.
Cho đ n khi t t c các d ng đ i t ng c a h th ng đ c cài đ t xong đ đ c cây ph h . V. CÁC VÍ D Ví d 7.1: Tính ti n l
ng c a các nhân viên trong c quan theo các d ng khác nhau. D ng ng i lao
đ ng lãnh l ng t ngân sách Nhà n c đ c g i là cán b , công ch c (d ng biên ch ). D ng ng i lao đ ng lãnh l ng t ngân sách c a c quan đ c g i là ng
i làm h p đ ng. Nh v y h th ng chúng ta có hai đ i t ng: biên ch và h p đ ng. Hai lo i đ i t
ng này có đ c tính chung đó là viên ch c làm vi c cho c quan. T đây có th t o
nên l p c s đ qu n lý m t viên ch c (l p Nguoi) bao g m mã s , h tên và l ng.
Sau đó chúng ta xây dựng các l p còn l i k th a t l p c s trên:
L p dành cho cán b , công ch c (l p BienChe) g m các thu c tính: h s l ng, ti n ph c p ch c v . L p dành cho ng
i làm h p đ ng (l p HopDong) g m các thu c tính: ti n công lao đ ng, s
ngày làm vi c trong tháng, h s v t gi . Hình 7.3
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 135 File PERSON.H 1: //PERSON.H 2: Định nghĩa lớp Nguoi 3: #ifndef PERSON_H 4: #define PERSON_H 5: 6: #include 7: 8: #define MAX_TEN 50 9: #define MAX_MASO 5 10: #define MUC_CO_BAN 120000 11: 12: class Nguoi 13: { 14: protected: 15: char HoTen[MAX_TEN]; 16: char MaSo[MAX_MASO]; 17: float Luong; 18: public: 19: Nguoi();
20: virtual void TinhLuong()=0; 21: void Xuat() const; 22: virtual void Nhap(); 23: }; 24: 25: #endif File PERSON.CPP 1: //PERSON.CPP
2: Định nghĩa hàm thành viên cho lớp Nguoi 3: #include 4: #include 5: #include "person.h" 6: 7: Nguoi::Nguoi() 8: { 9: strcpy(HoTen,""); 10: strcpy(MaSo,""); 11: Luong=0; 12: } 13: 14: void Nguoi::Xuat() const 15: {
16: cout<<"Ma so:"<17: #9; <<",Luong:"<18: } 19: 20: void Nguoi::Nhap() 21: { 22: cout<<"Ma so:"; 23: cin>>MaSo; 24: cin.ignore(); 25: cout<<"Ho va ten:";
26: cin.getline(HoTen,MAX_TEN); 27: }
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 136 File STAFF.H 1: //STAFF.H
2 Định nghĩa lớp BienChe 3: #ifndef STAFF_H 4: #define STAFF_H 5: 5: #include "person.h" 6:
7: class BienChe: public Nguoi 8: { 9: protected: 10: float HeSoLuong; 11: float HeSoPhuCap; 12: public: 13: BienChe(); 14: virtual void TinhLuong(); 15: virtual void Nhap(); 16: }; 17: 18: #endif File STAFF.CPP 1: //STAFF.CPP
2: Định nghĩa hàm thành viên cho lớp BienChe 3: #include "staff.h" 4: 5: BienChe::BienChe() 6: { 7: HeSoLuong=HeSoPhuCap=0; 8: } 9: 10: void BienChe::Nhap() 11: { 12: Nguoi::Nhap();
13: cout<<"He so luong:"; 14: cin>>HeSoLuong;
15: cout<<"He so phu cap chu vu:"; 16: cin>>HeSoPhuCap; 17: } 18: 19: void BienChe::TinhLuong() 20: {
21: Luong=MUC_CO_BAN*(1.0+HeSoLuong+HeSoPhuCap); 22: } File CONTRACT.H 1: //CONTRACT.H
2: Định nghĩa lớp HopDong 3: #ifndef CONTRACT_H 4: #define CONTRACT_H 5: 6: #include "person.h" 7:
8: class HopDong : public Nguoi 9: { 10: protected: 11: float TienCong; 12: float NgayCong;
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 137 13: float HeSoVuotGio; 14: public: 15: HopDong(); 16: virtual void TinhLuong(); 17: virtual void Nhap(); 18: }; 19: 20: #endif File CONTRACT.CPP: 1: //CONTRACT.CPP
2: Định nghĩa hàm thành viên cho lớp HopDong 3: #include "contract.h" 4: 5: HopDong::HopDong() 6: {
7: TienCong=NgayCong=HeSoVuotGio=0; 8: } 9: 10: void HopDong::Nhap() 11: { 12: Nguoi::Nhap(); 13: cout<<"Tien cong:"; 14: cin>>TienCong; 15: cout<<"Ngay cong:"; 16: cin>>NgayCong;
17: cout<<"He so vuot gio:"; 18: cin>>HeSoVuotGio; 19: } 20: 21: void HopDong::TinhLuong() 22: {
23: Luong=TienCong*NgayCong*(1+HeSoVuotGio); 24: } File CT7_1.CPP: 1: //CT7_1.CPP 2: //Chương trình 7.1 3: #include 4: #include 5: #include "person.h" 6: #include "staff.h" 7: #include "contract.h" 8: 9: int main() 10: { 11: Nguoi *Ng[100]; 12: int N=0; 13: char Chon,Loai; 14: do 15: {
16: cout<<"Bien che hay Hop dong (B/H)? "; 17: cin>>Loai; 18: Loai=toupper(Loai); 19: if (Loai=='B') 20: Ng[N]=new BienChe; 21: else 22: Ng[N]=new HopDong;
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 138 23: Ng[N++]->Nhap();
24: cout<<"Tiep tuc (C/K)? "; 25: cin>>Chon; 26: Chon=toupper(Chon);
27: if ((N==100)||(Chon=='K')) 28: break; 29: } 30: while (1); 31: for(int I=0;I32: { 33: Ng[I]->TinhLuong(); 34: Ng[I]->Xuat(); 35: } 36: return 0; 37: }
Chúng ta ch y ví d 7.1, k t qu hình 7.4
Hình 7.4: K t qu c a ví d 7.1
Ví d 7.2: Gi s cu i nĕm h c c n trao gi i th
ng cho các sinh viên xu t s c và các gi ng viên có nhi u công trình khoa h c đ
c công b trên t p chí. Các l p trong cây ph h nh hình 7.5: l p Nguoi đ
qu n lý h s cá nhân, l p SinhVien qu n lý v sinh viên và l p GiangVien qu n lý gi ng viên. L p Nguoi: D li u h và tên. Ph ng th c ki m tra kh nĕng đ c khen th ng. Đây là ph ng th c thu n o. Ph ng th c xu t. Đây là ph ng th c thu n o. L p SinhVien: D li u đi m trung bình. Ph ng th c ki m tra kh nĕng đ c khen th ng. Ph ng th c xu t. L p GiangVien: D li u đi m trung bình. Ph ng th c ki m tra kh nĕng đ c khen th ng. Ph ng th c xu t.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 139 Hình 7.5 File PERSON.H 1: //PERSON.H 2: Định nghĩa lớp Nguoi 3: #ifndef PERSON_H 4: #define PERSON_H 5: 6: #include 7: 8: #define MAX_TEN 50 9: 10: class Nguoi 11: { 12: protected: 13: char HoTen[MAX_TEN]; 14: public: 15: Nguoi(char *HT);
16: virtual int DuocKhenThuong() const=0;
17: virtual void Xuat() const=0; 18: }; 19: 20: #endif File PERSON.CPP: 1: //PERSON.CPP
2: Định nghĩa hàm thành viên cho lớp Nguoi 3: #include 4: #include "person.h" 5: 6: Nguoi::Nguoi(char *HT) 7: { 8: strcpy(HoTen,HT); 9: } File STUDENT.H: 1: //STUDENT.H
2: Định nghĩa lớp SinhVien 3: #ifndef STUDENT_H 4: #define STUDENT_H 5:
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 140 6: #include "person.h" 7:
8: class SinhVien : public Nguoi 9: { 10: protected: 11: float DiemTB; 12: public:
13: SinhVien(char *HT,float DTB);
14: virtual int DuocKhenThuong() const;
15: virtual void Xuat() const; 16: }; 17: 18: #endif File STUDENT.CPP: 1: //STUDENT.CPP
2: Định nghĩa hàm thành viên cho lớp SinhVien 3: #include "student.h" 4:
5: SinhVien::SinhVien(char *HT,float DTB):Nguoi(HT) 6: { 7: DiemTB=DTB; 8: } 9:
10: int SinhVien::DuocKhenThuong() const 11: { 12: return DiemTB>9.0; 13: } 14:
15: void SinhVien::Xuat() const 16: {
17: cout<<"Ho va ten cua sinh vien:"<18: } File TEACHER.H: 1: //TEACHER.H
2: Định nghĩa lớp GiangVien 3: #ifndef TEACHER_H 4: #define TEACHER_H 5: 6: #include "person.h" 7:
8: class GiangVien : public Nguoi 9: { 10: protected: 11: int SoBaiBao; 12: public:
13: GiangVien(char *HT,int SBB);
14: virtual int DuocKhenThuong() const;
15: virtual void Xuat() const; 16: }; 17: 18: #endif File TEACHER.CPP: 1: //TEACHER.CPP
2: Định nghĩa hàm thành viên cho lớp GiangVien 3: #include "teacher.h" 4:
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 141
5: GiangVien::GiangVien(char *HT,int SBB):Nguoi(HT) 6: { 7: SoBaiBao=SBB; 8: } 9:
10: int GiangVien::DuocKhenThuong() const 11: { 12: return SoBaiBao>5; 13: } 14:
15: void GiangVien::Xuat() const 16: {
17: cout<<"Ho va ten cua giang vien:"<18: } File CT7_2.CPP: 1: //CT7_2.CPP 2: //Chương trình 7.2 3: #include 4: #include "person.h" 5: #include "student.h" 6: #include "teacher.h" 7: 8: int main() 9: { 10: Nguoi *Ng[100]; 11: int N=0; 12: char Chon,Loai; 13: char HoTen[MAX_TEN]; 14: do 15: { 16: cout<<"Ho va ten:";
17: cin.getline(HoTen,MAX_TEN);
18: cout<<"Sinh vien hay Giang vien(S/G)? "; 19: cin>>Loai; 20: Loai=toupper(Loai); 21: if (Loai=='S') 22: { 23: float DTB;
24: cout<<"Diem trung binh:"; 25: cin>>DTB;
26: Ng[N++]=new SinhVien(HoTen,DTB); 27: } 28: else 29: { 30: int SoBaiBao;
31: cout<<"So bai bao:"; 32: cin>>SoBaiBao;
33: Ng[N++]=new GiangVien(HoTen,SoBaiBao); 34: }
35: cout<<"Tiep tuc (C/K)? "; 36: cin>>Chon; 37: Chon=toupper(Chon); 38: cin.ignore();
39: if ((N==100)||(Chon=='K')) 40: break; 41: } 42: while (1);
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 142 43: for(int I=0;I44: { 45: Ng[I]->Xuat();
46: if (Ng[I]->DuocKhenThuong())
47: cout<<". Nguoi nay duoc khen thuong"; 48: cout<49: } 50: return 0; 51: }
Chúng ta ch y ví d 7.2, k t qu hình 7.6
Hình 7.6: K t qu c a ví d 7.2
Ví d 7.3: Gi s c n ph i t o các hình: hình tròn và hình ch nh t đ
c tô theo hai màu red và blue.
Xây dựng m t cây ph h đ qu n lý các hình này. Tr
c h t chúng ta c n có l p c s Shape đ l u tr thông tin chung cho các hình, sau đó là hai l p d n
xu t Rectangle v hình hình ch nh t và Circle v hình tròn nh hình 7.7 L p Shape: T a đ tâm. Màu đ ng biên. Màu tô. Ph ng th c thi t l p tô màu. Ph ng th c v hình. Đây là ph ng th c thu n o. L p Rectangle: Chi u dài và chi u r ng. Ph ng th c v hình. L p Circle: Bán kính. Ph ng th c v hình.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 143 CHƯƠNG 8 CÁC D NG NH P/XU T I. D N NH P
Các th vi n chu n C++ cung c p m t t p h p các kh nĕng nh p/xu t r ng l n. Trong ch ng này
chúng ta tìm hi u m t ph m vi c a các kh nĕng đ đ ph n l n các thao tác nh p xu t.
Ph n l n các đ c tính nh p xu t mô t đây theo h ng đ i t
ng. Ki u này c a nh p/xu t thi hành
vi c s d ng các đ c tính khác c a C++ nh các tham chi u, đa nĕng hóa hàm và đa nĕng hóa toán t .
Nh chúng ta s th y, C++ s d ng nh p/xu t ki u an toàn (type safe). M i thao tác nh p/xu t đ c
thực hi n m t cách tự đ ng theo l i nh y c m v ki u d li u. M i thao tác nh p xu t có đ c đ nh nghƿa
thích h p đ x lý m t ki u d li u c th thì hàm đó đ
c g i đ x lý ki u d li u đó. N u không có đ i
sánh gi a ki u c a d li u hi n t i và m t hàm cho vi c x lý ki u d li u đó, m t ch d n l i biên d ch đ c
thi t l p. Vì th d li u không thích h p không th "lách" qua h th ng. Các ng
i dùng có th ch đ nh nh p/xu t c a các ki u d li u do ng
i dùng đ nh nghƿa cũng nh các
ki u d li u chu n. Tính m r ng này là m t trong các đ c tính quan tr ng c a C++. II. CÁC DÒNG(STREAMS)
Nh p/xu t C++ x y ra trong các dòng c a các byte. M t dòng đ n gi n là m t dãy tu n tự các byte.
Trong các thao tác nh p, các byte ch y t thi t b (ch ng h n: m t bàn phím, m t đƿa, m t k t n i m ng)
t i b nh chính. Trong các thao tác xu t, các byte ch y t b nh chính t i m t thi t b (ch ng h n: m t
màn hình, m t máy in, m t đƿa, m t k t n i m ng).
ùng d ng liên k t v i các byte. Các byte có th bi u di n các ký tự ASCII, bên trong đ nh d ng d li u
thô, các nh đ h a, ti ng nói s , hình nh s ho c b t c lo i thông tin m t ng d ng có th đòi h i.
Công vi c c a các c ch h th ng nh p/xu t là di chuy n các byte t các thi t b t i b nh và ng c
l i theo l i ch c và đáng tin c y. Nh th các di chuy n th
ng bao g m sự di chuy n c h c nh sự quay
c a m t đƿa ho c m t bĕng t , ho c nh n phím t i m t bàn phím. Th i gian các di chuy n này thông th ng
kh ng l so v i th i gian b x lý thao tác dự li u n i t i. Vì th , các thao tác nh p/xu t đòi h i có k ho ch
c n th n và đi u ch nh đ b o đ m sự thi hành t i đa.
C++ cung c p c hai kh nĕng nh p/xu t "m c th p" (low-level) và "m c cao" (high-level). Các kh
nĕng nh p/xu t m c th p (nghƿa là nh p/xu t không đ nh d ng) ch đ nh c th s byte nào đó ph i đ c di
chuy n hoàn toàn t thi t b t i b nh ho c t b nh t i thi t b . Trong các di chuy n nh th , byte riêng r
là m c c n quan tâm. Vì th các kh nĕng m c th p cung c p t c đ cao, các di chuy n dung l ng cao,
nh ng các kh nĕng này không ph i là ti n l i l m cho l p trình viên.
Các l p trình viên u thích quan đi m nh p/xu t m c cao, nghƿa là nh p/xu t có đ nh d ng, trong đó các byte đ
c nhóm thành các đ n v có ý nghƿa nh các s nguyên, các s ch m đ ng, các ký tự, các chu i và các ki u do ng i dùng đ nh nghƿa.
II.1. Các file header c a th vi n iostream
Th vi n iostream c a C++ cung c p hàng trĕm kh nĕng c a nh p/xu t. M t vài t p tin header ch a
các ph n c a giao di n th vi n. Ph n l n ch ng trình C++ th
ng include t p tin header mà ch a các thông tin c b n
đòi h i t t c các thao tác dòng nh p/xu t. T p tin header ch a các đ i t ng cin, cout, cerr clog mà t
ng ng v i dòng nh p chu n, dòng xu t chu n, dòng l i chu n không vùng đ m và dòng l i
chu n vùng đ m. C hai kh nĕng nh p/xu t đ nh d ng và không đ nh d ng đ c cung c p.
Header ch a thông tin h u ích cho vi c thực hi n nh p/xu t đ nh d ng v i tên g i là các
b x lý dòng bi u hi n b ng tham s (parameterized stream manipulators).
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 144
Header ch a các thông tin quan tr ng cho các thao tác x lý file do ng i dùng ki m soát.
Header ch a các thông tin quan tr ng cho vi c thực hi n các đ nh d ng trong b nh .
Đi u này t ng tự x lý file, nh ng các thao tác nh p/xu t t i và t m ng các ký tự h n là file.
Header ch a các thông tin quan tr ng cho các ch
ng trình tr n các ki u nh p/xu t c a C và C++. Các ch
ng trình m i ph i tránh ki u nh p/xu t C, nh ng c n thì hi u ch nh các ch ng trình C, ho c ti n tri n ch ng trình C thành C++. II.2. Các l p và các đ i t ng c a dòng nh p/xu t
Th vi n iostream ch a nhi u l p đ x lý m t sự đa d ng r ng c a các thao tác nh p/xu t. L p
istream h tr các thao tác dòng nh p. L p ostream h tr các thao tác dòng xu t. L p iostream h tr c
hai thao tác dòng nh p và dòng xu t. L p istream và l p ostream đ u k th a đ n t l p c s ios. L p iostream đ
c k th a thông qua đa k th a t hai l p istream ostream.
Hình 8.1: M t ph n c a phân c p l p dòng nh p/xu t
Đa nĕng hóa toán t cung c p m t ký hi u thích h p cho vi c thực hi n nh p/xu t. Toán t d ch chuy n trái (<<) đ
c đa nĕng hóa đ đ nh rõ dòng xu t và đ
c tham chi u nh là toán t chèn dòng. Toán t d ch
chuy n ph i (>>) đ
c đa nĕng hóa đ đ nh rõ dòng nh p và đ
c tham chi u nh là toán t trích dòng. Các toán t này đ c s d ng v i các đ i t
ng dòng chu n cin, cout, cerr clog, và bình th ng v i các đ i t ng dòng do ng i dùng đ nh nghƿa. cin là m t đ i t
ng c a l p istream và đ
c nói là "b ràng bu c t i" (ho c k t n i t i) thi t b nh p chu n, thông th
ng là bàn phím. Toán t trích dòng đ
c s d ng l nh sau t o ra m t giá tr cho bi n nguyên X đ
c nh p t cin t i b nh : int X; cin >> X; cout là m t đ i t
ng c a l p ostream và đ
c nói là "b ràng bu c t i" thi t b xu t chu n, thông th
ng là màn hình. Toán t chèn dòng đ
c s d ng l nh sau t o ra m t giá tr cho bi n nguyên X đ c
xu t t b nh t i thi t b chu n: cout << X; cerr là m t đ i t
ng c a l p ostream và đ
c nói là "b ràng bu c t i" thi t b l i chu n. Vi c xu t
đ i t ng cerr là không vùng đ m. Đi u này có nghƿa là m i l n chèn t i cerr t o ra k t xu t c a nó xu t
hi n ngay t c thì; Đi u này thích h p cho vi c thông báo nhanh chóng ng i dùng khi có sự c . clog là m t đ i t
ng c a l p ostream và đ
c nói là "b ràng bu c t i" thi t b l i chu n. Vi c xu t
đ i t ng cerr là có vùng đ m. Đi u này có nghƿa là m i l n chèn t i cerr t o ra k t xu t c a nó đ c gi
trong vùng đ m cho đ n khi vùng đ m đ y ho c vùng đ m đ c flush.
Vi c x lý file c a C++ s d ng các l p ifstream đ thực hi n các thao tác nh p file, ofstream cho các
thao tác xu t file, và fstream cho các thao tác nh p/xu t file. L p ifstream k th a t istream, ofstream l p
k th a t ostream, và l p fstream k th a t iostream.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 145
Hình 8.2: M t ph n c a phân c p l p dòng nh p/xu t v i vi c x lý file. III. DÒNG XU T
ostream c a C++ cung c p kh nĕng đ thực hi n xu t đ nh d ng và không đ nh d ng. Các kh nĕng
xu t bao g m: xu t các ki u d li u chu n v i toán t chèn dòng; xu t các ký tự v i hàm thành viên put();
xu t không đ nh d ng v i hàm thành viên write; xu t các s nguyên d ng th p phân, bát phân và th p l c
phân; xu t các giá tr ch m đ ng v i đ chính xác khác nhau, v i d u ch m th p phân, theo ký hi u khoa h c
và theo ký hi u c đ nh; xu t d li u theo các tr
ng đ n thêm các ký tự ch đ nh; và xu t các m u tự ch
hoa theo ký hi u khoa h c và ký hi u th p l c phân.
III.1. Toán t chèn dòng Dòng xu t có th đ
c thực hi n v i toán t chèn dòng, nghƿa là toán t << đã đa nĕng hóa. Toán t <<
đã đ c đa nĕng hóa đ xu t các m c d li u c a các ki u có s n, xu t chu i, và xu t các giá tr con tr .
Ví d 8.1: Minh h a xu t chu i s d ng m t l nh chèn dòng.
1: //Chương trình 8.1:Xuất một chuỗi sử dụng chèn dòng 2: #include 3: 4: int main() 5: {
6: cout<<"Welcome to C++!\n"; 7: return 0; 8: }
Chúng ta ch y ví d 8.1, k t qu hình 8.3
Hình 8.3: K t qu c a ví d 8.1
Ví d 8.2: Minh h a xu t chu i s d ng nhi u l nh chèn dòng.
1: //Chương trình 8.2:Xuất một chuỗi sử dụng hai chèn dòng 2: #include 3: 4: int main() 5: { 6: cout<<"Welcome to"; 7: cout<<"C++!\n"; 8: return 0; 9: }
Chúng ta ch y ví d 8.2, k t qu hình 8.4
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 146
Hình 8.4: K t qu c a ví d 8.2
Hi u qu c a chu i thoát \n (newline) cũng đ t đ
c b i b x lý dòng (stream manipulator) endl (end line). Ví d 8.3:
1: //Chương trình 8.3:Sử dụng bộ xử lý dòng endl 2: #include 3: 4: int main() 5: { 6: cout<<"Welcome to"; 7: cout<<"C++!"; 8: cout<9: return 0; 10: }
Chúng ta ch y ví d 8.3, k t qu hình 8.5
Hình 8.5: K t qu c a ví d 8.3
B x lý dòng endl đ a ra m t ký tự newline, và h n n a, flush vùng đ m xu t (nghƿa là t o ra vùng
đ m xu t đ c xu t ngay l p t c k c nó ch a đ y). Vùng đ m xu t cũng có th đ c flush b ng:
cout<Ví d 8.4: Các bi u th c có th xu t
1: //Chương trình 8.4: Xuất giá trị bi u thức. 2: #include 3: 4: int main() 5: {
6: cout<<"47 plus 53 is "; 7: cout<< (47+53); 8: cout<9: return 0; 10: }
Chúng ta ch y ví d 8.4, k t qu hình 8.6
Hình 8.6: K t qu c a ví d 8.4
III.2. N i các toán t chèn dòng và trích dòng
Các toán t đã đa nĕng hóa << >> có th đ c theo d ng n i vào nhau.
Ví d 8.5: N i các toán t đã đa nĕng hóa
1: //Chương trình 8.5: Nối toán tử << đã đa năng hóa. 2: #include 3: 4: int main() 5: {
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 147
6: cout<<"47 plus 53 is "<< (47+53)<7: return 0; 8: }
Chúng ta ch y ví d 8.5, k t qu hình 8.7
Hình 8.7: K t qu c a ví d 8.5
Nhi u chèn dòng dòng 6 trong ví d 8.5 đ c thực thi n u có th vi t:
(((cout<<"47 plus 53 is ")<< (47+53))<nghƿa là << liên k t t trái qua ph i. Lo i liên k t c a các toán t chèn dòng đ c phép b i vì toán t đa
nĕng hóa << tr v m t tham chi u t i đ i t
ng toán h ng bên trái c a nó, nghƿa là cout. Vì th bi u th c
đ t trong ngo c bên cực trái:
(cout<<"47 plus 53 is ")
xu t ra m t chu i đã ch đ nh và tr v m t tham chi u t i cout. Đi u này cho phép bi u th c đ t trong ngo c gi a đ c c l ng: (cout<< (47+53))
xu t giá tr nguyên 100 và tr v m t tham chi u t i cout. Sau đó bi u th c đ t trong ngo c bên cực ph i đ c c l ng:
cout<xu t m t newline, flush cout và tr v m t tham chi u t i cout. Tr v cu i cùng này không đ c s d ng.
8.3.3 Xu t các bi n ki u char *:
Trong nh p/xu t ki u C, th t c n thi t cho l p trình viên đ cung c p thông tin ki u. C++ xác
đ nh các ki u d li u m t cách tự đ ng – m t c i ti n hay h n C. Đôi khi đi u này là m t tr ng i.
Ch ng h n, chúng ta bi t r ng m t chu i ký tự là ki u char *. M c đích c a chúng ta in giá tr c a
con tr đó, nghƿa là đ a ch b nh c a ký tự đ u tiên c a chu i đó. Nh ng toán t << đã đ c đa
nĕng hóa đ in d li u c a ki u char * nh là chu i k t thúc ký tự null. Gi i pháp là ép con tr thành ki u void *.
Ví d 8.6: In đ a ch l u trong m t bi n ki u char *
Chúng ta ch y ví d 8.6, k t qu hình 8.8
Hình 8.8: K t qu c a ví d 8.6
III.3. Xu t ký tự v i hàm thành viên put(); N i v i nhau hàm put()
Hàm thành viên put() c a l p ostream xu t m t ký tự có d ng :
ostream& put(char ch); Ch ng h n: cout.put(‘A’); G i put() có th đ c n i vào nhau nh :
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 148
cout.put(‘A’).put(‘\n’);
Hàm put() cũng có th g i v i m t bi u th c có giá tr là mã ASCII nh : cout.put(65); IV. DÒNG NH P Dòng nh p có th đ
c thực hi n v i toán t trích, nghƿa là toán t đã đa nĕng hóa >>. Bình th ng toán
t này b qua các ký t kho ng tr ng (nh các blank, tab và newline). trong dòng nh p. Toán t trích dòng
tr v zero (false) khi k t thúc file (end-of-file) đ c b t g p trên m t dòng; Ng
c l i, toán t trích dòng tr v m t tham chi u t i đ i t ng xuyên qua đó nó đ
c kéo theo. M i dòng ch a m t t p các bit tr ng thái
(state bit) s d ng đ đi u khi n tr ng thái c a dòng (nghƿa là đ nh d ng, n đ nh các tr ng thái l i,…). Trích
dòng sinh ra failbit c a dòng đ
c thi t l p n u d li u c a ki u sai đ
c nh p, và sinh ra badbit c a dòng
đ c thi t l p n u thao tác sai.
IV.1. Toán t trích dòng:
Đ đ c hai s nguyên s d ng đ i t ng cin và toán t trích dòng đã đa nĕng hóa >>. Ví d 8.7: 1: //Chương trình 8.7 2: #include 3: 4: int main() 5: { 6: int X, Y;
7: cout << "Enter two integers: "; 8: cin >> X >> Y;
9: cout << "Sum of " << X << " and " << Y << " is: "
10: << (X + Y) << endl; 11: return 0; 12: }
Chúng ta ch y ví d 8.7, k t qu hình 8.9
Hình 8.9: K t qu c a ví d 8.7
M t cách ph bi n đ nh p m t dãy các giá tr là s d ng toán t trích dòng trong vòng l p while. Toán
t trích dòng tr v false (0) khi end-of-file đ c b t g p: Ví d 8.8: 2: #include 3: 4: int main() 5: {
6: int Grade, HighestGrade = -1;
7: cout << "Enter grade (enter end-of-file to end): "; 8: while (cin >> Grade) 9: {
10: if (Grade > HighestGrade ) 11: HighestGrade = Grade;
12: cout << "Enter grade (enter end-of-file to end): "; 13: } 14: cout <15: return 0; 16: }
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 149
Chúng ta ch y ví d 8.8, k t qu hình 8.10
Hình 8.10: K t qu c a ví d 8.8
IV.2. Các hàm thành viên get() và getline()
Hàm istream::get() có các d ng sau: (1) int get();
(2) istream& get(unsigned char &ch);
(3) istream& get(signed char &ch);
(4) istream& get(unsigned char * puch, int len, char delim=’\n’);
(5) istream& get(signed char * psch, int len, char delim=’\n’);
D ng (1) trích ký tự đ n t dòng và tr v nó ho c EOF khi end-of-file trên dòng đ c b t g p.
D ng (2) và (3) trích m t ký tự đ n t dòng và l u tr nó vào ch.
D ng (4) và (5) trích các ký tự t dòng cho đ n khi ho c delim đ
c tìm th y, gi i h n len đ t đ n, ho c end-of-file đ c b t g p. Các ký tự đ
c l u trong con tr ch đ n m ng ký tự puch ho c psch.
Ví d 8.9: S d ng hàm get() d ng (1) 1: //Chương trình 8.9 2: #include 3: int main() 4: { 5: int Ch;
6: cout << "Before input, cin.eof() is " << cin.eof() << endl
7: << "Enter a sentence followed by end-of-file:" << endl;
8: while ( ( Ch = cin.get() ) != EOF) 9: cout.put(Ch);
10: cout << endl << "EOF in this system is: " << Ch << endl;
11: cout << "After input, cin.eof() is " << cin.eof() << endl; 12: return 0; 13: }
Chúng ta ch y ví d 8.9, k t qu hình 8.11
Hình 8.11: K t qu c a ví d 8.9
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 150
Trong ví d 8.9 trên, chúng ta có s d ng hàm ios::eof() có d ng sau: int eof();
Hàm tr v giá tri khác zero n u end-of-file b t g p.
Ví d 8.10: S d ng hàm get() d ng (5) 1: //Chương trình 8.10 2: #include 3: 4: const int SIZE = 80; 5: 6: int main() 7: {
8: char Buffer1[SIZE], Buffer2[SIZE];
9: cout << "Enter a sentence:" << endl; 10: cin >> Buffer1;
11: cout << endl << "The string read with cin was:" << endl
12: << Buffer1 << endl << endl; 13: cin.get(Buffer2, SIZE);
14: cout << "The string read with cin.get was:" << endl
15: << Buffer2 << endl; 16: return 0; 17: }
Chúng ta ch y ví d 8.10, k t qu hình 8.12
Hình 8.12: K t qu c a ví d 8.10
Hàm istream::getline() có các d ng sau:
(1) istream& getline(unsigned char * puch, int len, char delim=’\n’);
(2) istream& getline(signed char * psch, int len, char delim=’\n’);
Ví d 8.11: S d ng hàm getline() 1: //Chương trình 8.11 2: #include 3: 4: const SIZE = 80; 5: 6: int main() 7: { 8: char Buffer[SIZE];
9: cout << "Enter a sentence:" << endl;
10: cin.getline(Buffer, SIZE);
11: cout << endl << "The sentence entered is:" << endl
12: << Buffer << endl; 13: return 0; 14: }
Chúng ta ch y ví d 8.11, k t qu hình 8.13
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 151
Hình 8.13: K t qu c a ví d 8.11
IV.3. Các hàm thành viên khác c a istream Hàm ignore(): istream& ignore(int
nCount = 1, int delim = EOF);
Trích và lo i b lên đ n nCount ký tự. Vi c trích d ng n u delim đ
c b t g p ho c n u end-of-file b t g p. Hàm putback(): istream& putback(char ch);
Đ t m t ký tự ng c l i dòng nh p. Hàm peek(): int peek();
Hàm tr v ký tự k ti p mà không trích nó t dòng.
IV.4. Nh p/xu t ki u an toàn
C++ cung c p nh p/xu t ki u an toàn (type-safe). Các toán t << >> đ c đa nĕng hóa đ nh n các
m c d li u c a ki u c th . N u d li u b t ng đ
c x lý, các c hi u l i khác nhau đ c thi t l p mà ng
i dùng có th ki m tra đ xác đ nh n u m t thao tác nh p/xu t thành công ho c th t b i. Ph n sau chúng ta s kh o sát k h n.
V. NH P/XU T KHÔNG Đ NH D NG V I READ(),GCOUNT() VÀ WRITE() Nh p/xu t không đ nh d ng đ
c thực hi n v i các hàm thành viên istream::read() ostream::write(). Hàm istream::read():
istream& read(unsigned char* puch, int nCount);
istream& read(signed char* psch, int nCount);
Trích các byte t dòng cho đ n khi gi i h n nCount đ t đ n ho c cho đ n khi end- of-file đ t đ n. Hàm
này có ích cho dòng nh p nh phân. Hàm ostream::write():
ostream& write(const unsigned char* puch, int nCount);
ostream& write(const signed char* psch, int nCount);
Chèn nCount byte vào t vùng đ m (đ
c tr b i puch psch) vào dòng. N u file đ c m ch đ
text, các ký tự CR có th đ
c chèn vào. Hàm này có ích cho dòng xu t nh phân. Ch ng h n: char Buff[]="HAPPY BIRTHDAY";
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 152 cout.write(Buff,10);
Hàm istream::gcount(): int gcount();
Hàm tr v s ký tự đã trích b i hàm nh p không đ nh d ng cu i cùng. VI. DÒNG NH P/ XU T FILE
Đ thực thi x lý file trong C++, các ch ng trình ph i include t p tin và .
Header g m đ nh nghƿa cho các l p dòng ifstream cho nh p (đ c) t m t file, ofstream cho
xu t (ghi) t i m t file) và fstream cho nh p/xu t (đ c/ghi) t i m t file. Các file đ c m b ng cách t o các
đ i t ng c a các l p dòng này. Cây ph h c a các l p này hình 8.2.
• Constructor c a l p ofstream: (1) ofstream();
(2) ofstream(const char* szName,int nMode=ios::out,int nProt=filebuf::openprot);
(3) ofstream(int fd);
(4) ofstream(filedesc fd, char* pch, int nLength);
Trong đó: szName: Tên file đ c m .
nMode: M t s nguyên ch a các bit mode đ nh nghƿa là ki u li y kê c a ios. Có th k t h p b ng toán t
|. Tham s này có th m t trong các giá tr sau: Mode Ý nghƿa ios::app
Hàm di chuy n con tr file t i end-of-file. Khi các byte m i đ c ghi lên file,
chúng luôn luôn n i thêm vào cu i, ngay c v trí đ c di chuy n v i hàm ostream::seekp(). ios::ate
Hàm di chuy n con tr file t i end-of-file. Khi byte m i đ u tiên đ c ghi lên file,
chúng luôn luôn n i thêm vào cu i, nh ng khi các byte k ti p đ c ghi, chúng ghi vào v trí hi n hành. ios::in
M file đ đ c.V i dòng ifstream, vi c m file đ ng nhiên đ c thực hi n ch đ này. ios::out
M file đ đ c.V i dòng ofstream, vi c m file đ ng nhiên đ c thực hi n ch đ này. ios::trunc
Xóa file hi n có trên đƿa và t o file m i cùng tên. Cũng có hi u đây là ch t c t file cũ, làm cho kích th
c c a nó b ng 0, chu n b ghi n i dung m i. Mode này đ c áp d ng n u ios::out đ
c ch đ nh và ios::app, ios::ate, và ios::in không đ c ch đ nh. ios::nocreate
N u file không t n t i thì thao tác m th t b i. ios::noreplace
N u file t n t i thì thao tác m th t b i. ios::binary
M file ch đ nh phân (m c đ nh là ch đ vĕn b n).
nProt: Đ c t ch đ b o v file.
fd: Mã nh n di n file.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 153
pch: Con tr tr t i vùng dành riêng chi u dài nLength. Giá tr NULL (ho c nLength=0) d n đ n dòng không vùng đ m.
nLength: Chi u dài tính theo byte c a vùng dành riêng (0=không vùng đ m).
D ng (1) xây dựng m t đ i t
ng ofstream mà không m file.
D ng (2) xây dựng m t đ i t
ng ofstream và m file đã ch đ nh.
D ng (3) xây dựng m t đ i t
ng ofstream và g n (attach) v i m t file m .
D ng (4) xây dựng m t đ i t
ng ofstream mà liên k t v i đ i t ng filebuf. Đ i t ng filebuf đ c
g n t i file m và vùng dành riêng.
• Constructor c a l p ifstream: (1) ifstream();
(2) ifstream(const char* szName,int nMode=ios::in,int nProt=filebuf::openprot);
(3) ifstream(int fd);
(4) ifstream(filedesc fd, char* pch, int nLength);
D ng (1) xây dựng m t đ i t
ng ifstream mà không m file.
D ng (2) xây dựng m t đ i t
ng ifstream và m file đã ch đ nh.
D ng (3) xây dựng m t đ i t
ng ifstream và g n (attach) v i m t file m .
D ng (4) xây dựng m t đ i t
ng ofstream mà liên k t v i đ i t ng filebuf. Đ i t ng filebuf đ c
g n t i file m và vùng dành riêng.
• Constructor c a l p fstream: (1) fstream();
(2) fstream(const char* szName,int nMode,int nProt=filebuf::openprot);
(3) fstream(int fd);
(4) fstream(filedesc fd, char* pch, int nLength);
D ng (1) xây dựng m t đ i t
ng fstream mà không m file.
D ng (2) xây dựng m t đ i t
ng fstream và m file đã ch đ nh.
D ng (3) xây dựng m t đ i t
ng fstream và g n (attach) v i m t file m .
D ng (4) xây dựng m t đ i t
ng ofstream mà liên k t v i đ i t ng filebuf. Đ i t ng filebuf đ c
g n t i file m và vùng dành riêng.
N u chúng ta s d ng constructor d ng (1) thì chúng ta dùng hàm open() đ m file:
• Hàm ofstream::open():
void open(const char* szName,int nMode=ios::out,int nProt=filebuf::openprot); Hàm ifstream::open():
void open(const char* szName,int nMode=ios::in,int nProt=filebuf::openprot); Hàm fstream::open():
void open(const char* szName,int nMode,int nProt=filebuf::openprot);
Đ đóng file chúng ta dùng hàm close(), hàm này các l p ifstream, ofstream, và fstream đ u có d ng: void close();
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 154
Các hàm liên quan đến con trỏ file: - L p istream:
Hàm seekg(): (seek get)
(1) istream& seekg(streampos pos);
(2) istream& seekg(streamoff off,ios::seek_dir dir); Trong đó:
+ pos: V trí m i. streampos là t ng đ
ng typedef v i long.
+ off: Giá tr offset m i. là t ng đ
ng typedef v i long. + dir: h
ng seek. Có m t trong các tr sau: ios::begin Seek t b t đ u c a dòng. ios::cur
Seek t øv trí hi n hành c a dòng ios::end Seek t cu i c a dòng
Hàm tellg(): (tell get) streampos tellg();
Hàm tr v v trí hi n hành c a con tr file. - L p ostream:
Hàm seekp(): (seek put)
(1) ostream& seekp(streampos pos);
(2) ostream& seekp(streamoff off,ios::seek_dir dir);
Hàm tellp(): (tell put) streampos tellp();
Hàm tr v v trí hi n hành c a con tr file.
VI.1. Nh p/xu t file vĕn b n N u dòng đ
c g n v i file vĕn b n, vi c nh p/xu t file đ
c thực hi n m t cách đ n gi n b i các toán
t >> <<, gi ng nh khi chúng ta làm vi c v i cin cout. File vĕn b n ch a d li u d ng mã ASCII, k t thúc b i ký tự EOF.
Ví d 8.28: T o file vĕn b n có th đ
c s d ng trong h th ng có th nh n đ c các tài kho n đ giúp
đ qu n lý ti n n b i các khách hàng tín d ng c a công ty. M i khách hàng, ch ng trình ch a m t s tài
kho n, tên và s d (balance). 1: //Chương trình 8.28 2: #include 3: #include 4: #include 5: 6: int main() 7: {
8: ofstream OutClientFile("clients.dat", ios::out); 9: if (!OutClientFile) 10: {
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 155
11: cerr << "File could not be opened" << endl; 12: exit(1); 13: }
14: cout << "Enter the Account, Name, and Balance." << endl
15: << "Enter EOF to end input." << endl << "? "; 16: int Account; 17: char Name[10]; 18: float Balance;
19: while (cin >> Account >> Name >> Balance) 20: {
21: OutClientFile << Account << " " << Name
22: << " " << Balance << endl; 23: cout << "? "; 24: } 25: OutClientFile.close(); 26: return 0; 27: }
Chúng ta ch y ví d 8.28, k t qu hình 8.30
Hình 8.30: K t qu c a ví d 8.28
Ví d 8.29: Đ c file vĕn b n t o ví d 8.28 và xu t ra màn hình. 1: //Chương trình 8.29 2: #include 3: #include 4: #include 5: #include 6:
7: void OutputLine(int, char*, float); 8: 9: int main() 10: {
11: ifstream InClientFile("clients.dat", ios::in); 12: if (!InClientFile) 13: {
14: cerr << "File could not be opened" << endl; 15: exit(1); 16: } 17: int Account; 18: char Name[10]; 19: float Balance;
20: cout << setiosflags(ios::left) << setw(10) << "Account"
21: << setw(13) << "Name" << "Balance" << endl;
22: while (InClientFile >> Account >> Name >> Balance)
23: OutputLine(Account, Name, Balance); 24: InClientFile.close(); 25: return 0;
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 156 26: } 27:
28: void OutputLine(int Acct, char *Name, float Bal) 29: {
30: cout << setiosflags(ios::left) << setw(10) << Acct
31: << setw(13) << Name << setw(7) << etprecision(2)
32:<< setiosflags(ios::showpoint | ios::right) << Bal << endl; 33: }
Chúng ta ch y ví d 8.29, k t qu hình 8.31
Hình 8.31: K t qu c a ví d 8.29
Do l p ifstream d n xu t t l p istream nên chúng ta có th dùng các hàm istream::get(), istream::getline().
Ví d 8.30: Đ c file vĕn b n t o ví d 8.28 b ng hàm istream::getline() và xu t ra màn hình. 1: //Chương trình 8.30 2: #include 3: #include 4: #include 5: #include 6: 7: #define MAXLINE 256 8: 9: int main() 10: {
11: ifstream InClientFile("clients.dat", ios::in); 12: if (!InClientFile) 13: {
14: cerr << "File could not be opened" << endl; 15: exit(1); 16: } 17: char Line[MAXLINE];
18: while (!InClientFile.eof()) 19: {
20: InClientFile.getline(Line,MAXLINE-1); 21: cout<22: } 23: InClientFile.close(); 24: return 0; 25: }
Chúng ta ch y ví d 8.30, k t qu hình 8.32.(n i dung t p tin clients.dat)
Hình 8.32: K t qu c a ví d 8.30
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 157
VI.2. Nh p/xu t file nh phân
Đối với file nh phân (còn g i là file truy cập ngẫu nhiên), chúng ta mở ở chế độ ios::binary. Đối với
file nh phân, chúng ta có thể dùng hàm istream::get() ostream::put() để đ c và ghi từng byte một. Để
đ c và ghi nhiều byte cùng lúc chúng ta có thể dùng istream::read() ostream::write().
Ví d 8.31: L y l i ví d 8.28 nh ng l u d li u d i d ng nh phân. 1: //Chương trình 8.31 2: #include 3: #include 4: #include 5: 6: typedef struct 7: { 8: int Account; 9: char Name[10]; 10: float Balance; 11: }Client; 12: 13: int main() 14: {
15: ofstream OutClientFile("credit.dat", ios::out|ios::binary); 16: if (!OutClientFile) 17: {
18: cerr << "File could not be opened" << endl; 19: exit(1); 20: }
21: cout << "Enter the Account, Name, and Balance." << endl
22: << "Enter EOF to end input." << endl << "? "; 23: Client C;
24: while (cin >> C.Account >> C.Name >> C.Balance) 25: {
26: OutClientFile.write((char *)&C,sizeof(Client)); 27: cout << "? "; 28: } 29: OutClientFile.close(); 30: return 0; 31: }
Chúng ta ch y ví d 8.31, k t qu hình 8.33 (n i dung t p tin credit.dat)
Hình 8.33: K t qu c a ví d 8.31
Ví d 8.32: Đ c file t o ví d 8.31 và xu t ra màn hình. 1: //Chương trình 8.32 2: #include 3: #include 4: #include 5: #include 6:
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 158 7: typedef struct 8: { 9: int Account; 10: char Name[10]; 11: float Balance; 12: }Client; 13: 14: void OutputLine(Client); 15: 16: int main() 17: {
18: ifstream InClientFile("credit.dat", ios::in|ios::binary); 19: if (!InClientFile) 20: {
21: cerr << "File could not be opened" << endl; 22: exit(1); 23: }
24: cout << setiosflags(ios::left) << setw(10) << "Account"
25: << setw(13) << "Name" << "Balance" << endl; 26: Client C;
27: while (InClientFile.read((char *)&C,sizeof(Client))) 28: OutputLine(C); 29: InClientFile.close(); 30: return 0; 31: } 32: 33: void OutputLine(Client C) 34: {
35: cout << setiosflags(ios::left) << setw(10) << C.Account
36: << setw(13) << C.Name << setw(7) << setprecision(2)
37: << setiosflags(ios::showpoint | ios::right)<< C.Balance << endl; 38: }
Chúng ta ch y ví d 8.32, k t qu hình 8.34
Hình 8.34: K t qu c a ví d 8.32 BÀI T P
Bài 1: Cài đ t toán t >> và << cho ki u d li u m ng đ nh p và xu t.
Bài 2: Cài đ t thêm toán t >> và << cho l p Time trong bài 5 c a ch ng 4.
Bài 3: Cài đ t thêm toán t >> và << cho l p Date trong bài 6 c a ch ng 4. Bài 4: Vi t ch
ng trình ki m tra các giá tr nguyên nh p vào d ng h 10, h 8 và h 16. Bài 5: Vi t ch
ng trình in b ng mã ASCII cho các ký tự có mã ASCII t 33 đ n 126. Ch ng
trình in g m giá tr ký tự, giá tr h 10, giá tr h 8 và giá tr h 16. Bài 6: Vi t ch
ng trình in các giá tr nguyên d ng luôn có d u + phía tr c. Bài 7: Vi t ch ng trình t
ng tự nh l nh COPY c a DOS đ sao chép n i dung c a file . Bài 8: Vi t ch ng trình cho bi t kích th c file. Bài 9: Vi t ch ng trình đ m s l
ng t có trong m t file vĕn b n ti ng Anh.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 159 CHƯƠNG 9 HÀM L P TEMPLATE
Trong ph n này, chúng ta tìm hi u v m t trong các đ c tính còn l i c a C++, đó là template (khuôn
m u). Các template cho phép chúng ta đ đ nh rõ, v i m t đo n mã đ n gi n, m t toàn b ph m vi c a các
hàm có liên quan (đa nĕng hóa)–g i là các hàm template-ho c m t toàn b ph m vi c a các l p có liên quan- g i là l p template.
Chúng ta có th vi t m t hàm template đ n gi n cho vi c s p x p m t m ng và C++ tự đ ng phát sinh
các hàm template riêng bi t mà s s p x p m t m ng int, s p x p m t m ng float, …
Chúng ta có th vi t m t l p template cho l p stack và sau đó C++ tự đ ng phát sinh các l p template
riêng bi t nh l p stack c a int, l p stack c a float,… I. Các hàm template
Các hàm đa nĕng hóa bình th ng đ
c s d ng đ thực hi n các thao tác t ng tự trên các ki u khác
nhau c a d li u. N u các thao tác đ ng nh t cho m i ki u, đi u này có th thực hi n m ch l c và thu n ti n
h n s d ng các hàm template. L p trình viên vi t đ nh nghƿa hàm template đ n gi n. Dựa vào các ki u tham
s cung c p trong l i g i hàm này, trình biên d ch tự đ ng phát sinh các hàm mã đ i t ng riêng bi t đ x
lý m i ki u c a l i g i thích h p. Trong C, đi u này có th đ
c thực hi n b ng cách s d ng các macro t o
v i ti n x lý #define. Tuy nhiên, các macro bi u th kh nĕng đ i v i các hi u ng l nghiêm tr ng và
không cho phép trình biên d ch thực hi n vi c ki m tra ki u. Các hàm template cung c p m t gi i pháp m ch
l c gi ng nh các macro, nh ng cho phép ki m tra ki u đ y đ . Ch ng h n, chúng ta mu n vi t hàm l y tr
tuy t đ i c a m t s , chúng ta có th vi t nhi u d ng khác nhau nh sau: int MyAbs(int X) { return X>=0?X:-X; } long MyAbs(long X) { return X>=0?X:-X; } double MyAbs(double X) { return X>=0?X:-X; }
Tuy nhiên v i các hàm này chúng ta v n ch a có gi i pháp t t, mang tính t ng quát nh t nh hàm có
tham s ki u int nh ng giá tr tr v là double và ng c l i.
T t c các hàm template đ nh nghƿa b t đ u v i t khóa template theo sau m t danh sách các tham s
hình th c v i hàm template vây quanh trong các ngo c nh n (<>); M i tham s hình th c ph i đ c đ t tr
c b i t khóa class nh :
template T> ho c
template T1, class T2,>
Các tham s hình th c c a m t đ nh nghƿa template đ
c s d ng đ mô t các ki u c a các tham s cho
hàm, đ mô t ki u tr v c a hàm, và đ khai báo các bi n bên trong hàm. Ph n đ nh nghƿa hàm theo sau và
đ c đ nh nghƿa gi ng nh b t kỳ hàm nào. Chú ý t khóa class s d ng đ mô t các ki u tham s c a hàm
template thực sự nghƿa là "ki u có s n và ki u ng
i dùng đ nh nghƿa b t kỳ".
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 160
Khi đó, hàm tr tuy t đ i trên vi t theo hàm template: template T MyAbs(T x) { return (x>=0)?x:-x; }
Hàm template MyAbs() khai báo m t tham s hình th c T cho ki u c a m t s . T đ c tham kh o nh
m t tham s ki u. Khi trình biên d ch phát hi n ra m t l i g i hàm MyAbs() trong ch ng trình, ki u c a
tham s th nh t c a hàm MyAbs() đ
c thay th cho T thông qua đ nh nghƿa template, và C++ t o m t hàm
template đ y đ đ tr v tr tuy t đ i c a m t s c a ki u d li u đã cho. Sau đó, hàm m i t o đ c biên d ch. Ch ng h n:
cout<cout<Trong l n g i th nh t, hàm MyAbs() có tham s thực là int nên trình biên d ch t o ra hàm int
MyAbs(int) theo d ng c a hàm template, l n th hai s t o ra hàm float MyAbs(float).
M i tham s hình th c trong m t đ nh nghƿa hàm template ph i xu t hi n trong danh sách tham s c a
hàm t i thi u m t l n. Tên c a tham s hình th c ch có th s d ng m t l n trong danh sách tham s c a ph n đ u template.
Ví d 9.1: S d ng hàm template đ in các giá tr c a m t m ng có ki u b t kỳ. 1: //Chương trình 9.1 2: #include 3: 4: template
5: void PrintArray(T *Array, const int Count) 6: {
7: for (int I = 0; I < Count; I++)
8: cout << Array[I] << " "; 9: 10: cout << endl; 11: } 12: 13: int main() 14: {
15: const int Count1 = 5, Count2 = 7, Count3 = 6;
16: int A1[Count1] = {1, 2, 3, 4, 5};
17: float A2[Count2] = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7};
18: char A3[Count3] = "HELLO";
19: cout << "Array A1 contains:" << endl;
20: PrintArray(A1, Count1); //Hàm template ki u int
21: cout << "Array A2 contains:" << endl;
22: PrintArray(A2, Count2); //Hàm template ki u float
23: cout << "Array A3 contains:" << endl;
24: PrintArray(A3, Count3); //Hàm template ki u char 25: return 0; 26: }
Chúng ta ch y ví d 9.1, k t qu hình 9.1
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 161
Hình 9.1: K t qu c a ví d 9.1
Ví d 9.2: Hàm template có th có nhi u tham s . 1: //Chương trình 9.2 2: #include 3: 4: template 5: T Max(T a, T b) 6: { 7: return (a>b)?a:b; 8: } 9: 10: int main() 11: { 12: float A,B;
13: cout<<"Enter first number:"; 14: cin>>A;
15: cout<<"Enter second number:"; 16: cin>>B;
17: cout<<"Maximum:"<18: return 0; 19: }
Chúng ta ch y ví d 9.2, k t qu hình 9.2
Hình 9.2: K t qu c a ví d 9.2 M t hàm template có th đ
c đa nĕng hóa theo vài cách. Chúng ta có th cung c p các hàm template
khác mà mô t cùng tên hàm nh ng các tham s hàm khác nhau. M t hàm template cũng có th đ c đa
nĕng hóa b i cung c p hàm non-template v i cùng tên hàm nh ng các tham s hàm khác nhau. Trình biên
d ch thực hi n m t x lý so sánh đ xác đ nh hàm g i khi m t hàm đ
c g i. Đ u tiên trình biên d ch c
g ng tìm và s d ng m t đ i sánh chính xác mà các tên hàm và các ki u tham s đ i sánh chính xác. N u
đi u này th t b i, trình biên d ch ki m tra n u m t hàm template đã có mà có th phát sinh m t hàm template
v i m t đ i sánh chính xác c a tên hàm và các ki u tham s . N u m t hàm template nh th đ c tìm th y,
trình biên d ch phát sinh và s d ng hàm template thích h p. Chú ý x lý đ i sánh này v i các template đòi
yêu các đ i sánh chính xác trên t t c ki u tham s -không có các chuy n đ i tự đ ng đ c áp d ng. II. Các l p template
Bên c nh hàm template, ngôn ng C++ còn trang b thêm l p template, l p này cũng mang đ y đ ý t
ng c a hàm template. Các l p template đ
c g i là các ki u có tham s (parameterized types) b i vì
chúng đòi h i m t ho c nhi u tham s đ mô t làm th nào tùy ch nh m t l p template chung đ t o thành m t l p template c th .
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 162
Chúng ta cài đ t m t l p Stack, thông th
ng chúng ta ph i đ nh nghƿa tr c m t ki u d li u cho t ng
ph n t c a stack. Nh ng đi u này ch mang l i sự trong sáng cho m t ch
ng trình và không gi i quy t
đ c v n đ t ng quát. Do đó chúng ta đ nh nghƿa l p template Stack. Ví d 9.3: File TSTACK.H: 1: //TSTACK.H 2: //Lớp template Stack 3: #ifndef TSTACK_H 4: #define TSTACK_H 5: 6: #include 7: 8: template 9: class Stack 10: { 11: private:
12: int Size; //Kích thước stack 13: int Top; 14: T *StackPtr; 15: public: 16: Stack(int = 10); 17: ~Stack() 18: { 19: delete [] StackPtr; 20: } 21: int Push(const T&); 22: int Pop(T&); 23: int IsEmpty() const 24: { 25: return Top == -1; 26: } 27: int IsFull() const 28: { 29: return Top == Size - 1; 30: } 31: }; 32: 33: template 34: Stack::Stack(int S) 35: {
36: Size = (S > 0 && S < 1000) ? S : 10; 37: Top = -1; 38: StackPtr = new T[Size]; 39: } 40: 41: template
42: int Stack::Push(const T &Item) 43: { 44: if (!IsFull()) 45: { 46: StackPtr[++Top] = Item; 47: return 1; 48: } 49: return 0; 50: } 51:
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 163 52: template
53: int Stack::Pop(T &PopValue) 54: { 55: if (!IsEmpty()) 56: {
57: PopValue = StackPtr[Top--]; 58: return 1; 59: } 60: return 0; 61: } 62: 63: #endif File CT9_3.CPP: 1: //CT9_3.CPP 2: //Chương trình 9.3 3: #include "tstack.h" 4: 5: int main() 6: { 7: Stack FloatStack(5); 8: float F = 1.1;
9: cout << "Pushing elements onto FloatStack" << endl;
10: while (FloatStack.Push(F)) 11: {
12: cout << F << ' '; 13: F += 1.1; 14: }
15:cout << endl << "Stack is full. Cannot push " << F << endl
16: << endl << "Popping elements from FloatStack" << endl; 17: while (FloatStack.Pop(F))
18: cout << F << ' ';
19: cout << endl << "Stack is empty. Cannot pop" << endl; 20: Stack IntStack; 21: int I = 1;
22: cout << endl << "Pushing elements onto IntStack" << endl; 23: while (IntStack.Push(I)) 24: {
25: cout << I << ' '; 26: ++I ; 27: }
28:cout << endl << "Stack is full. Cannot push " << I << endl
29: << endl << "Popping elements from IntStack" << endl; 30: while (IntStack.Pop(I))
31: cout << I << ' ';
32: cout << endl << "Stack is empty. Cannot pop" << endl; 33: return 0; 34: }
Chúng ta ch y ví d 9.3, k t qu hình 9.3
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 164
Hình 9.3: K t qu c a ví d 9.3
Hàm thành viên đ nh nghƿa bên ngoài l p template b t đ u v i ph n đ u là
template T> Sau đó m i đ nh nghƿa t
ng tự m t đ nh nghƿa hàm th
ng ngo i tr ki u ph n t luôn luôn đ c li t
kê t ng quát nh tham s ki u T. Ch ng h n: template
int Stack::Push(const T &Item) { ……………. }
Ngôn ng C++ còn cho phép chúng ta t o ra các l p template linh đ ng h n b ng cách cho phép thay
đ i giá tr c a các thành viên d li u bên trong l p. Khi đó l p có d ng c a m t hàm v i tham s hình th c. BÀI T P
Bài 1: Vi t hàm template tr v giá tr trung bình c a m t m ng, các tham s hình th c c a hàm này là tên m ng và kích th c m ng.
Bài 2: Cài đ t hàng đ i template.
Bài 3: Cài đ t l p template dùng cho cây nh phân tìm ki m (BST).
Bài 4: Cài đ t l p template cho vector đ qu n lý vector các thành ph n có ki u b t kỳ.
Bài 5: Vi t hàm template đ s p x p ki u d li u b t kỳ.
Bài 6: Trong C++, phép toán new đ
c dùng đ c p phát b nh , khi không c p phát đ c con tr có
giá tr NULL. Hãy cài đ t l i các l p Matrix và Vector trong đó có b sung thêm thành viên là l p exception
v i tên g i là Memory đ ki m tra vi c c p phát này.
Biên so n: Lê Th Mỹ H nh
Giáo trình môn L p trình h ng đ i t ng Trang 165 TÀI LI U THAM KH O [1] L p trình h ng đ i t ng C++ c a Nguy n Thanh Thu [2] L p trình h ng đ i t ng C++ c a Tr n Vĕn Lĕng
[3] C++ K thu t và ng d ng – Scott Robert Ladd
[4] Ngôn ng l p trình C và C++ [5] Bài t p L p trình h ng đ i t ng - Nguy n Thanh Thu
[6] Introduction to Object-Oriented Programming Using C++ - Peter Müller [7] ..
Biên so n: Lê Th Mỹ H nh