-
Thông tin
-
Hỏi đáp
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!
Lập trình hướng đối tượng 1 tài liệu
Trường Đại học Sư phạm Kỹ thuật, Đại học Đà Nẵng 5 tài liệu
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!
Môn: Lập trình hướng đối tượng 1 tài liệu
Trường: Trường Đại học Sư phạm Kỹ thuật, Đại học Đà Nẵng 5 tài liệu
Thông tin:
Tác giả:
Tài liệu khác của Trường Đại học Sư phạm Kỹ thuật, Đại học Đà Nẵng
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 và 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 struct và union 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 struct và union đ
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 và 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() và 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 và 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 và 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 và 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, Minute và second. 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 public và private đ
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 và 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 và 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 là 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 và 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 và 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 và 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 và 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 và 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
và HireDate. Các thành viên BirthDate và HireDate 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 và 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 và 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 và 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 và 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 &, *, + và – 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 >> và << 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 và 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 new và delete:
• 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 và delete m c đ nh.
• Chúng ta đa nĕng hóa các toán t new và delete 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 new và delete áp d ng đ i v i l p đó. Khi chúng ta dùng new và delete đ i v i l p nào đó, trình
biên d ch s ki m tra xem new và delete có đ
c đ nh nghƿa riêng cho l p đó hay không; n u không thì dùng
new và delete toàn c c (có th đã đ c đa nĕng hóa).
Hàm toán t c a toán t new và delete 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 new và delete toàn c c đ ng th i ch ng t r ng toán t new và delete
do đa nĕng hóa thay th toán t new và delete 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 new và delete 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 new và delete 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 new và delete m t cách toàn c c.
Ví d 4.16: Đa nĕng hóa toán t new và delete 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 << là
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 và protected c a l p c s
đ c k th a nh là các thành viên public và 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 và 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 và 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() và 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 và 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 và 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 và 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, protected và private.
class <drived_class_name> : <type_of_inheritance> <base_class_name> {……………….. };
Trong đó type_of_inheritance là public, 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 và 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 và 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 và protected c a l p public và protected c a l p hàm thành viên public c s . c s .
và 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 và 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 và 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 và 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 và 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 và 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 << và >> 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 << và >> đ 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() và 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 và 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 >> và <<, gi ng nh khi chúng ta làm vi c v i cin và 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() và 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() và 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 VÀ 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 (< và >); 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