Phong Cach Lap Trinh

  • July 2020
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Phong Cach Lap Trinh as PDF for free.

More details

  • Words: 18,982
  • Pages: 58
++ . Tác gi : Giáo viên h ng d n: Sinh viên d ch:

Mats Henricson and Erik Nyquist. Th y Nguy n T n Tr n Minh Khang. Lê Quang Song.

! "#" $% &' !: • • • •

• •

• •

• •

1. % % ()%*'(Introduction) 2. )'+( !,(Terminology) 3. - ". ")' !(General Recommendations) 4./0 !'1 (23 ! ), ! 4%56(Source Code in Files) * 4.1. ' (27" 80(Structure of Code) * 4.2. 9 ), ! 4%56(Naming Files) * 4.3. ), ! 5:% !% % ();")(Comments) * 4.4.I "5'&6 ), ! 4%56(Include Files) 5. ), ! (9 !# (Assigning Names) 6.<)3 ! "#")(Style) * 6.1. #" 5 =(Classes) * 6.2. #" )>8(Functions) * 6.3.?)@% 5* ) A%-' B)%C (Flow Control Statements) * 6.4D 3 (2E F> ()G8 ")%H'(Pointers and References) * 7.1.Quy-n truy c+p(Considerations Regarding Access Rights) * 7.2.H>8 Inline(Inline Functions) * 7.3. #" )>8 IJ (Friends) * 7.4. >8 )K ! ()> ) F%9 (const Member Functions) * 7.5. >8 B)L% (J3M)>8 )NO(Constructors and Destructors) * 7.6.T3# (. gán(Assignment Operators) * 7.6. '# ( % (3# (.(Operator Overloading) * 7.7.?%C' (2 F- "NG )>8 ()> ) F%9 (Member Function Return Types) * 7.8.KH ()PG(Inheritance) 8.Q = (68=5G(6R(Class Templates) 9. >8(Functions) * 9.1. @% R@ "NG )>8(Function Arguments) * 9.2. '# ( % )>8(Function Overloading) * 9.3. @% R@ )S ) ()T"(Formal Arguments) * 9.4.Gi# (2 F> B%C' (2 F-(Return Types and Values) * 9.5.Hàm inline(Inline Functions) * 9.6. ), ! A@% ( U ! (J8 ():%(Temporary Objects) * 9.7. Vng quan(General) 10. K !(Constants) 11. %H (Variables)

• • • • • •



12. 3 (2E F> ()G8 ")%H'(Pointers and References) 13.Ép B%C'(Type Conversions) 14.?)@% " ' (27" A%-' B)%C (Flow Control Structures) 15. %C' ()T"(Expressions) 16. = =)#( I$ ) (Memory Allocation) 17./0 5% ) A$ !(Portable Code) * 17.1.W, 5%*' (2P' ( U !(Data Abstraction) * 17.2.?;"B "X "NG B%C'(Sizes of Types) * 17.3. )'OC AV% B%C'(Type Conversions) * 17.4./Y ( &, 5%*'(Data Representation) * 17.5. Underflow/Overflow *17.6. @% ( U ! (J8 ():%(Temporary Objects) *17.7. 3 (2E R@ )Z"(Pointer Arithmetic) 18.[#") ()G8 B) 3(References)

1.GI\I THI]U(INTRODUCTIONS) /^" A;") "NG (>% 5%*' >O 5> _#" A ) 8$( =)3 ! "#") 5+= (2S ) (23 ! ++D ), ! `'% (a" F> ), ! A". L AbO B)Y ! =) % 5> ( ( " ) ! c "' ! " = ), ! B%H ()T" "d I AC 5>8 F%*" F % ++D += )U= ), ! `'% (a" >O Re 5> ), ! (>% 5%*' f ! A$ !MB)'OH B);") Rg =) ( (2%C thêm. ), ! O9' " ' F-

), ! `'% (a" 8 % )GO ), ! Rg ()GO AV% "#" `'% (a" A U" BC AH !) "h ! "c ()C !L% AH ")7 ! (Y% `'G A G ")i 8G%5 ) RG' : • •

) 5> =)^ 5^" "NG (>' >O. ), ! A-

[email protected] [email protected]

), ! ") d ! (2S ) A U" =)#( (2%C ()63 "#" `'% (a" F> ), ! (%H ". L AbO Re: j 7 !. * /G ! (; ) (#% R. &^ ! C AJ( AH Rg "); ) _#"M") d ! (2S ) 9 : * c 8$( =)3 ! "#") ) ( `'# . * W &> ! AZ" F> )%C'. j ?) f ! ")'OC AV% !%,G "#" !Y !,. j J3 2G ), ! ()Y ! I#3 5k% =)V I%H . j c ()C &'O (2S IL% ), ! )> 5+= (2S ) B)#" )G'. ), ! "b' )E% (23 ! F%*" ()%H( BH ) 5> l5>8 ()H >3 AC ()%H( BH 8$( 5 = )3m" An ! " = "NG 5 = K8 !3>% (>% 5%*' >OD c ()C ()G8 B) 3 ), ! R#") (23 ! A U" !% % ()%*' "'@% (>% 5%*' >O. ), ! !S ")TG Ag ! I9 (23 ! (>% 5%*' >O Re ")i 2G "#") ) ()H >3 AC !% % `'OH( "c )%*' `' ), ! B);G "J ) B)c B)f ) ( trong C++D =) % a8 Ia( F> )Z" Bo ), ! F; &^ F- ), ! A3J 80 F; &^ A U" "' ! " = L AbO.

2.THUpT NG (TERMINOLOGY) 1. M$( I%H ,)K ! M)>8 )3m" 8$( B%C' trong C++ A-' "c 8$( nh danh (identifier) hay 5> 8$( (9n riêng D?)% " ()%H(, 8$( A ) &G ) "c " ' (27" $% I$ "c !)oG 5> "c "#" (%- (@ M(9 F> "#" )+' (@ (23 ! Ac.q )63 ()T (g)

2.Class 5> 8$( B%C' &, 5%*' &3 ! :% &r ! (g A ) !)oG IG3 !18 "#" &, 5%*' F> "#" )>8 ()g" )%* (29 "#" &, 5%*' Ac.Trong C++ ,AbO "c 5e A U" B)G% I#3 ) 8$( 5 = M c "h ! A U" B)G% I#3 ) 8$( " ' (member (27"(struct) )GO 8$( union .W, 5%*' A U" A ) !)oG (23 ! 5 = A U" !Z% 5> data) . > ), ! )>8 A U" A ) !)oG (23 ! 5 = A U" !Z% 5> "#" (member functions) . sD/$( class/struct )3m" union A U" c% 5> "#" B%C' &, 5%*' (2P' ( U !(abstract data type) ")7 ! B)Y ! "c I ( BS 8$( >3. (public or protected member data.) tD/$( struct "h ! 5> 8$( B%C' &, 5%*' &3 ! :% &r ! A ) !)oG ) "$ ! (public data)8> ()Y%.

! ")7 ! ")i ")TG &, 5%*' "Y !

5. Public members "NG 8$( 5 = 5> "#" &, 5%*' ()> ) F%9 ( member data)F> "#" )>8 ()> ) F%9 (member fuctions) "#% 8> "c ()C A U" R. &^ ! 8Z% d% . 6.Protected members "NG 8$( 5 = 5> "#" member data F> "#" member functions 8> "#" )>8 ()> ) F%9 "NG 5 = !@" 8 % (2'O "+= A U" . uD/$( class template A ) !)oG 8$( )Z "NG ), ! 5 = D/$( 5 = 8 % A U" Re A U" (J3 (P class template IK ! F%*" "' ! " = 8$( R@ "#" A@% R@. ), ! !%# (2 >O "c ()C 5> (9 "NG ), ! B%C' )GO "#" I%C' ()T" )Kng. vD d ! (g 8$( functions template A ) !)oG 8$( )Z "NG ), ! )>8D/$( )>8 8 % Re A U" (J3 (P functions template IK ! F%*" "' ! " = 8$( R@ "#" A@% R@D ), ! !%# (2 >O "c ()C 5> (9 "NG ), ! B%C' )GO "#" I%C' ()T" )K( B%C' enumeration type 5> 8$( B)G% I#3 2w 2> ! (+= )U= A O AN B; )%*' )K !. 23 ! xx c A U" B)G% I#3 5> enum. 10./$( typedef 5> 8$( (9 B)#" ")3 8$( B%C' &, 5%*' M(23 ! xx ()S B)G% I#3 5> typedef . 11./$( ()G8 ")%H'(reference) 5> 8$( (9 B)#" ")3 8$( I%H .Trong C++ M(3# (. A G ")i (&) A U" B)G% I#3 !GO RG' B%C' &, 5%*' AC ")i 2K ! A0 B)G% I#3 8$( I%H M)K !MA@% R@ "NG )>8 5> 8$( ()G8 ")%H'. 12./$( (macro) 5> (9 ")3 8$( ")'k% Ff I n "#% 8> A U" A ) !)oG (23 ! B)G% I#3 #define . ?)% (9 >O _' ( )%* trong A3J 80M(2S ) I%9 & ") Re ()GO ()H c & % &J ! Ff I . 13 Constructor 5> 8$( )>8 B)L% (J3 ")3 8$( A@% ( U !. 14.Copy constructor 5> )>8 (J3 I RG3 Ac 5> 8$( )>8 B)L% (J3 (23 ! Ac A@% R@ A ' (%9 ()G8 ")%H' AH A@% ( U ! "r ! B%C' F % A@% ( U ! A U" B)L% (J3 . 15. >8 B)L% (J3 8m" A ) 5> )>8 B)Y ! "c A@% R@. 16.Overloaded function name 5> `'# ( % (9 )>8 "c !)oG 5> (9 A U" R. &^ ! ")3 )G% )GO )%-' )>8 ) ! B)#" ()G8 R@ (2'O- F>3 F> B%C' (2 F-. 17.Overridden 5> )>8 ")1 ! "c !)oG 5> 8$( )>8 ()> ) F%9 (23 ! 5 = "d RL A U" A ) !)oG 5J% (P 5 = !@". )7 ! 5> "#" )>8 3(virtual).

18.Pre-defined data type 5> B%C' &, 5%*' "c (23 ! !Y

!, MF; &^ int ,float…

19.User-defined data type 5> B%C' &, 5%*' &3 ! :% &r ! A ) !)oG ) 5> :class,struct… 20.Abstract base class 5> 8$( 5 = 8> B)Y ! A@% ( U ! >3 "c ()C (J3 M c ")i A U" R. &^ ! ) 8$( 5 = "d RL ")3 F%*" (S8 2G 8$( 5 = B)#".

3.

(General Recommendations)

- ". 1: @% ' 80 B)% IJ ")i B)% IJ IJ "c Rg ()g" ()% "c F A-. ['O !)o )G% 5 (2 " B)% IJ Ia( A '. - ". 2: H' IJ R. &^ ! (2S ) I%9 & ") ++ trên Cfront M5'Y 5'Y I%9 & ") F % ": )%*' +w ()%H( 5+= "#" OH' (@ 53J% IE B)% 8$( F>% I#3 A$ ! "c ()C. )%-' "'$" B%C8 (2G ")3 () O c% ")' ! )%-' )> 5+= (2S ) A0 (@ 2 ( )%-' ():% !%G AC (@% ' ), ! A3J 80 "#% 8> ") G IG3 !%: A U" ")JOD H' ") d ! (2S ) "NG IJ `'# ")+8 MR. &^ ! gprof++ )3m" "Y ! "^ ( d ! (g AC _#" A ) "); ) _#" I ") ( "NG ), ! F A- (2 " B)% (@% '.

4./y 4.1.

{ Q|(Source Code in Files)

z

' (27" "NG 80: '% (a" 1: ), ! 4%56 ")} F>3 trong xx 5'Y 5'Y "c (9

4%56 "c A'Y% 8L 2$ ! “.h”.

'% (a" 2: ), ! 4%56 ()g" ()% trong C++ 5'Y 5'Y "c (9 4%56 "c A'Y% 8L 2$ ! “.cpp”. - ". 3: /$( % "5'&6 4%56 B)Y ! 9 ")TG )%-' )d 8$( 5:% A ) !)oG 5 =. - ". 4: )%G ), ! A ) !)oG "NG ), ! )>8 ()> ) F%9 )GO ), ! )>8 ()> ) )%-' file kh#" )G' H' "c ()C. - ". 5: m( ), ! 80 8#O A$" 5+= 59 ), ! 4%56 B)#" )G' AC & &> ! _#" A ) F (2; B)% 8G ! AH 8#O B)#".

/^" A;") "NG ), ! `'% " >O 5> AC "' ! " = Rg ()C )%* A1 ! ) ( "NG ), ! (9 file. /$( 5; &3 ")3 A%-' >O Ac 5> & &> ! ()G3 (#" ), ! "Y ! "^ (29 (9 4%56 "c A'Y% 8L 2$ ! Ac. c )G% 53J% 4%56 include trong C++ l ), ! "#% A U" ") = )+ trong " (2S ) I%9 & ") ANSI-C F> C++ FG ), ! ()T ")i A U" ") = )+ (23 ! (2S ) I%9 & ") xx 8> ()Y%.W3 Ac =) % =)b I%*( AC (2# ) 5k% (23 ! "#" 4%56 % "5'&6(&3 R. &^ ! RG% 53J% 4%56 ")} F>3). H' ) 8$( 4%56 "c A'Y% 5> .cpp ")TG )%-' A ) !)oG )>8 M8$( 4%56 A@% ( U ! A U" (J3 ra 5 B)Y ! " ()%H(. C ()' A U" 8$( 4%56 ()% )> ) )E ) ( "c ()C ()S " =) % A ) !)oG ), ! )>8 (29 ), ! 4%56 2%9 ! I%*(. ! U" 5J%M"c ), ! F A- (23 ! F%*" `' 5; 8$( R@ 5 "#" 4%56 Ac ,():% !%G " ()%H( AC I%9 & ") "#" 4%56 Ac Re 2 ( 5b'. /$( F>% ") d ! (2S ) !X 2@% Re B)Y ! !X 2@% A U" I9 (23 ! ()b "NG ), ! )>8 D K ! "#") Am( ), ! )>8 Ac (23 ! ), ! 4%56 B)#" I%*( F> % "5'&6 c F>3 4%56 I%9 & ") ,FS F+O Re _. 5; ()b "#" )>8 ) ), ! )>8 ()Y ! () : ! F> &3 Ac Re !L 2@% A U" ), ! )>8 (23 ! B)% B%C8 (2G ") d ! (2S )DD C 5>8 "Y ! F%*" >O 8$( "Y ! !)* _. 5; Am( I%*( =) % A U" R. &^ !. ?)% ), ! "Y ! "^ `' 5; 80 ++ 5> B)Y ! ()CM()+( 5> & &> ! )d ")3 ), ! G% R. &^ ! F> I 3 (2S ), ! 5 = H' ")i "c 8$( 5 = (29 8$( 4%56 2%9 ! I%*( F> H' Rg ()% )> ) ), ! )>8 ()> ) F%9 (23 ! ), ! 5 = B)#" )G' )%* (J% B)Y ! K8 "r( 4%56.

4.2.Tên file - ". 6: Q'Y 5'Y Am( (9 4%56 "#% 8> A$" ) ( (23 ! 8$( !. "

)5

"c ()C.

- ". 7: /$( 4%56 ")} F>3 ")3 8$( 5 = "c (9 "c &J ! :~(9 5 =• xA'Y% 8L 2$ ! . [. &^ ! ), ! B; (g )3G F> () : ! ()63 "r ! 8$( "#") ) (23 ! m0 !'1 . P B)% (9 "NG ), ! 5 = =) % R. &^ ! ()@ ! ) ( (23 ! 8$( !, " ) 5 M()+( 5> ();") )U= AC R. &^ ! ), ! Am" A%C8 >O ")3 F%*" Am( (9 "NG ), ! 4%56 ")} F>3. %-' >O Re !%7= ), ! "Y ! "^ 4%56 "d I A ) F 5 = 8$( "#") & &> !.

tDsD ), ! 5:% ")7 ();")(Comments) '% (a" 3: /k% 4%56 ")TG Ag ! 80 !'1 =) % "c 8$( (>% 5%*' (23 ! Ac "c ), ! 5:% ")7 ();") !% % ()%*' F- "#" ()Y ! (% "NG 4%56 F> $% &' ! "NG c. '% (ac 4: ( " "#" 4%56 ")} F>3 =) % IG3 !18 ()Y ! (% F- I '% (a" 5: ( " "#" 5:% !% % ();") =) % F%H( IK ! (%H ! € ). - ". 8: %H( 8$( F>% ")7 ();") 8Y ( (2 - ". 9: [. &^ ! •• ")3 5:% ")7 ();").

" 8k% )>8.

`'O- .

c 5> Rg " ()%H( ")3 8$( (>% 5%*' 80 !'1 D %-' >O A U" ")m( ")e F> & (S8D %*" ")Z A7 ! "#") ")3 ), ! (9 I%H M )>8 F> 5 = F> A7 ! "#") " ' (27" 80 ()S Re " ;( 5:% !% % ();") (23 ! A3J 80. )7 ‚ 2K ! ), ! 5:% !% % ();") (23 ! ), ! 4%56 ")} F>3 5> "c ‚ !)oG ")3 ! :% R. &^ ! ), ! 5 = M(23 ! B)% Ac ), ! 5:% !% % ();") (23 ! 4%56 ()% )> ) "c ‚ !)oG ")3 ), ! ! :% I 3 `' 5 =. ( " A3J 80 "NG ")7 ! (G =) % "c I `'O- 2w 2> !D H' ), ! A3J 80 A U" =)#( (2%C `'# 8$( ")' BS ), ! nfmM8k% f8 =) % Ia( A '. ), ! 5:% !% % ();") () : ! A- "+= ), ! F> ./$( 5:% !% % ();") ")%H 5 U" 8Y ( )>8 5> !S F> =) !S "NG A3J 80 A U" &g A ) AC 5>8 F> ), ! !S A U" ()GO ()H RG' A3J 80 >O./$( 5:% !% % ();") R#") 5 U" 8Y ( 8$( &ƒ ! Ad "NG 80 ), ! !S A U" &g A ) 5>8 F> ), ! !S A U" ()GO ()H M H' "c ()C , "'@% 8k% &ƒ ! >O. %H" ()GO , H' `'# )%-' 5:% ")7 ();") ) F+O Re 5>8 ")3 ), ! A3J 80 B)c AZ". @% F % 5; &3 >O ,"c 8$( A- ". 5> ")N OH' R. &^ ! ), ! 5:% !% % ();") ")%H 5 U" M(2P B)% "@ !% % ();") ), ! A3J 80 2 ( =)T" (J=. H' ) ), ! B; (g // ) ( `'# R. &^ ! ")3 ), ! 5:% !% % ();") MRG' Ac "c ()C R. &^ ! Rg BH( )U= /* */ AC 5>8 ), ! 5:% !% % ();") !3>% (3> I$ =) 80 (23 ! R'@( !%G% A3J =)#( (2%C F> !X 2@%. ; &^ 1: >% 5%*' "NG 4%56: // // // // // // // // // // // // // // // // // // // // // //

File: test.cc /Y ( : This is a test program Rev: A U" (J3: Thur. Oct 31, 1991, 12:30:14 #" !% : Erik Nyquist mail: [email protected] `'O- : Ellemtel Utvecklings AB 1991 BOX 1505 125 25 ALVSJO SWEDEN tel int + 46 8 727 3000 The copyright to the computer program(s) herein is the property of Ellemtel Utvecklings AB, Sweden. The program(s) may be used and/or copied only with the written permission of Ellemtel Utvecklings AB or in accordance with the terms and conditions stipulated in the agreement/contract under which the program(s) have been supplied.

; &^ 2:Q:% !% % ();") ")%H 5 U" F> R#") 5 U"(Strategic and Tactical Comments) // THE NEXT TWO LINES ARE STRATEGIC COMMENTS // This function does some complicated things. It works like this: // blah-blah-blah ... int insanelyGreatAndComplicatedFunction( int i ) { int index = i++ + ++i * i-- - --i; // THIS IS A TACTICAL COMMENT return index; }

4.4. ), ! 4%56 ")} F>3(Include files) '% (a" 6: /k% 4%56 ")} F>3 =) % ")TG 8$( "d ")H !f ")m (; ) I$% "NG "#" 4%56 ")} F>3 Ac. '% (a" 7: )63 ), ! 53J% A ) !)oG A U" R. &^ !q(23 ! 4%56 I%9 & ") F> 4%56 ")} F>3) M")7 ! =) % A U" ")} F>3 8$( "#") (#") I%*(: • ), ! 5 = A U" R. &^ ! ) ), ! 5 = "d RL. • ), ! 5 = A U" R. &^ ! ) ), ! I%H ()> ) F%9 . • ), ! 5 = _' ( )%* ) B%C' (2 F- )3m" ) 8$( B%C' A@% R@ (23 ! !'O9 8 ' )>8 )3m" )>8 ()> ) F%9 . • !'O9 8 ' )>8 ")3 )>8 )GO )>8 ()> ) F%9 R. &^ ! (23 ! )>8 ()> ) F%9 inline A U" A ) !)oG (23 ! 8$( 4%56. '% (a" 8: ), ! A ) !)oG "NG ), ! 5 = "#% 8> ")i A U" (2'O _' ( `'G "3 (2E (*) )GO ()G8 ")%H'(&) Re không A U" ")} F>3 (23 ! 4%56 ")} . '% (a" 9: ")i A ) ), ! ()T 5%9 `'G AH tên UNIX (23 ! ")i () #include '% (a" 10: /k% 4%56 ()% )> ) 5> IG3 !18 ), ! 4%56 5%9 `'G : • ), ! B)G% I#3 "NG ), ! B%C' F> ), ! )>8 R. &^ ! (23 ! ), ! )>8 A U" ()g" ()% (23 ! 4%56. • ), ! B)G% I#3 "NG ), ! I%H F> "NG ), ! )>8 ()> ) F%9 R. &^ ! (23 ! ), ! )>8 A U" ()g" ()% (23 ! 4%56.

- ". 10: [. &^ ! ")i () #include ” filename.h ”")3 ), ! 4%56 ")} F>3.

- ". 11: [. &^ ! ")i () #include < filename.hh >")3 ), ! 4%56 (23 ! () F%* . - ". 12: P ! IG3 !%: ")} 4%56 B)#" (23 ! file “.cpp” -/$( "#") & ) ( AC B)Y ! I 5m= 5J% "#" 4%56 ")} F>3 ()S &r ! B)@% # ifndef #define F>3 A ' "NG 4%56 F> #endif "'@% 4%56. -[@ 4%56 ")} F>3 9 )EM H' ) 8$( 4%56 A U" ")} F>3 (23 ! 8$( % "5'&6 4%56M RG' Ac (23 ! 8k% 4%56 ()% )> ) A G F>3 ), ! 4%56 ")} 5 ()T )G% F> c Re I%9 & ") 5J% 8k% B)% 4%56 A ' (%9 I ()GO AV%. /$( Rg ()GO AV% Ad !% (23 ! 8$( 4%56 "c ()C 5>8 c " ()%H( AC I%9 & ") 5J% 8$( R@ 4%56 5 )d . - H' 8$( file ")i ")TG ), ! ()Y ! (% ")i " ")3 ")3 4%56 I%9 & ") ()S B)Y ! 9 A G F>3 I ( "T 4%56 ")} >3. -<) I%*( Rg B)#" )G' !%,G ), ! ")i () ")} F>3 5> "NG ! :% &r ! (g A ) !)oG )GO 5 O (P () F%* D H' (9 4%56 ")} F>3 K8 !%,G )G% & ' “< “ F>” >” ()S I$ (%- _. 5; Re B)Y ! (S8 () O 4%56 >O (23 ! () 8^" 8m" A ) . %-' >O Re & AH 8@% !'O )%C8 B)Y ! I#3 (2 " A U" 5> Rg _' ! A$( 5 )G' !%,G (9 &3 ! :% &r ! A ) !)oG F> (9 (23 ! () F%* ")} F>3. - K ! F%*" B)G% I#3 ")'k% )K ! "^" I$M(2S ) I%9 & ") (2L 9 nhanh hdn. %-' >O "c 5e & &> ! _#" A ) =)%9 I "NG ") d ! (2S ) A U" R. &^ !. )'k% =) % Ia( A ' IL% B; (g “@(#) ”( ; &^ 5) ; &^ 3:?„ ()'+( !f ")m Rg (2r ! (9 "NG ), ! 4%56 ")} F>3: #ifndef FOO_HH #define FOO_HH // )7 ‚ "'@% 4%56 =) % "c #endif ; &^ 4: P ! IG3 !%: R. &^ ! A : ! & //Không A- ". F> B)Y ! 9 ()g" )%* :

('O*( A@% ) :

#include <../include/fnutt.h> #include <sys/socket.h> ; &^ 5 :/$( )K ! ")'k% "^" I$ AC )+ 2G 4%56 ()% )> ) static const char* sccsid = "@(#) Exception.cpp, rev. A, Copyright Ellemtel Utvecklings AB 1991"; ; &^ 6: {%56 ")} F>3 ")3 5 = PackableString: // file: PackableString.h #ifndef PACKABLESTRING_H #define PACKABLESTRING_H #include "String.h"

#include "Packable.h" // It is not necessary to extern-declare class Buffer when // each pointer declaration specifies the keyword class as shown below. // An explicit extern-declaration makes the code easier to // understand. extern class Buffer; class PackableString : public String, public Packable { public: PackableString( const String& s ); class Buffer* put( class Buffer* outbuffer ); // ... }; #endif ; &^ 7:{%56 ()% )> ) ")3 5 = PackableString : // PackableString.cpp #include "PackableString.h" // To be able to use Buffer-instances, Buffer.h MUST be included. #include "Buffer.h" Buffer* PackableString::put( Buffer* outbuffer ) { // ... }

…D # (9 : '% (a" 10: P A ) &G ) ")3 ), ! 5 = (3> "^"M B%C' 5%*( B9M B%C' A ) !)oGM)>8 M)K ! F> ), ! I%H (23 ! 8$( () F%* 5 = (%- (@ Ac 5> unique ")3 () F%* . '% (a" 11: 9 "NG ), ! I%H M ), ! )K !M ), ! )>8 A U" Ia( A ' F % 8$( "), "#% () : !.

'% (a" 12: 9 "NG ), ! B%C' &, 5%*' (2P' ( U ! M ), ! " ' (27"MB%C' A ) !)oGMB%C' 5%*( B9 A U" Ia( A ' F % "), "#% hoa. '% (a" 13: 23 ! ), ! (9 )%-' )d 8$( (P M ), ! (P A U" F%H( 5%- )G' F> 8k% (P =) % Ia( A ' F % 8$( "), "#% F%H( )3G. '% (a" 14: Không A U" R. &^ ! (P A ) &G ) F % 8$( )GO )G% A : ! !J") & %(‘_’ hay ’__’). '% (a" 15: /$( (9 (#") I%*( F % (%- (@ "NG c 5> 8$( & ' !J") & %(‘_’). '% (a" 16: /$( (9 Ia( A ' F % 8$( "), "#% )3G A U" _' ( )%* !GO RG' (%- (@ "NG c. '% (a" 17: /$( (9 Ia( A ' F % 8$( "), "#% () : ! (#") IJ") F % (%- (@ "NG c IL% & '(‘_’). - ". 13: ?)Y ! A U" R. &^ ! ), ! B%C' (9 8> ")i "c B)#" )G' F- ), ! "), )3G F> "), () : !. - ". 14: 9 B)Y ! 9 IG3 !18 ), ! "), F%H( (Ga( 8> B)Y ! A U" ") = )+ chung. - ". 15: )Z (9

), ! I%H 8> "c (; ) ") ( !U% ‚ R. &^ !.

- ". 16: c% !Z ), ! I%H (3> "^" F> ), ! )K ! MB%C' 5%*( B9MB%C' A ) !)oG (23 ! 8$( 5 =.

23 ! ") d ! >O M ()+( 5> `'G (2Z ! AC =)b I%*( !%,G ), ! (P A ) &G ) F> ), ! (9 . 9 5> 8$( =) "NG (P A ) &G ) "#% 8> I%C' () !)oG "NG c./$( (P A ) &G ) IG3 !18 8$( (%(@M8$( (9 F> 8$( )+' (@q()63 ()T (g). %- (@ F> )+' (@ 5> (rO ")Z ./$( )+' (@ ")i A U" R. &^ ! bL% "Y ! "^ 80 xx (V ! `'#( MAC (2# ) _' ! A$( !%,G F % ), ! 80 xx &3 ! :% R. &^ ! F%H(. [. &^ ! )G% & ' !J") & % (‘__’) (23 ! (P A ) &G ) A U" &> ) 2%9 ! I9 (23 ! I%9 & ") R. &^ ! ()63 ANSI- ")'† . ), ! & ' !J") & % (‘_’) () : ! A U" R. &^ ! (23 ! ), ! (9 "NG ), ! )>8 () F%* q ) 5> “_main” F>”_exit”)D C (2# ) Rg _' ! A$( MB)Y ! A U" Ia( A ' (P A ) &G ) F % 8$( & ' !J"). /$( `'% (a" "); ) OH' 5> Am( 8$( (9 8> không A U" _#" A ) 2w 2> ! 5> 8$( "#") Am( (9 (1% (*./$( "#% (9 &>% ()Y ! () : ! (@( )d (9 !a M(9 B)c )%C'MRg "a( _‡ "h ! 5> F A- " =) % _68 _‡(. ), ! "), F%H( (a( "c ()C 5'Y 5'Y !bO Rg )%C' 5 8. ), ! I%H (3> "^",n), ! )>8 M ), ! )K ! =) % 5> 8$( "#% (9 AN &>% AC (2# ) Rg _' ! A$( ) ! B)Y ! `'# &>%. c 2 ( )%-' 5 = "c ()C (+ &^ ! (23 ! () F%* F> !% R. (23 ! 8$( =23ˆ6"( "c )> ! !> 5 = M&3 F+O ()+( 5> `'G (2Z ! AC Am( (9 AC (2# ) Rg _' ! A$( _ O 2G./$( "#") AC !f ")m Rg _' ! A$( 5> =) % "c 8$( `'% (a" !)%98 B)a" ")3 F%*" !# (9 A@% F % ), ! A@% ( U ! (3> "^" "c ()C () O A U". )63 "#") >O ), ! 5 = (P (23 ! () F%* "c ()C A U" R. &^ ! "r ! 8$( 57".

9 "NG ), ! B%C' RG' AbO =) % "c (%- (@: • 9 B%C'(classes, typedefs, enums, structs, unions, etc). • ), ! )K ! F> ), ! I%H (3> "^". • ), ! (9 )>8qB)Y ! 5> "#" )>8 ()> ) F%9 ) • #" ")i () (#define) ), ! I%H (o ) (23 ! 8$( 5 = 9 A U" R. &^ ! ()GO FS ), ! )K ! MI%H (3> "^" MB%C' &, 5%*' 5%*( B9 F> A ) !)oG. ; &^ 8: )Z (9 : int groupID; // instead of grpID int nameLength; // instead of namLn PrinterStatus resetPrinter; // instead of rstprt ; &^ 9: ), ! (9 8d )1: void termProcess(); // Terminate process or // terminal process? ; &^ 10: 9 F % ), ! B; (g R@ "c ()C 5> !'O9 )b 5k% FS B)c A ) F : int I0 = 13; // Names with digits can be int IO = I0; // difficult to read.

; &^ 11: ) !)oG 5 = (23 ! 5 = () F%* : class Emc2Class { public: Emc2Class(); // Default constructor // ... private: int id; // ... };

; &^ 12:/$( "#") AC (2# ) "#" )>8 F> "#" 5 = (3> "^": // )GO FS B)G% I#3: void Emc2_myFunc1(); void Emc2_myFunc2(); class Emc2MyClass { /* ... */ }; // c% !Z ), ! )>8 R. &^ ! 5 = (2P' ( U !: class Emc2

{ public: static void myFunc1(); static void myFunc2(); class MyClass { /* ... */ }; private: virtual dummy() = 0; // Trick to make the class abstract }; // Now, functions and classes may be accessed by using the scope-operator: Emc2::myFunc1(); Emc2::myFunc2(); Emc2::MyClass myObject;

‰D<)3 ! "#")(Style) 6.1.Nh, ! 5 =(Classes)

'% (a" 18: ), ! ()> ) ph n protected ,public MF> private (23 ! 8$( "5GRR A U" B)G% I#3 ()63 ()T (g AcqA ' (%9 5> public AH protected F> "'@% "r ! 5> private). '% (a" 19: Không 8$( )>8 ()> ) F%9 >3 A U" A ) !)oG (23 ! 8$( 5 =. %*" Am( B)G% I#3 public A ' (%9 M8Z% ()T `'G (b8 IL% ! :% &r ! A U" (+= )U= (23 ! A%C8 Ia( A ' "NG F%*" B)G% I#3 5 =. <) protected "c 5e "h ! A U" `'G (b8 IL% ! :% ()%H( BH B)% _68 _‡( (; ) BH ()PG "NG 8$( 5 =D<) private ")TG ), ! ")% (%H( () : ! ;( `'G (b8 )d . ), ! )>8 ()> ) F%9 A U" A ) !)oG (23 ! 8$( 5 = (g A$ ! (2L ()> ) )>8 inline DQ:% A ) !)oG 5 = 5> B‡8 ")m( ")e F> !m= )%-' B)c B)f AC AZ" B)% A ) !)oG ")7 ! (23 ! Ac. > ! U" 5J% B)% B)G% I#3 ), ! L !3>% A ) !)oG 5 = ()S c Re (2L ()> ) ), ! )>8 ()Y ! () : !. ; &^ 12:/$( A ) !)oG 5 = ()63 `'% (a" "NG =)3 ! "#") : class String : private Object { public: String(); // Default constructor String( const String& s ); // Copy constructor

unsigned length() const; // ... protected: int checkIndex( unsigned index ) const; // ... private: unsigned noOfChars; // ... }; ; &^ 13:?)Y ! A ) !)oG )>8 ()> ) F%9 (23 ! B)G% I#3 5 =: // )GO FS F%H( ) RG': class String { public: int length() const // KHÔNG !! { return len; } // ... private: int len; }; // 9 B)G% I#3 ) RG': class String { public: int length() const; // ... private: int len; }; inline int String::length() const { return len; }

6.2. ), ! )>m(Functions) - ". 17:

Kh% B)G% I#3 8$( )>8 ()S & ' !3m" A ' (%9 F> A@% R@ A ' (%9 q H' "c) =) % A U" F%H( (29 "r ! 8$( &ƒ ! F % (9 )>8. H' B)3 ! (2@ ! ")3 =)‡= ()S & ' !3m" Ac ! F> "#" A@% R@ B)#" "h ! "r ! 8$( &ƒ !. #") B)#" 8k% A@% R@ A U" F%H( 8$( &ƒ !. - ". 18: 23 ! A ) !)oG )>8 ()S B%C' (2 F- =) % =) % F%H( L 8$( &ƒ ! "#") I%*(. - ". 19: Q'Y 5'Y F%H( & ' !3m" I9 (2#% !GO RG' (9 )>8. ; &^ 14:W ' !3m" (2#% 5'Y 5'Y F%H( !GO RG' (9 )>8: Void foo (); // ? Š ‹!! void fooqŒ• •• Ž ! ; &^ 15: #") B)G% I#3 A7 ! F> RG% ), ! A@% R@ (23 ! A ) !)oG )>8: // 7 !: int myComplicatedFunction( unsigned unsignedValue, int intValue, char* charPointerValue, int* intPointerValue, myClass* myClassPointerValue, unsigned* unsignedPointerValue ); // SAI: int myComplicatedFunction( unsigned unsignedValue, int intValue, char* charPointerValue, int* intPointerValue, myClass* myClassPointerValue, unsigned* unsignedPointerValue );

6.3D?)@% 5* ) A%-' B)%C : - ". 20: ), ! B)@% 5* ) A%-' B)%C ) if , else , for , while ,do… 9 A U" ()63 RG' IL% 8$( ! " !GO " B)% ")7 ! (2@ !. ?)% 8> B)Y ! "c 8$( B)@% ()S (G "c ()C & &> ! Am( RG' c 8$( & ' ") 8 =)†O F> A%-' >O Re & Rg )%C' 5 8 B)% AZ" 80 F> "c ()C & AH ") d ! (2S ) I RG% 8> (G B)c () O A U".

; &^ 16:

' (27" B)@% 5* ) B)% B)Y ! "c 5* ) I9 (23 !:

// No block at all - No! while ( /* Something */ ); // Empty block - better! while ( /* Something */ )

AH

{ // Empty ! }

6.4. 3 (2E F> ()G8 ")%H': - ". 21: 3# (. (2E (*) F> (3# (. A G ")i (&) 9 Am( !GO RG' B%C' (9 (23 ! B)G% I#3 F> A ) !)oG. #" B; (g ‘ * ’ F> ‘ & ’ 9 Am( !GO RG' B%C' "NG I%H ()GO FS RG' (9 I%H AC ) 8J ) 2K ! ")7 ! 5> =) "NG B%C' A ) !)oGD )GO FS B)G% I#3 2K ! *i 5> B%C' int ()S B)G% I#3 int*. 23 ! ), ! "b' B)G% I#3 B%C' "NG I%H ()S =) % B)G% I#3 (3# (. (23 ! !GO RG' (9 I%H AC 5>8 !% 8 _#" R' ( 5k%. ; &^ 16: ?)G% I#3 F % ‘ & ’ F> ‘ * ’ : char* Object::asString() { // Something }; char* userName = 0; int sfBook = 42;int& anIntRef = sfBook; ; &^ 17:?)G% I#3 F>% I%H (23 ! "b' 5* ) "c ( * ): ••?)Y ! 9 B)G% I#3 char* i,j; // i is declared pointer to char, while j is declared char

7.L p(Class) 7.1/ Quy-n Truy C+p ( Right Access) '% (a" 20:

- Không bao gi: dùng identifier public hay protected cho các d, li*u thành ph n ( member data) trong m$t l p. - Vi*c s. d^ng biHn toàn c^c (public variable) không A Uc khuyHnh khích b:i vì nh,ng lí do sau Aây: 1. Vi*c s. d^ng biHn toàn c^c se vi phJm m$t trong nh,ng nguyên tac cd b n cNa l+p trình h ng A@i t Ung – Aó là tính bao Aóng ( encapsulation). Ví d^, nHu có m$t l p có kiCu là BankAccount, trong Aó account_balance là m$t biHn toàn c^c ( public variable), thì giá tr cNa biHn này có thC b thay AVi bLi b t cT sg truy c+p nào tP bên ngoài. Tuy nhiên, nHu biHn A Uc khai bò là private, giá tr cNa nó chi có thC b thay AVi bLi nh,ng hàm thành ph n trong l p Aó 2. B t cT hàm nào trong m$t ch dng trình hng có thC thay AVi giá tr cNa public data. Vi*c này có thê gây ra nh,ng lki mà ta khó có thC xác A nh A Uc. 3. Khi mà m$t public data không A Uc s. d^ng, thì vi*c thay AVi d, li*u cNa biHn này se không làm cho các class s. d^ng class này ph i thay AVi lJi code cNa mình. Tóm lJi thì ta nên hi*n thgc m$t l p sao cho mZi sg thay AVi trong sg hi*n thgc cNa l p này se không làm thay AVi nh,ng l p s. d^ng nó. Vi*c s. d^ng nh,ng biHn protected trong m$t class chng không nên A Uc khuyHn khích, bLi vì nh,ng biHn protected này se trL nên visible A@i v i nh,ng l p d n xu t ( derived class) cNa nó. Tên cNa kiCu ( type) và biHn ( variable) trong l p cd sL ( base class) không nên thay AVi bLi vì nh,ng l p d n xu t ( derived class) có thC ph^ thu$c vào chúng. NHu trong m$ tr :ng hUp nào Aó, l p d n xu t truy xu t AHn data trong l p cd sL ( base class), m$t gi i pháp là viHt m$t hàm protected trong base class tr v- nh,ng private data trong base class. HJn chH s. d^ng struct bLi vì nó chi chTa public data. ; &^ 18:D i Aây là cách AC Aóng gói d, li*u ( encapsulate) sao cho có thê thay AVi nó sau này // Original class: class Symbol {}; class OldSymbol : public Symbol {}; class Priority { public: // returns pd int priority(); // returns symbol class Symbol* getSymbol() const; // ... private: int pd; OldSymbol symbol; };

// L p A Uc chinh s.a:

// L+p trình viên chZn thay AVi private data tP kiCu nguyên sang enum. M$t user cNa class ‘Priority’ không ph i thay AVi code, bLi vì giá tr tr v- enum tP hàm thành ph n ( member function) priority()A Uc tg A$ng chuyCn sang kiCu nguyên. class Symbol {}; class NewSymbol : public Symbol {}; enum Priority { low, high, urgent }; class Priority { public: // Interface intact through implicit cast, returns priority_data Priority priority(); // Interface intact, object of new subclass to symbol returned class Symbol* getSymbol() const; // ... private: Priority priority_data; // New representation/name of internal data NewSymbol symbol; };

7.2.Hàm Inline : - ". 21: Access functions nên là inline. - ". 22: Nh,ng hàm chuyCn tiHp nên inline. - ". 23: Constructor và destructor không nên là inline. Lý do AC khai báo m$t hàm là inline là AC tfng t@c A$ thgc thi cNa nó. Nh,ng hàm nhE, chnng hJn nh access function, tr v- giá tr cNa m$t thành ph n ( member) cNa m$t class và nh,ng hàm forwarding se thgc thi m$t hàm khác ( chng là hàm inline). Vi*c s. d^ng hàm inline Aúng chk se d n AHn vi*c gi m kích th c cNa code. Chú ý: - Nh,ng hàm mà gZi hàm inline khác thì se trL nên phTc tJp cho trình biên d ch trong vi*c làm cho chúng inline, mmc dù nh,ng hàm này chi là nh,ng hàm nhE. - ây là v n A- th :ng hay gmp A@i v i constructor và destructor. M$t constructor luôn luôn gZi thgc thi m$t constructor cNa l p cd sL ( base class) và nh,ng d, li*u thành ph n ( member data) tr c khi thgc thi code cNa nó. Nên tránh inline constructor và destructor.

7.3 Friends: - Friends cNa m$t class nên cung c p thêm nh,ng hàm mà A Uc gi, L ngoài class. - Nh,ng operation trên m$t class Aôi lúc A Uc cung c p bLi m$t t+p hUp cNa class và hàm. - M$t friend không ph i là m$t member cNa m$t class và A Uc phép truy c+p AHn nonpublic members cNa class. Friends cung c p m$t cách AC có thC “Ai ngõ sau” A@i v i sg bao Aóng d, li*u ( data encapsulation) cNa m$t class. M$t friend class A Uc s. d^ng AC cung c p hàm yêu c u d, li*u hdn là nh,ng hàm c n thiHt bLi class nh thông th :ng. Gi s. có m$t class list c n m$t con trE ( pointer) AC duy*t t t c các element cNa list. Con trE này thi không c n thiHt cho các operation khác trên list. Trong m$t vài tr :ng hUp, chnng hJn nh c n tìm ph n t. nhE nh t cNa list, thì thay vì tJo m$t iteratE, chúng ta chTa con trE trE AHn các element cNa list. M$t v n A- v i gi i pháp này là class iterator không thC truy xu t AHn c u trúc d, li*u A Uc s. d^ng AC represent list ( bLi vì chúng ta Aã khuyHnh khích dùng private date). BKng cách khai báo iterator class nh là m$t friend class, v n A- này có thC A Uc gi i quyHt mà không có vi phJm tính bao Aóng cNa d, li*u ( data encapsulation). S. d^ng friend thì t@t nHu A Uc s. d^ng Aúng lúc.

7.4 Hàm hKng thành viên: '% (a" 21: - M$t hàm thành ph n mà không thay AVi biHn cNa m$t object thì A Uc khai báo là const. '% (a" 22: - NHu hành A$ng cNa m$t object ph^ thu$c vào data bên ngoài objct thì data này không nên A Uc chinh s.a ( modified) bLi hàm thành ph n const. - Hàm thành ph n ( member function) A Uc khai báo là const không A Uc chinh s.a nh,ng d, li*u thành ph n và chi nh,ng hàm A Uc gZi trên nh,ng A@i t Ung hKng ( const object). ( Nh,ng object nh v+y coi nh vô d^ng ( unusable ) nHu không có const method. Vi*c khai báo const A m b o cho object không b chinh s.a ( modified). M$t thu+n lUi l n A Uc cung c p bLi C++ là kh nfng overload function A@i v i “tính ch t hang” ( const-ness) cNa chúng. ( Hai hàm thành ph n có thC có cùng tên , trong Aó m$t hàm là const và hàm còn lJi thì không). - HoJt A$ng cNa m$t object có thC b nh h Lng bLi d, li*u bên ngoài object. Nh,ng d, li*u nh v+y không nên A Uc chinh s.a bLi m$t const member function.

Ví d^ 19: const-declared access functions to internal data in a class : class SpecialAccount : public Account { public:

int insertMoney(); // int getAmountOfMoney(); No! Forbids ANY constant object to // access the amount of money. int getAmountOfMoney() const; // Better! // ... private: int moneyAmount; }; Ví d^ 20: Overloading an operator/function with respect to const-ness #include #include <string.h> static unsigned const cSize = 1024; class InternalData {}; class Buffer { public: Buffer( char* cp ); // Inline functions in this class are written compactly so the example // may fit on one page. THIS is NOT to be done in practice // A. non-const member functions: result is an lvalue char& operator[]( unsigned index ) { return buffer[index]; } InternalData& get() { return data; } // B. const member functions: result is not an lvalue char operator[]( unsigned index ) const { return buffer[index]; } const InternalData& get() const { return data; } private: char buffer[cSize]; InternalData data; }; inline Buffer::Buffer( char* cp ) { strncpy( buffer , cp , sizeof( buffer ) ); } main() { const Buffer cfoo = "peter";// This is a constant buffer Buffer foo = "mary";// This buffer can change

foo[2]='c';// calls char& Buffer::operator[](unsigned) cfoo[2] = 'c' // ERROR: cfoo[2] is not an lvalue. // cfoo[2] means that Buffer::operator[](unsigned) const is called. cout << cfoo[2] << ":" << foo[2] << endl; // OK! Only rvalues are needed foo.get() = cfoo.get(); cfoo.get() = foo.get(); // ERROR: cfoo.get() is not an lvalue }

7.5 Constructor và Destructor: '% (a" 23: - M$t class mà s. d^ng “new” AC c p phát m$t thgc thC (instance) A Uc qu n lý bLi class, ph i A nh nghoa m$t constructor. '% (a" 24: - T t c các class A Uc s. d^ng nh m$t base-class ( có hàm o – virtual machine), ph i A nh nghoa m$t virtual destructor. - ". 24: - Tránh s. d^ng A@i t Ung toàn c^c ( global object) trong constructor và destructor. - M$t copy cNa constructor A Uc khuyHn khích AC tr :ng hUp m$t object A Uc khLi tJo s. d^ng m$t object cùng kiCu. NHu m$t object qu n lý sg c p phát ( allocation) và hu• ( deallocation) m$t object trên vùng heap (A@i t Ung qu n lý s. d^ng m$t con trE trE AHn object A Uc tJo bLi constructor cNa class), chi nh,ng giá tr cNa con trE se A Uc copy. i-u này có thC d n AHn sg hai invocation cNa destructor cho cùng m$t object ( trên vùng heap), se d n AHn run-time error. - V n A- t dng tg x y ra A@i v i toán t. gán (“=”) - NHu m$t class, có m$t hàm o nh ng không có destructor o, A Uc s. d^ng, there may be a surprise if nh,ng con trE trE AHn class A Uc s. d^ng. NHu m$t con trE nh v+y A Uc gán cho m$t thgc thC (instance) cNa m$t l p d n xu t và nHu delete A Uc s. d^ng trên object này, chi destructor cNa base class A Uc thgc thi. NHu ch dng trình ph^ thu$c vào sg thgc thi destructor cNa l p d n xu t, ch dng trình se fail. - Liên quan AHn sg khLi tJo cNa nh,ng object A Uc c p ph t tonh ( statically allocated object), không có gì chac chan rKng nh,ng A@i t Ung tonh (static object) khác se A Uc khLi tJo ( ví d^, global object). BLi vì thT tg khLi tJo cNa object tonh ( cái mà A Uc A nh nghoa trong nh,ng Adn v biên d ch khác nhau), thì không A Uc A nh nghoa trong A nh nghoa cNa ngôn ng,. - BJn ph i biHt nh,ng gì bJn Aang làm nHu bJn gZi m$t hàm o tP m$t constructor trong m$t class. NHu m$t hàm o trong m$t l p d n xu t A Uc overridden, A nh nghoa ban A u (original definition) trong base class se v n A Uc thgc thi bLi constructor cNa base class. Override, then, không luôn luôn work khi gZi hàm o trong constructor . Xem VD 30. NgoJi l* A@i vLi Rule 24:

-

ôi khi chúng ta mu@n nh,ng object trong m$t class chia se dg li*u. Trong tr :ng hUp nh v+y, không c n thiHt ph i A nh nghoa m$t copy constructor.

Ví d^ 21:M$t A nh nghoa l p “nguy hiCm” không có m$t copy contructor : #include <string.h> class String { public: String( const char* cp = ""); // Constructor ~String(); // Destructor // ... private: char* sp; // ... }; String::String(const char* cp) : sp( new char[strlen(cp)] ) { strcpy(sp,cp); } String::~String() // Destructor { delete sp; }

// Constructor

// "Dangerous" String class void main() { String w1; String w2 = w1; // WARNING: IN A BITWISE COPY OF w1::sp, // THE DESTRUCTOR FOR W1::SP WILL BE CALLED TWICE: // FIRST, WHEN w1 IS DESTROYED; AGAIN, WHEN w2 IS DESTROYED. }

Ví d^ 22:L p “an toàn” có copy contructor và contructor mmc A nh : #include <string.h> class String

{ public: String( const char* cp = ""); // Constructor String( const String& sp ); // Copy constructor ~String(); // Destructor // ... private: char* sp; // ... }; String::String( const char* cp ) : sp( new char[strlen(cp)] ) // Constructor { strcpy(sp,cp); } String::String( const String& stringA ) : sp( new char[strlen(stringA.sp)] ) { strcpy(sp,stringA.sp); } String::~String() // Destructor { delete sp; } // "Safe" String class void main() { String w1; String w2 = w1; // SAFE COPY: String::String( const String& ) CALLED. }

Ví d^ 23:

nh nghoa l p không có virtual destructors :

class Fruit { public: ~Fruit(); // ... };

// Forgot to make destructor virtual!!

class Apple : public Fruit { public: ~Apple(); // Destructor

// ... }; // "Dangerous" usage of pointer to base class class FruitBasket { public: FruitBasket(); // Create FruitBasket ~FruitBasket();// Delete all fruits// ... void add(Fruit*); // Add instance allocated on the free store // ... private: Fruit* storage[42]; // Max 42 fruits stored int numberOfStoredFruits; }; void FruitBasket::add(Fruit* fp) { // Store pointer to fruit storage[numberOfStoredFruits++] = fp; } FruitBasket::FruitBasket() : numberOfStoredFruits(0) { } FruitBasket::~FruitBasket() { while (numberOfStoredFruits > 0) { delete storage[--numberOfStoredFruits]; // Only Fruit::~Fruit is called !! } }

Ví d^ 24:M$t cách b o A m rKng m$t A@i t Ung toàn c^c A Uc khLi tJo : // WARNING!!! Mã này không cho ng

ib t

u h c !!!

// PortSetup.hh class PortSetup { public: PortSetup();// Constructor: initializes flag void foo();// Only works correctly if flag is 42 private: int flag;// Always initialized to 42 }; extern PortSetup portSetup; // Must be initialized before use // Create one instance of portSetupInit in each translation unit // The constructor for portSetupInit will be called once for each // translation unit. It initializes portSetup by using the placement // syntax for the "new" operator. static class PortSetupInit { public: PortSetupInit(); // Default constructor private: static int isPortSetup; } portSetupInit; // PortSetup.cc #include "PortSetup.hh" #include // ... PortSetupInit::PortSetupInit() // Default constructor { if (!isPortSetup) { new (&portSetup) PortSetup; isPortSetup = 1; } }

Ví d^ 25 : Override of virtual functions does not work in the base class' constructors

class Base { public: Base(); // Default constructor virtual void foo() { cout << "Base::foo" << endl; } // ... }; Base::Base() { foo(); // Base::foo() is ALWAYS called. } // Derived class overrides foo() class Derived : public Base { public: virtual void foo() { cout << "Derived::foo" << endl; } //foo is overridden // ... }; main() { Derived d; // Base::foo() called when the Base-part of // Derived is constructed. }

7.6 Toán t. gán: '% (a" 25: - M$t class s. d^ng “new” AC c p phát m$t thgc thC AgUc qu n lý bLi class, ph i A nh nghoa toán t. gán. '% (a" 26: - M$t toán t. gán thgc hi*n m$t destructive action ph i A Uc b o A m là không có thgc hi*n destructive trên object mà nó Aang tác A$ng. - ". 25: - M$t toán t. gán ph i tr v- tham chiHu hKng ( const reference) AHn A@i t Ung gán (assigning object). - Toán t. gán không A Uc kH thPa nh nh,ng toán t. khác. NHu toán t. gán không A Uc A nh nghoa m$t cách t :ng minh (explicitly), thì m$t toán t. gán khác se A Uc tg A$ng A nh nghoa. Nh,ng toán t. gán nh v+t không thgc hi*n bit-wise copy d, li*u thành ph n; thay vào Aó, toán t. gán (A Uc A nh nghoa) cho mki kiCu d, li*u thành ph n A Uc gZi. Bit-wise copying chi A Uc thgc hi*n A@i v i d, li*u thành ph n có kiCu d, li*u nguyên thu• ( primitive).

- M$t h* qu cNa vi*c này là bit-wise copying A Uc thgc hi*n A@i v i d, li*u thành ph n có kiCu con trE. Vi*c này se d n AHn m$t v n A-: homc là gZi destructor cho A@i t Ung A Uc qu n lý nhi-u l n homc là c@ gang s. d^ng A@i t Ung Aã A Uc hu• ( deallocated object). See Rule 25. - NHu m$t toán t. gán A Uc overload, l+p trình viên ph i A m b o rKng l p cd sL và toán t. gán cNa member chJy. - M$t lki th :ng gmp là gán m$t object cho chính nó. Bình th :ng, destructor m$t thgc thC cái mà A Uc c p phát trên vùng nh heap A Uc gZi tr c khi vi*c gán A Uc thgc thi. NHu m$t object A Uc gán cho chính nó, giá tr cNa biHn thgc thC se b m t bLi vì nó A Uc gán. Vi*c này se dãn AHn run-time errors. If a =a A Uc dò ra, A@i t Ung A Uc gán không thay AVi.

Ví d^ 26: Giá tr tr v- Aúng và không Aúng tP toán t. gán: void MySpecialClass::operator=( const MySpecialClass& msp );

/ Well ...?

MySpecialClass& MySpecialClass::operator=( const MySpecialClass& msp );

// No!

const MySpecialClass& MySpecialClass::operator=( const MySpecialClass& msp );

// Recommended

Ví d^ 27: Definition of a class with an overloaded assignment operator class DangerousBlob { public: const DangerousBlob& operator=( const DangerousBlob& dbr ); // ... private: char* cp; }; // Definition of assignment operator const DangerousBlob& DangerousBlob::operator=( const DangerousBlob& dbr ) { if ( this != &dbr ) // Guard against assigning to the "this" pointer { delete cp; // Disastrous if this == &dbr } // ... }

7.7 Quá t i toán t. - ". 26: - Khi hai toán t. là ng Uc nhau ( ví d^ nh == va !=) thì nên A nh nghoa c hai. - Operator Overloading có mmt thu+n lUi l n b t lUi. M$t thu+n lUi là code s. d^ng class có overloaded operators se d AZc hdn. M$t thu+n lUi khác là ng, nghoa ( semantic) thì Adn gi n và tg nhiên. M$t b t lUi là d b hiCu nh m ý nghoa cNa overloaded operator ( nHu l+p trình viên không s. d^ng nghoa thông th :ng). Ví d^ nh toán t. c$ng thì A Uc A nh nghoa lJi v i ý nghoa là trP và toán t. trP A Uc A nh nghoa lJi v i nghoa là c$ng . - nh nghoa m$t th vi*n class thì gi@ng nh vi*c A nh nghoa m$t ngôn ng,. NHu s. d^ng operator overloading, s. d^ng nó theo l@i hiCu thông th :ng, không s. d^ng nó nHu vi*c này có thC d n AHn hiCu l m.

7.8 Hàm thành ph n tr và kiCu tr v-: '% (a" 27: - M$t public member function không nên tr v- m$t non-const reference homc con trE AHn d, li*u thành ph n. '% (a" 28: - M$t pubic member function không tr lJi m$t non-const reference homc m$t con trE AHn d, li*u bên ngoài cNa object ngoJi trP tr :ng hUp object chia s• d, li*u v i nh,ng A@i t Ung khác. - BKng cách cho phép truy su t trgc tiHp AHn m$t private member data cNa m$t object tP bên ngoài, d, li*u này có thC b thay AVi theo cách mà không Aúng v i ý A nh thiHt kH class cNa ng :i thiHt kH. Vi*c này làm gi m sg tin c+y cNa designer’s code. - M$t tr :ng hUp nguy hiCm n,a là s. d^ng nh,ng con trE trE AHn vùng nh Aã b hu• . Rule 29 và 30 se tránh tr :ng hUp này.

Ví d^ 28: Png bao gi: tr v- m$t tham chiHu không ph i là hKng AHn d, li*u thành viên tP hàm public: class Account { public: Account( int myMoney ) : moneyAmount( myMoney ) {}; const int& getSafeMoney() const { return moneyAmount; } int& getRiskyMoney() const { return moneyAmount; } // ... private: int moneyAmount; };

// No!

Account myAcc(10); // I'm a poor lonesome programmer a long way from home myAcc.getSafeMoney() += 1000000; // Compilation error: assignment to constant myAcc.getRiskyMoney() += 1000000; // myAcc::moneyAmount = 1000010 !!

7.9 KH thPa - ". 27: - Tránh sg thPa kH cho quan h* parts-of ( cái này chi là thành ph n cNa cái kia). - ". 28: - Chi nên cho phép l p d n xu t truy xu t AHn d, li*u cNa l p cd sL bKng cách khai báo protected access function. - M$t lki th :ng gmp n,a là s. d^ng nhi-u l n sg kH thPa cho quan h* parts-of ( khi m$t object chTa m$t vài object khác, nh,ng object này A Uc kH thPa thay vì s. d^ng nh,ng biHn thành ph n. i-u này có thC d n AHn m$t c u trúc class lJ mat và code thì không có kh chuyCn ( flexible) . Trong C++, có thC có m$t s@ l Ung b t k‘ cNa s@ l Ung thgc thC cNa m$t kiCu d, li*u cho s’n; nHu sg kH thPa A Uc s. d^ng, sg kH thPa trgc tiHp tP m$t class chi A Uc s. d^ng m$t l n. - M$t l p d n xu t th :ng c n truy c+p AHn d, li*u thành ph n cNa l p cd sL AC tJo ra m$t hàm thành ph n. Thu+n lUi trong vi*c s. d^ng hàm thành ph n protected là tHn cNa d, li*u cNa l p cd sL không có visible (A Uc nhìn th y) trong l p d n xu t và vì v+y có thC b thay AVi. Nh,ng hàm truy xu t (access function) nên tr lJi giá tr cNa d, li*u thành ph n ( read-online acccess). i-u này A Uc thgc hi*n m$t cách Adn gi n bKng cách khai báo const function cho d, li*u thành ph n.

8 . L p Template: - ". 29: - Không nên c@ gang AC tJo m$t thgc thC cNa m$t template class sN d^ng kiCu mà không A nh nghoa nh,ng hàm thành ph n mà class template yêu c u. - ". 30: - C†n th+n tránh A nh nghoa nhi-u l n ( multiple definition) nh,ng overloaded function cùng v i sg khLi tJo cNa class template. - Trong C++ thì không thC chi rõ yêu c u cho kiCu cNa A@i s@ cNa class template và function template. Vi*c này có nghoa là kiCu thì A Uc chZn bLi user, không tuân theo interface nh yêu c u bLi template. Ví d^, m$t class template yêu c u kiCu A@i s@ có toán t. so sánh A Uc A nh nghoa. - M$t v n A- v i type template có thC n y sinh A@i v i overloaded function. NHu m$t hàm A Uc overload, có thC se có xung A$t nHu kiCu d, li*u thành ph n ( element type) xu t hi*n t :ng minh

trong m$t trong nh,ng s@ Aó. Sau khi khLi tJo, có thC có hai hàm có kiCu nguyên int nh là m$t A@i s@. Trình biên d ch có thC se thông báo lki, nh,ng th+t là nguy hiCm nHu ng :i thiHt kH class không chú ý nó.

Ví d^ 29:V n A- khi s. d^ng kiCu tham s@: template class Conflict { public: void foo( int a ); void foo( ET a ); // What if ET is an int or another integral type? // The compiler will discover this, but ... };

9. Hàm(Functions) 9.1 @i s@ cNa hàm ( function argument) '% (a" 29: - Không s. d^ng A@i s@ cNa hàm mà không chi rõ kiCu d, li*u ( kí hi*u d u ch m l.ng ). '% (a" 30: - Tránh nh,ng hàm có nhi-u A@i s@. '% (a" 31: - NHu m$t hàm chTa m$t con trE trE AHn m$t object (A Uc truy c+p thông qua A@i s@) thì nên khai báo A@i s@ có kiCu con trE. S. d^ng reference argument trong nh,ng tr :ng hUp nh thH này. - ". 31: - S. d^ng tham chiHu hKng ( const reference) ( const &) thay vì gZi-bKng-giá -tr ( call-byvalue), trP khi s. d^ng nh,ng kiCu d, li*u A Uc A nh nghoa tr c hay con trE. - Hàm thông d^ng s. d^ng A@i s@ không chi rõ (unspecified argument) là printf(). Vi*c s. d^ng nh,ng hàm nh v+y thì không nên A Uc khuyHn khích bLi vì vi*c kiCm tra kiCu khac khe trong C++.Trong m$t vài tr :ng hUp thì vi*c s. d^ng A@i s@ không chi rõ (unspecified argument) có thC A Uc thay thH bKng ch1ng hàm( overloading function) homc sN d^ng A@i s@ mmc A nh ( default argument). - Hàm v i m$t danh sách A@i s@ dài thì nhìn có v• phTc tJp, khó AC AZc và khó AC b o trì sau này. BKng cách s. d^ng tham chiHu ( reference) thay vì con trE nh là A@i s@ cNa hàm thì code d AZc hdn. M$t b t lUi là không d dàng th y A Uc hàm nào thay AVi giá tr cNa A@i s@ cNa nó.

- M$t khác bi*t gi,a tham chiHu và con trE là không có tham chiHu null trong ngông ng,, trong khi có null-pointer. i-u này có nghoa là m$t A@i t Ung ph i A Uc c p phát tr c khi truy-n nó AHn hàm. ThuJn lUi L Aây là không c n thiHt kiCm tra sg t1n tJi cNa A@i t Ung trong hàm. - C++ gZi hàm theo kiCu gZi-bKng-tr ( call-by-value). i-u này có nghoa là nh,ng A@i s@ cNa hàm A Uc copy vào stack thông qua vi*c gZi copy constuctor, vi*c này se d n AHn gi m hi*u qu thgc thi nHu nh,ng object Aó là nh,ng object l n. Ngoài ra, destructor se A Uc gZi khi t1n tJi hàm. @i s@ “const & “ có nghoa là chi nh,ng tham chiHu AHn A@i t Ung trong v n A- Aang nói AHn A Uc Amt vào stack ( callby-reference) và trJng thaía cNa object( biHn cNa thgc thC) không thC chinh s.a A Uc .

Ví d^ 30 :Tham chiHu thay vì con trE : // Unnecessarily complicated use of pointers void addOneComplicated( int* integerPointer ) { *integerPointer += 1; } addOneComplicated( &j ); // Write this way instead: void addOneEasy( int& integerReference ) { integerReference += 1; } addOneEasy( i );

Ví d 31 : Different mechanisms for passing arguments // a. A copy of the argument is created on the stack. // The copy constructor is called on entry, // and the destructor is called at exit from the function. // This may lead to very inefficient code. void foo1( String s ); String a; foo1( a ); // call-by-value // b. The actual argument is used by the function // and it can be modified by the function. void foo2( String& s ); String b; foo2( b ); // call-by-reference // c. The actual argument is used by the function // but it cannot be modified by the function.

void foo3( const String& s ); String c; foo3( c ); // call-by-constant-reference // d. A pointer to the actual argument is used by the function. // May lead to messy syntax when the function uses the argument. void foo4( const String* s ); String d; foo4( &d ); // call-by-constant-pointer

9.2 Ch1ng hàm ( Function overloading) - Khi ch1ng hàm thì mZi biHn thC nên có cùng chung m$t ng, nghoa (A Uc s. d^ng cho cùng m$t m^c Aích). - Ch1ng hàm là m$t công c^ng mJnh AC tJo ra m$t hZ nh,ng hàm liên quan v i nhau mà chi khá nhau L kiCu d, li*u cung c p bLi A@i s@. NHu không s. d^ng nó m$t cách hUp lý ( chnng hJn nh nh,ng hàm gi@ng nhau v- tên A Uc dùng cho nh,ng m^c Aíc khác nhau), có thC gây ra sg nh m l n.

Ví d^ 32:Ví d^ cho cách s. d^ng Aúng cNa quá t i hàm: class String { public: // ... int contains( const char c ); int contains( const char* cs ); int contains( const String& s ); // ... };

// // // // //

Used like this: String x = "abc123"; int i = x.contains( 'b' ); int j = x.contains( "bc1" ); int k = x.contains( x );

9.3 @i s@ hình thTc: '% (a" 32: - Tên cNa formal arguments A@i v i m$t hàm A Uc chi rõ và có thC gi@ng nhau trong khai báo hàm v trong A nh nghoa cNa hàm. - Tên cNa formal arguments A Uc chi rõ trong A nh nghoa hàm và trong khai báo hàm trong C++. Cung c p tên cho A@i s@ hàm là m$t ph n cNa function documention. Tên cNa A@i s@ nên ph n ánh A Uc A@i s@ A Uc s. d^ng nh thH nào, gi m A Uc vi*c ph i viêt comment, ví d^, m$t A nh nghoa l p.

Ví d^ 33 : @i s@ hình thTc : int setPoint( int, int ); // No ! int setPoint( int x, int y ); // Good

int setPoint( int x, int y ) { // ... }

9.4 Giá tr và kiCu tr v-: '% (a" 33: - Luôn luôn chi rõ m$t cách t :ng minh kiCu tr v- cNa m$t hàm . '% (a" 34: - M$t public function không nên tr lJi tham chiHu hay con trE AHn biHn c^c b$. - Hàm mà không có chi rõ kiCu tr v- trong khai báo thì se ng m A nh nh+n kiCu tr v- là int. i-u này có thC gây nh m l n, bLi vì compiler se warning là thiHu kiCu tr v-. BLi vì Ai-u này, nh,ng hàm khôgng có tr v- giá tr nào nên chi rõ kiCu tr v- là void. - NHu m$t hàm tr v- tham chiHu homc con trE AHn m$t biHn c^c b$, b$ nh mà nó trE t i se b hu• khi tham chiHu homc con trE A Uc s. d^ng. Trong m$t s@ tr :ng hUp thì Compiler se give a warning cho tr :ng hUp này.

9.5 Hàm inline: '% (a" 35: - Không s. d^ng preprocessE directive #define AC làm cho code hi*u qu hdn, thay vào Aó, s. d^ng inline function. - ". 32: - S. d^ng inline function khi th+t sg c n thiHt. - Inline function có thu+n lUi là nhanh hdn hàm bình th :ng. B t lUi cNa inline function là vi*c hi*n thgc trL nên quá exposed, bLi vì A nh nghoa m$t inline function ph i A Uc Amt trong m$t include file cNa class, trong khi A nh nghoa cNa m$t hàm bình th :ng A Uc Amt trong m$t file riêng bi*t. - KHt qu là nh,ng thay AVi trong s hi*n thgc ( implementation) cNa m$t inline function yêu c u re-compiling khi include file thay AVi. Vi*c này chi Aúng cho nh,n môi tr :ng l+p trình dga trên fiel ( file-based programming enviroment) s. d^ng nh,ng cd chH nh v+y khi make for compilation. - Compiler không bat bu$c ph i make m$t function inline. QuyHt A nh cho v n A- này tu‘ thu$c vào compiler. Nh,ng thông th :ng thì se set m$t compiler flag sao cho compiler give a warning khi nó không make a function line ( trái v i khai báo). “Outlined inlines” có thC d n AHn nh,ng ch dng trình l n và ch+m m$t cách không c n thiHt. - Se là hUp lí nHu tách A nh nghoa cNa inline function ra khEi A nh nghoa cNa class và Amt chúng vào m$t file riêng bi*t.

Ví d^ 34:Hàm inline t@t hdn macro // Ví d có v n v i #define "functions" #define SQUARE(x) ((x)*(x)) int a = 2; int b = SQUARE(a++); // b = (2 * 3) = 6 // Inline functions are safer and easier to use than macros if you // need an ordinary function that would have been unacceptable for // efficiency reasons. // They are also easier to convert to ordinary functions later on. inline int square( int x ) { return ( x * x ); }; int c = 2; int d = square( c++ ); // d = ( 2 * 2 ) = 4

9.6 @i t Ung tJm th:i: - ". 33: - Gi m thiCu s@ object tJm th:i A Uc tJo ra nh là giá tr tr v- tP nh,ng hàm homc nh là nh,ng A@i s@ cNa hàm. - @i t Ung tJm th:i th :ng A Uc tJo ra khi m$t obect A Uc tr v- tP m$t hàm homc khi A@i t :ng A Uc truy-n nh là m$t A@i s@ cNa hàm. Trong c hai tr :ng hUp, m$t constructor cho object A Uc gZi tr c, sau Aó, destructor A Uc gZi. Nh,ng A@i t Ung tJm v i kích th c l n làm cho code kém hi*u qu . Trong m$t vài tr :ng hUp se xu t hi*n lki khi A@i t Ung tJm A Uc tJo. Và m$t Ai-u quan trZng n,a là không nên dùng con trE trE AHn A@i t Ung tJm , bLi vì th:i gian s@n ( lifetime) cNa m$t A@i t :ng tJm thi không xác A nh.( Xem 18.7)

Ví d^ 35 : @i t Ung tJm và m$t cách AC loJi chúng: class BigObject { double big[123456]; }; // Example of a very inefficient function with respect to temporary objects: BigObject slowTransform( BigObject myBO ) { // When entering slowTransform(), myBO is a copy of the function argument // provided by the user. -> A copy constructor for BigObject is executed. // ... Transform myBO in some way return myBO; // Transformed myBO returned to the user }

// When exiting slowTransform(), a copy of myBO is returned to the // user -> copy-constructor for BigObject is executed, again. // Much more efficient solution: BigObject& fastTransform( BigObject& myBO ) { // When entering fastTransform(), myBO is the same object as the function // argument provided by the user. -> No copy-constructor is executed. // Transform myBO in some way return myBO; // Transformed myBO is returned to the user. } // When exiting fastTransform(), the very same myBO is returned // to the user. -> No copy constructor executed. void main() { BigObject BO; BO = slowTransform( BO ); BO = fastTransform( BO ); // Same syntax as slowTransform() !! }

9.7 TVng quan: - ". 34: - Tránh nh,ng hàm dài và phTc tJp - Nh,ng b t lUi cNa m$t hàm dài: 1. NHu m$t hàm quá dài thì se khó AC hiCu khi AZc. 2. Trong tr :ng hUp có lki trong m$t hàm r t dài thì se khó AC có thC xác A nh lki và “undo” tr c khi report the error to the calling function. BKng cách s. d^ng nh,ng hàm ngan thì nh,ng lki này có thC d dàng xác A nh A Uc. 3. Nh,ng hàm phTc tJp thì khó AC test. NHu m$t hàm chTa AHn 15 câu l*nh if l1ng nhau thì se có 2^15 = 32768 nhánh khác nhau AC kiCm tra trong m$t hàm.

10. HKng (Constant) '% (a" 36: Constant nên A Uc A nh nghoa s. d^ng constant homc enum, thay vì # define. '% (a" 37:

Tránh s. d^ng nh,ng giá tr s@ (numeric value) trong code. Thay vào Aó nHn s. d^ng symbol value. B$ ti-n x. lý ( preprocessor) thgc hi*n sg thay thH cho nh,ng macro trong source code, r1i sau Aó source code A Uc compile. Vi*c này gây ra m$t s@ h+u qu không mong mu@n. Ví d^, nHu m$t hKng s@ A Uc A nh nghoa dùng #define, tên cNa hKng không A Uc nh+n ra trong nhi-u trình gX r@i ( debugger). NHu hKng A Uc thay thH bLi m$t expression, thì expession này có thC AuUc tính toán khác nhau cho nh,ng l n khLi tJo khác nhau,tu‘ thu$c vào t m vgc ( scope) cNa tên biHn. Numerical value trong code ( th :ng A Uc gZi là “Magic Numbers”) nên tránh s. d^ng bLi vì nó có thC gây ra nh,ng khó khfn nHu chúng ta c n thay AVi giá tr cNa chúng. M$t l Ung l n code có thC ph^ thu$c vào m$t giá tr (giá tr này không bao gi: thay AVi), giá tr này có thC A Uc s. d^ng tJi nhi-u v trí khác nhau trong code ( se khó khfn AC xác A nh v trí cNa t t c chúng), và nh,ng giá tr nh v+y hiHm khi anonymous ( có thC x y ra tr :ng hUp là mki s@ ‘2’ trong code không nh t thiHt ph i A Uc thay thH bLi t t c các s@ ‘3’).

Ví d^ 36:Nhi-u cách khác nhau AC khai báo hKng : // Constants using macros #define BUFSIZE 7 // No type checking // Constants using const const int bufSize = 7; // Type checking takes place // Constants using enums enum SIZE { BufSize = 7 }; // Type checking takes place

11. BiHn(Variable) '% (a" 38: BiHn nên A Uc khai báo v i t m vgc nhE nh t có thC. '% (a" 39: Mki biHn A Uc khai báo bKng m$t dòng riêng bi*t. '% (a" 40: Mki biHn A Uc khai báo nên A Uc khLi tJo m$t giá tr nào Aó tr

c khi nó A Uc s. d^ng.

'% (a" 41: NHu có thC thì s. d^ng khLi tJo ( initializatio) thay vì phép gán (assignment).

M$t biHn nên A Uc khai báo v i t m vgc nhE nh t có thC AC có thê nâng cao tính d AZc cNa code, và AC cho biHn không A Uc c p phát không c n thiHt. Khi m$t biHn A Uc khai báo tJi A u cNa m$t hàm A Uc s. d^ng L m$t ndi nào Aó trong code, thì se không de dàn AC biHt trgc tiHp kiCu cNa biHn Aó. Ngoài ra, còn có m$t nguy cd n,a là nh,ng biHn nh v+y thì tình c: b †n nHu nó là biHn c^c b$, có cùng tên, A Uc khai báo L m$t kh@i bên trong ( internal block). M$t biHn ph i A Uc khLi tJo tr c khi s. d^ng. Bình th :ng thì trinh biên d ch se c nh báo nHu m$t biHn ch a A Uc A nh nghoa. Nh,ng chng nên c†n th+n trong nh,ng tr :ng hUp nh v+y bLi vì sg c†n th+n v n không thPa. Thgc thC cNa m$t l p th :n A Uc khLi tJo nHu không có A@i s@ A Uc cung c p trong ph n khai báo ( empty constructor se A Uc gZi). C khai báo m$t biHn mà A Uc khLi tJo trong m$t file khác, the keyword extern A Uc s. d^ng. BKng cách khLi tJo m$t biHn tr c khi s. d^ng, thay vì gán giá tr cho chúng tr c khi chúng A Uc s. d^ng, code se hi*u qu hdn bLi vì không có A@i t Ung tJm A Uc tJo ra trong sg khLi tJo. @i v i nh,ng object chTa m$t l Ung l n d, li*u, vi*c này có thC giúp nâng cao Aáng kC t@c A$ cNa ch dng trình. Chú ý: Trong m$t s@ tr :ng hUp, m$t biHn A Uc gánn giá tr cNa m$t biCu thTc phTc tJp ;lúc Aó se không c n thiHt khLi tJo giá tr ban A u cho biHn. Xem VD 37

Ví d^ 37:KhLi tJo thay vì gán: //Không nên làm Ai-u này! //int i; //... 1022 lines of code //i = 10; int j = 10;// Better class Special//Array of this class is used to initialize{// MyClass::complicated public: Special(); // Default constructorint isValid() const; int value() const; }; const int Magic = 1066; Special specialInit[Magic]; class MyClass { public: MyClass( const char* init ); // Constructor // ... private: String privateString; int complicated; }; // Do not do this! Inefficient code. // Empty constructor + assignment operator called for privateString

// // MyClass::MyClass( const char* init ) // { // privateString = init; // ... // } MyClass::MyClass( const char* init ) : privateString( init ) // Better { // Special case - complicated expression for( int i = 0; i < Magic; i++ )// No! You should enclose "for" if ( specialInit[i].isValid() )// loops in braces! See Rec. 25! { complicated = specialInit[i].value(); break; } }

12. Con trE và tham chiHu: '% (ac 42: Không so sánh con trE NULL homc gán NULL cho m$t con trE, thay vì v+y s. d^ng 0. - ". 35: Con trE trE AHn con trE nên tránh nHu có thC A Uc. - ". 36: S. d^ng typedef AC Adn gi m syntax cNa prEgam khi khai báo m$t con trE hàm. Trong ANSI-C standard, NULL A Uc A nh nghoa homc là (void *) 0 homc 0. NHu A nh nghoa này v n còn Aúng trong ANSI-C++ thì se n y sinh ra v n A-. NHu NULL A Uc A nh nghoa là kiCu “void*), nó không thC A Uc gán cho b t cT con trE nào mà không ép kiCu m$t cách t :ng minh (explicit type conversion). Vì lí do này, nên so sánh v i 0 ít nh t cho AHn khi ANSI-C++ committee A a ra quyHt A nh. Con trE trE AHn con trE thì th :ng không A Uc s. d^ng. Thay vì v+y, m$t l p nên A Uc khai báo, trong Aó có chTa m$t biHn thành ph n là kiCu con trE. Vi*c này nâng cao tính d AZc cNa code và khuyHnh khích trPu t Ung hoá d, li*u ( data abstraction). BKn cách c i thi*n tinh d AZc cNa code, xác xu t AC m$t ch dng trình chJy Aúng se A Uc nâng cao hdn. M$t hàm thay AVi giá tr cNa con trE A Uc cung c p d tham chiHu AHn con trE ( e.g. char & c) .

i dJng A@i s@, nên khai báo A@i s@ có

Typedef là m$t cách hay AC giúp code d b o trì và kh chuyCn ( portable). Xem 18.1, Port.Rec.1. M$t lý do khác AC s. d^ng typedef là tính d dZc cNa code A Uc c i thi*n. Con trE hàm có thC A Uc s. d^ng nh hàm bình th :ng; chúng không c n dereferenced.

Ví d^ 38:So sánh sg khác bi*t cNa nh,ng con trE: char* sp = new char[100]; if ( !sp ) cout << "New failed!" << endl; // No! if ( sp == 0 ) cout << "New failed!" << endl; // Best if ( sp == NULL ) cout << "New failed!" << endl; // ERROR sometimes !!!

Ví d^ 39:Con trE trE t i con trE là không c n thiHt: #include void print_mij(int** m, int dim1, int dim2) { for (int i = 0; i < dim1; i++) { for (int j = 0; j < dim2; j++ ) cout << " " << ((int*)m)[i*dim2+j]; cout << endl; } } // Có th c vi t l i là: class Int_Matrix { public: Int_Matrix(int dim1, int dim2); int value(int,int) const; int dim1() const; int dim2() const; // .. }; void print_Mij(Int_Matrix m) { for (int i = 0; i < m.dim1(); i++) { for (int j = 0; j < m.dim2(); j++ ) cout << " " << m.value(i,j); cout << endl; } }

Ví d^ 40:Nh,ng khai báo phTc tJp: // func1 là m t hàm: int -> (function : const char* -> int) // t c là hàm có m t i s c a ki u int và ki u tr v // là m t con tr n hàm có m t i s ki u const char* // và tr v ki u int

int (*func1(int))(const char*); // func1 of the same type as func2 typedef int FTYPE(const char*); FTYPE* func2(int); int (*(*func1p)(int))(const char*) = func2; // Realistic example from signal.h void (*signal(int,void (*)(int)))(int);

Ví d^ 41:Cú pháp Adn gi n nh,ng hàm con trE s. d^ng m$t typedef #include <math.h> // Ordinary messy way of declaring pointers to functions: // double ( *mathFunc ) ( double ) = sqrt; // With a typedef, life is filled with happiness (chinese proverb): typedef double MathFuncType( double ); MathFuncType* mathFunc = sqrt; void main() { // You can invoke the funktion in an easy or complicated way double returnValue1 = mathFunc( 23.0 ); // Easy way double returnValue2 = ( *mathFunc )( 23.0 ); // No! Correct, but complicated }

13 . Ép kiCu: '% (a" 43: Tránh s. d^ng ép kiCu t :ng minh (explicit type conversion) ( casts). '% (a" 44: Không viHt code ph^ thu$c vào nh,ng hàm sN d^ng ép kiCu không t :ng minh. '% (a" 45:

Không bao gi: chuyCn con trE trE AHn A@i t Ung cNa l p d n xu t thành con trE trE AHn A@i t Ung cNa l p cd sL o ( virtual base class) '% (a" 46: Không chuyCn m$t const thành m$t non-const M$t sg ép kiCu t :ng minh homc không t :ng mình, ph^ thu$c vào vi*c nó A Uc ordered b:i l+p trình viên homc trình biên d ch. Ép kiCu t :ng minh ( casts) A Uc s. d^ng khi l+p trình viên mu@n get around h* th@ng kiCu cNa trình biên d ch. Ép kiCu t :ng minh gi,a nh,ng A@i t Ung khác kiCu se làm cho code khó AC AZc. Ép kiCu t :ng minh ( casts) nên A Uc s. d^ng trong tr :ng hUp con trE l p cd sd trE AHn l p d n xu t A Uc dùng. Vi*c này x y ra khi, ví d^, m$t heterogeneous container class A Uc s. d^ng AC hi*n thgc m$t container class AC chTa con trE AHn A@i t Ung d n xu t. L p m i này có thC A Uc làm “type-safe” nHu programmer exclude object khác hdn là con trE l p d n xu t from being stored. C sg thgc thi này hoJt A$ng, Ai-u c n thiHt là con trE l p cd sL A Uc chuyCn sang con trE l p d n xu t khi chúng A Uc removed khEi heterogeneous container class. Hai lý do trên cho vi*c s. d^ng explicit casts hoàn toàn không xu t hi*n n,a khi template A Uc A a vào hoJt A$ng trong C++. Có hai kiCu ép kiCu không t :ng minh: homc là có m$t sg chuyCn cNa m$t hàm tP kiCu này thành kiCu khác, A Uc viêt bLi programmer, homc là trình biên d ch se thgc hi*n nó theo chu†n cNa ngôn ng,. Nh ng c hai tr :ng hUp có thC phát sinh v n A-. C++ là m$t ngôn ng, d dãi trong v n A- biHn mà A Uc s. d^ng nh là A@i s@ cNa m$t hàm. NHu không có hàm mà phù hUp v i kiCu cNa A@i s@ thì compiler se c@ gang A- convert kiCu AC tìm m$t kiCu phù hUp. Cái b t lUi L Aây là nHu có nhi-u hdn m$t hàm phù hUp A Uc tìm th y, m$t lki biên dich se A Uc phát sinh. T* hdn n,a là code mà compiler cho phép trong ng, c nh này se chTa lki mà khi m$t sg ép kiCu không t :ng minh A Uc dùng trong code này. M$t hi*u Tng l khác cNa vi*c ép kiCu không t :ng minh là A@i t Ung tJm A Uc tJo ra trong vi*c chuyCn kiCu. @i t Ung này se là A@i s@ cNa hàm, không ph i là A@i t Ung g@c A Uc truy-n. nh nghoa cNa ngôn ng, ngfn c m vi*c gán m$t A@i t Ung tJm cho m$t non-constant reference, nh ng ph n l n compiler v n cho phép Ai-u này. Trong ph n l n tr :ng hUp, vi*c này có nghoa là ch dng trình se không hoJt A$ng m$t cách hoàn h o. Nên c†n th+n v i constructor mà s. d^ng chi m$t A@i s@, bLi vì vi*c này se d n AHn m$t sg ép kiCu m i mà trình biên d ch có thC s. d^ng m$t cách không mong mu@n khi nó th y hUp lý trong m$t tình hu@ng xác A nh. NgoJi l* A@i v i Rule 43 L p cd sL o chng gây ra v n A- ép kiCu. Có thC chuyCn m$t con trE, trE AHn m$t thgc thC cNa m$t class có l p cd sL o, AHn m$t con trE trE AHn m$t A@i t Ung cNa l p cd sL o. Sg chuyCn ng Uc lJi không A Uc phép, i.e. sg chuyCn kiCu không có tính A o ng Uc. Vì lí do này, chúng ta không nên chuyCn m$t con trE trE AHn l p l p d n xu t trE AHn m$t con trE cNa l p cd sL o. C có thC tr v- A@i t Ung tJm non-const, Aôi lúc vi*c ép kiCu t :ng minh A Uc s. d^ng AC chuyCn m$t const member data thành m$t non-const. ây không ph i là m$t thói quen l+p trình t@t, bLi vì có thC là trình biên d ch se c p phát nh,ng hKng s@ trên ROM. Exception to Rule 44:

Ép kiCu t :ng minh A Uc s. d^ng AC chuyCn m$t con trE trE AHn l p cd sL thành m$t con trE trE AHn l p d n xu t trogn type-safe container class mà A Uc hi*n thgc s. d^ng heterogeneous container class. Ép kiCu t :ng minh A Uc s. d^ng AC chuyCn m$t anonymous bit-stream thành m$t object. Vi*c này x y ra khi unpacking m$t message thành m$t message buff•. Tóm lJi, Ép kiCu t :ng minh A Uc s. d^ng AC AZc m$t external representation cNa m$t object. Exception to Rule 45: NHu m$t l p cd sL o chTa m$t hàm o, mà hàm o này chuyCn con trE trE AHn l p cd sL thành con trE trE AHn l p d n xu t, vi*c này có thC thgc hi*n bKng cách A nh nghoa hàm trong l p d n xu t. Chú ý rKng vi*c này có nghia là t t c l p d n xu t ph i A Uc hiCu trong l p cd sL o.

Ví d^ 42: Constructors with a single argument that may imply dangerous type conversions class String { public: String( int length ); // ... };

// Allocation constructor

// Function that receives an object of type String as an argument void foo( const String& aString ); // Here we call this function with an int as argument int x = 100; foo( x ); // Implicit conversion: foo( String( x ) );

Ví d^ 43:M$t cách s. d^ng ép kiCu †n: // String.hh class String { public: String( char* cp ); // Constructor operator const char* () const; // Conversion operator to const char* // ... }; void foo( const String& aString ); void bar( const char* someChars ); // main.cc

main() { foo( "hello" ); // Implicit type conversion char* -> String String peter = "pan"; bar( peter ); // Implicit type conversion String -> const char* }

Ví d^ 44:Khi ép kiCu †n cho kHt qu không mong mu@n : // This function looks bulletproof, but it isn't. // Newer versions of compilers should flag this as an error. void mySwap( int& x, int& y ) { int temp = x; x = y; y = temp; } int i = 10; unsigned int ui = 20; mySwap( i, ui ); // i u gì x y ra ây: // int T = int( ui ); // Implicit conversion // mySwap( i, T ); // ui is of course not changed! // Fortunately, the compiler warns for this !

Ví d^ 45:Ép kiCu tP con trE cNa l p g@c AHn con trE cNa l p o là không thC thay AVi A Uc class VirtualBase { public: virtual class Derived* asDerived() = 0; }; class Derived : virtual public VirtualBase { public: virtual Derived* asDerived(); }; Derived* Derived::asDerived() { return this; } void main() { Derived d;

Derived* dp = 0; VirtualBase* vp = (VirtualBase*)&d; dp = (Derived*)vp; // ERROR! Cast from virtual base class pointer dp = vp->asDerived(); // OK! Cast in function asDerived }

Ví d^ 46:Addition which leads to a compile-time error // String.hh class String { public: String( char* cp ); // Constructor operator const char* () const; // Conversion operator to const char* // ... }; void foo( const String& aString ); void bar( const char* someChars ); // Word.hh class Word { public: Word( char* cp ); // Constructor // ... }; // Function foo overloaded void foo( const Word& aWord ); // ERROR: foo( "hello" ) MATCHES BOTH: // void foo( const String& ); // AND void foo( const Word& ); //main.cc main() { foo( "hello" ); // Error ambiguous type conversion ! String peter = "pan"; bar( peter ); // Implicit type conversion String -> const char* }

Ví d^ 47:Cho vi*c thi hành hi*u qu hdn, gX bE nh,ng const-ness khi s. d^ng kHt qu trung gian: // oJn mã này không A Uc A- c. #include <math.h> class Vector { public: Vector(int, const int []); // Constructor double length() const; // length = sqrt(array[1]*array[1] + ... ) void set(int x, int value); // ... private: int size; int* array; double lengthCache; // to cache calculated length int hasChanged; // is it necessary to re-calculate length ? }; double Vector::length() const { if (hasChanged) // Do we need to re-calculate length { ((Vector*)this)->hasChanged=0; // No! Cast away const double quadLength = 0; for ( int i = 0; i < size; i++ ) { quadLength += pow(array[i],2); } ((Vector*)this)->lengthCache = sqrt(quadLength); // No! Cast away const } return lengthCache; } void Vector::set( int nr, int value ) { if ( nr >= size ) error( "Out Of Bounds"); array[nr]=value; hasChanged = 1; }

Ví d^ 48: Liên t^c loJi bE const-ness cho vi*c thgc thi có hi*u qu

// oJn mã này là an toàn hdn ví d^ 47 nh ng có thC kém hi*u qu #include <math.h> class Vector { public: Vector(int, const int []); // Constructor double length() const; // length = sqrt(array[1]*array[1] + ... ) void set(int x, int value); // ... private: int size; int* array; double* lengthCache; // to cache length in int* hasChanged; // is it necessary to re-calculate length ? }; Vector::Vector(int sizeA, const int arrayA[]) : size(sizeA), array( new int[sizeA] ), hasChanged(new int(1)), lengthCache(new double) { for ( int i = 0; i < size; i++ ) { array[i] = arrayA[i]; } } Vector::~Vector() // Destructor { delete array; delete hasChanged; delete lengthCache; } // Continue on next page ! double Vector::length() const { if (hasChanged) // Do we need to re-calculate length ? { *hasChanged=0; double quadLength = 0; for ( int i = 0; i < size; i++ ) { quadLength += pow(array[i],2);

} *lengthCache = sqrt(quadLength); } return lengthCache; } void Vector::set( int nr, int value ) { if ( nr >= size ) error( "Out Of Bounds"); array[nr]=value; *hasChanged = 1; }

14. Kh@i c u trúc Ai-u khiCn (Flow Control Structures) '% (a" 47: Code sau label case ph i luôn luôn A Uc kHt thúc bLi break. '% (a" 48: M$t phát biCu switch ph i luôn luôn chTa m$t default branch (AC A- phòng tr :ng hUp ngoJi l* phát sinh). '% (a" 49: Không bao gi: s. d^ng goto. '% (a" 50: Vi*c lga chZn c u trúc lmp ( for, while, do-while) ph^ thu$c vào Amc AiCm cNa vòng lmp. - ". 37: Luôn luôn s. d^ng unsigned cho biHn mà không có giá tr âm - ". 38: Nên s. d^ng inclusive lower limit và exclusive upper limits. - ". 39: Tránh s. d^ng continue - ". 40: S. d^ng break AC thoát khEi vòng lmp nHu vi“c này tránh s. d^ng c:. - ". 41: Không viHt biCu thTc lô-gíc theo kiCu if (test) or if (!test) khi test là m$t pointer.

Mki c u trúc lmp có m$t sg h,u d^ng riêng. C u trúc for A Uc s. d^ng khi biHn lmp ( loop variable) tfng m$t l Ung không AVi cho mki l n lmp và khi Ai-u ki*n kHt thúc cNa vòng lmp A Uc xác A nh bLi m$t biCu thTc hKng. Trong tr :ng hUp khác, while or do-while nên A Uc s. d^ng. Khi Ai-u ki*n kHt thúc A Uc tính toán tJi A u cNa vòng lfp, while nên A Uc s. d^ng; do-while A Uc s. d^ng khi Ai-u ki*n kHt thúc A Uc tính toán tJi cu@i vòng lmp. Goto thoát khEi lu1ng Ai-u khiCn ( flow control) và có thC d n AHn vi*c khó hiCu code. Ngoài ra, có sg gi i hJn khi goto A Uc s. d^ng. Ví d^, không A Uc phép nh y trL lJi m$t câu l*nh mà khLi tJo m$t object c^c b$ có destructor. Nh,ng biHn mà th :ng A Uc dùng AC miCu t kích th c và chi-u dài th :ng AuUc khai báo là unsigned. BKng cách s. d^ng cách này có thC tránh A Uc m$t vài lki khó ch u phát sinh mà ta không kiCm soát A Uc. T@t nh t là nên s. d^ng inclusive lower và exclusive upper limits. Thay vì nói rKng biHn x trong kho ng x>=23 và x<=42, s. d^ng gi i hàn x>=23 và x<43. Vi*c này có nh,ng lUi ích sau: + Kích th c cNa kho ng biHn thiên cNa x là hi*u cNa hai gi i hJn ( 43-23). + Gi i hJn bKng nhau nHu kho ng biHn thiên là rkng. + Gi i hJn trên không bao gi: nhE hdn gi i hJn d i. BKng cách trên thì nhi-u lki có thC tránh A Uc. NHu code sau lable case không kHt thúc bLi break, vi*c thgc thi tiHp túc sau lable case kH tiHp. Vi*c này se gây ra lki cho ch dng trình. Continue có thê A Uc s. d^ng AC thoátt khEi vòng lmp. Tuy nhiên, code có thC se d hiCu hdn bKng cách s. d^ng else bLi . Chú ý AHn t m vgc mà biHn chJy ( iteratioin variable) visible. M$t biHn A Uc khai báo trong vong for thì chi visible trong kh@i A Uc bao bLi cmp d u “{}” cNa vòng for Aó. Exception to Rule 47: Khi m$t vài label case có s. d^ng chung m$t block code, chi m$t phát biCu break là c n thiHt.

Ví d^ 49:V n A- s. d^ng kiCu unsigned trong biHn cNa vòng lmp: for( unsigned int i = 3; i >= 0; --i ) { // Vòng lmp se không bao gi: dPng, tP khi i Ai qua chu trình: // 3, 2, 1, 0, 4294967295, 4294967294, etc ... on a SparcStation // Note that this example does not follow the rules: i >= 0 // in the for statement. See next example ! }

Ví d^ 50:Khai báo Aã A Uc nhìn th y trong vòng for: for ( int index = 0; index < 10; index++ ) { cout << index; } int index = 3; // L I, ÂY LÀ M T S KHAI BÁO L I KHÔNG H P LÍ C A index // B I VÌ index C KHAI BÁO TRONG VÒNG FOR.

Ví d^ 51:Câu l*nh switch/case và sg nguy hiCm switch ( tag ) { case A:

{ // Không làm cái gì // L nh k ti p cg i

n foo()trong case k ti p

} case B: { foo(); // Không làm cái gì break; // Bây gi thi chúng ta thoát l nh switch } default: { // If no match in above cases, this is executed exit( 1 ); } }

Ví d^ 52:Nh,ng cách t@t và x u sg b@ trí có gi i hJn cho nh,ng biHn trong vòng lmp int a[10]; int ten = 10; int nine = 9; // Cách t t làm i u này: for( int i = 0; i < ten; i++ ) { a[i] = 0; } // X u khi làm nh sau: for( int j = 0; j <= nine; j++ ) { a[j] = 0; }

// Loop runs 10-0=10 times

// Loop runs 10 times, but 9-0=9 !!!

Ví d^ 53:S. d^ng break AC thoát vòng lmp ,không flags c n thiHt do {

// Cách này:

if ( Something ) { // Do something break; } } while( someCondition ); int endFlag = 0;

// là t t h n cách sau:

do { if ( /* Something */ ) { // Do something endFlag = 1; } } while( someCondition && !endFlag );

Ví d^ 53:BKng cách thêm vào else, continue c n tránh AC code d hiCu hdn: while( /* Something */ ) { if( /* Something */ ) { // Do something } else { // Do something else } }

//Cách này rõ ràng

while( /* Something */ ) // h n s d ng continue { if( /* Something */ ) { // Do something continue; // Không c! } // Do something else }

15. BiCu thTc(Expression) - ". 42: S. d^ng d u ngomc Adn AC làm rõ ràng thT tg tính toán cNa toán t. trong biCu thTc.

C@ m$t vài lki hay gmp trong vi*c tính toán m$t biCu thTc. Toán t. hai ngôi ( binary operator) trong C++ có tính kHt hUp ( trái homc ph i) và A$ u tiên. NHu m$t toán t. có tính kHt hUp trái và xu t hi*n L hai bên cNa m$t biHn trong m$t biCu thTc, thì biHn thu$c v- cùng m$t phàn cNa biCu thTc nh là toán t. bên phía trái cNa nó. M$t nh m l n phV biHn hay gmp là toán t. gán(assignment) và toán t. bKng( equality). Ví d^, toán t. << ( shift left) và >> ( shift right) th :ng A Uc s. d^ng trong input và output. BLi vì Aây là nh,ng toán t. bit, chúng có A$ u tiên cao hdn so v i toán t. quan h* ( relational operator). i-u này có ngho là d u ngomc Adn ph i A Uc s. d^ng khi xu t giá tr cNa biCu thTc logic.

Ví d^ 54:V n A- khi

c l Uc các d u ngomc

// Interpreted as ( a
Ví d^ 55:D u ngomc Adn A Uc A- c. int i = a >= b && c < d && e + f <= g + h; int j = ( a >= b ) && ( c < d ) && (( e + f ) <= ( g + h ));

// Không nên! // T t h n

16. C p phát b$ nh : '% (a" 51: Không s. d^ng malloc, realloc or free. '% (a" 52: Luôn luôn dùng empty brackets (“[]”) cho delete khi deallocate m$t array. - ". 43: Tránh s. d^ng d, li*u toàn c^c nHu có thC. - ". 44: Png có c p phát b$ nh và hy vZng rKng se có ai Aó deallocate nó sau này. - ". 45: Luôn luôn gán m$t giá tr m i cho m$t con trE mà trE AHn vùng nh Aã b deallocate.

Trong C++ d, li*u có thC A Uc c p phát, A$ng trên stack, homc A$ng trên heap. Có ba kiCu d, li*u tính: d, li*u toàn c^c, d, li*u l p toàn c^c ( global class data) và d, li*u tonh c^c b$ A@i v i m$t hàm ( static data local to a function). Se là nguy hiCm nHu : 1. gZi hàm delete m$t con trE obtained vai maaloc/realloc, 2. gZi hàm malloc/realloc cho nh,ng l p có constructor. 3. gZi hàm free cho b t cT cái gì mà A Uc c p phát bLi “new” Vì v+y, tránh nHu có thC vi*c s. d^ng malloc, realloc, và frê. NHu m$t array a có kiCu T A Uc c p phát, vi*c quan trZng là gZi delete theo Aúng cách. Chi viHt delete a, se d n AHn destructor d Uc thgc hi*n chi for first object cNa kiCu T. BKng cách viHt delete [m] a, m là m$t s@ nguyên l n hdn s@ l :ng A@i t Ung A Uc c p phát tr c Aây, destructor cNa T se A Uc gZi cho vùng b$ nh àm không represent l p kiCu T. Cách Adn gi n nh t AC làm vi*c này là viHt delete d a; bLi vì destructor se A Uc thgc thi chi cho nh,ng object Aã A Uc c p phát tr c Aây.

Ví d^ 56: Cách Aúng và sai AC xóa m$t m ng v i destructors int n = 7; T* myT = new T[n]; // T is a type with defined constructors and destructors // ... delete myT; // Không thC! Destructor chi A Uc gZi cho A@i t Ung A u tiên trong m ng delete [10] myT; // Không thC! Destructor called on memory out of bounds in array a delete [] myT;

// T t, và luôn luôn an toàn!

Ví d^ 57:Nh,ng nguy hiCm khi c p phát b$ nh : String myFunc( const char* myArgument ) { String* temp = new String( myArgument ); return *temp; //temp là không bao gi deallocated và ng i s d ng hàm myFunc không th deallocate // b!i vì m t b n t m c a instance không c tr l i. }

17. Mã linh A$ng(Portable Code)

17.1 Data Abstraction ( TrPu t Ung hoá d, li*u) - c. kh chuyCn 1: Tránh s. d^ng trgc tiHp nh,ng kiCu d, li*u Aã A Uc A nh nghoa tr

c trong khai báo.

M$t cách tuy*t v:i AC chuyCn your world thành “thung lhng n c mat” ( vale of tears) là s. d^ng trgc tiHp nh,ng d, li*u A Uc A nh nghoa s’n trong khai báo. NHu sau này,trong tr :ng hUp c n thiHt, bLi vì v n A- portability, AC thay AVi kiCu tr v- cNa m$t hàm, có thC se thay AVi nhi-u ndi trong code. M$t cách AC tránh Ai-u này là khai báo m$t kiCu tr v- m i s. d^ng nh,ng l p homc typedef AC miêu t kiCu cNa biHn A Uc s. d^ng. BKng cách này, ta có thC d dàng tJo sg thay AVi hdn. Vi*c này có thC A Uc s. d^ng AC gán m$t Adn v d, li*u v+t lý, chnng hJn nh kilogram hay meter. Nh,ng AoJn code nh va”a thì d dàng xem lJi hdn ( Ví d^, khi code không chJy t@t, có thC là m$t biHn miêu t meter A Uc gán cho m$t biên miêu t kilogram). Chú ý rKng typedef không tJo ra kiCu m i, chi là m$t cái tên khác cho m$t kiCu. Có nghoa là nHu khai báo typedef int Error, m$t biHn có kiCu Error có thê A Uc s. d^ng L b t cT ndi Aâu mà biHn ini A Uc sN d^ng

Ví d^ 58:KiCu khai báo s. d^ng typedef // Thay vì long int time; short int mouseX; char* menuName; // S d ng (for example): typedef long int TimeStamp; typedef short int Coordinate; class String { /* ... */ }; // và: TimeStamp time; Coordinate mouseX; String menuName;

17.2 Kích th

c cNa kiCu:

- c. kh chuyCn 2: Không nên ngho rKng m$t biHn kiCu int và long có cùng kích th c. - c. kh chuyCn 3: Không nên ngho rKng m$t biHn int dài 32 bits ( nó có thC chi dài có 16 bits). - c. kh chuyCn 4: Không nên ngho rKng m$t char là có d u hay không d u. - c. kh chuyCn 5: Luôn luôn gán char to unsigned if 8-bit ASCII A Uc s. d^ng. Trong A nh nghoa cNa ngôn ng, C++ thì m$t char ch a biHt là có d u hay không d u. Vi*c này ph^ thu$c vào compiler. NHu s. d^ng char theo cách này hay theo cách khác ( có d u hay không có d u), thì có thC se có bugs xu t hi*n truogn ch dng trình khi compiler khác A Uc s. d^ng. NHu 8-bits ASCII A Uc s. d^ng và phép so sánh hai kí tg A Uc thgc hi*n, thì unsigned char A Uc s. d^ng.

17.3 ChuyCn kiCu

- c. kh chuyCn 6: C†n th+n nHu chuyCn kiCu tP kiCu ngan hdn thành kiCu dài hdn. - c. kh chuyCn 7: Không nên ngho rKng pointer và integer có cùng kích th c. - c. kh chuyCn 8: S. d^ng Ép kiCu t :ng minh cho nh,ng phép tính s@ hZc s. d^ng giá tr không d u và có d u. KiHn trúc cNa b$ vi x. lý th :ng c m vi*c m$t d, li*u có kích th c c@ A nh A Uc c p phát cho m$t A a chi b t kì nào Aó. Ví d^, m$t tP ph i bat A u bKng m$t A a chi “chnng” fE MC680x0. NHu có m$t con trE trE AHn m$t char mà A Uc xác A nh là có A a chi “l•”, m$t sg chuyCn AVi kiCu tP con trE trE AHn kí tg này thành con trE int se là cho ch dng trình ATng khi con trE int A Uc sN d^ng, bLi vì vi*c này vi phJm nguyên tac cNa b$ x. lý trong vi*c gán d, li*u.

17.4 Mô t d, li*u (Data Representation) - c. kh chuyCn 9: Không nên ngho rKng d, li*u kiCu long,float, double, hay long double bat A u L b t c. A a chi nào. Vi*c biCu di n kiCu d, li*u trong b$ nh thì ph^ thu$c r t nhi-u vào máy tính. BKng cách c p phát data members cho m$t vùng nh nào Aó, b$ vi x. lý thgc thi code hi*u qu hdn. BLi vì Ai-u này, c u trúc d, li*u mà biCu di n m$t l p se A Uc chTa theo nh,ng cách khác nhau trong nh,ng kiHn trúc máy tính khác nhau. Code ph^ thu$c vào m$t specific represention thì không thC nói là portable A Uc.

17.5 Underflow/Overflow - c. kh chuyCn 10: Không nên ngho rKng A@i t Ung tonh A Uc khLi tJo theo m$t tr+t tg cho tr

c.

NHu giá tr A Uc chinh s.a hai l n trong cùng m$t biCu thTc, kHt qu cNa biCu thTc thì không A Uc xác A nh ngoJi trP khi thT tg tính toán A Uc A m b o cho nh,ng toán t. s. d^ng nó. ThT tg khLi tJo nh,ng A@i t Ung tonh có thC se làm phát sinh ra m$t s@ v n A-. M$t A@i t Ung tonh không A Uc s. d^ng trong constructor, nHu nó không A Uc khLi tJo cho AHn sau khi constructor A Uc gZi thgc thi. Lúc này, thP tg khLi tJo cNa nh,ng A@i t Ung tonh, A Uc A nh nghoa trong nh,ng Adn v biên d ch khác nhau, thì không A Uc xác A nh. Vi*c này d n AHn nh,ng lki mà khó AC xác A nh . Có vài ko thu+t AC tránh tình trJng này .

Ví d^ 59: Do not depend on the order of initialization in constructors. #include class X { public: X(int y);

private: int i; int j; }; inline X::X(int y) : j(y), i(j) // No! j may not be initialized before i !! { cout << "i:" << i << " & " << "j:" << j << endl; } main() { X x(7); }

// Rather unexpected output: i:0 & j:7

Ví d^ 60:KhLi tJo m$t A@i t Ung tonh(static objects) // Foo.hh #include #include <string.h> static unsigned int const Size = 1024; class Foo { public: Foo( char* cp ); // ... private: char buffer[Size]; static unsigned counter; }; extern Foo foo_1; extern Foo foo_2; // Foo1.cc #include "Foo.hh" unsigned Foo::counter = 0; Foo foo_1 = "one"; //Foo2.cc #include "Foo.hh"

// Constructor

// Number of constructed Foo:s

Foo foo_2 = "two"; Foo::Foo( char* cp ) // Irrational constructor { strncpy( buffer, cp, sizeof(buffer) ); foos[counter] = this; switch ( counter++ ) { case 0: case 1: cout << ::foo_1.buffer << "," << ::foo_2.buffer << endl; break; default: cout << "Hello, world" << endl; } } // If a program using Foo.hh is linked with Foo1.o and Foo2.o, either // ,two or one, is written on standard output depending on // one,two one,two the order of the files given to the linker.

17.5

@i t Ung tJm :

- c. kh chuyCn 11: - Không viHt code mà ph^ thu$c vào th:i gian s@ng cNa A@i t Ung tJm. - @i t Ung tJm th :ng A Uc tJo ra trong C++, chnng hJn nh khi hàm tr v- m$t giá tr . Nhi-u lki khó xác A nh có thC phát sinh khi có m$t con trE trE AHn m$t A@i t Ung tJm.

Ví d^ 60: Difficult error in a string class which lacks output operator class String { public: operator const char*() const; // Conversion operator to const char* friend String operator+( const String& left, const String& right ); // ... }; String a = "This may go to "; String b = "h***!"; // The addition of a and b generates a new temporary String object. // After it is converted to a char* by the conversion operator, it is // no longer needed and may be deallocated. This means that characters // which are already deallocated are printed to cout -> DANGEROUS!! cout << a + b;

17.6 Pointer Arithmetic - c. kh chuyCn 12: Tránh s. d^ng toán t. shift thay cho toán t. s@ hZc

Tránh s. d^ng pointer arithmetic Pointer arithmetic thì linh A$ng. Toán t. “==” và “!=”A Uc A nh nghoa cho t t c các pointer cNa cùng kiCu d, li*u, trong khi toán t. <,>,<=,>= thì linh A$ng chi khi chúng A Uc s. d^ng gi,a nh,ng con trE mà trE AHn cùng m$t m ng.

18.Sách tham kh o 1. The Annotated C++ Reference Manual, Bjarne Stroustrup/Margareth Ellis[ARM], Addison Wesley 1990, ISBN 0-201-51459-1. This book forms the basis of the work in the ANSI-C++ committee. 2. C++ Primer, Second Edition, Stanley B. Lippman, Addison Wesley 1991, ISBN 0-201-54848-8. Very good for learning the basics of C++. 3. The C++ Programming Language, Second Edition, Bjarne Stroustrup, Addison Wesley 1991, ISBN 0-201-53992-6. This second edition has been completely updated with the current (and future) language definition. It will most certainly become a standard reference book. 4. Advanced C++ Programming Styles and Idioms, James O. Coplien, Addison Wesley 1992, ISBN 0210-54855-0. Possibly the most advanced book on how to use C++. Contains many tricks and tips. 5. Object-oriented Software Construction, Bertrand Meyer, Prentice Hall 1988, ISBN 0-13-629049-3 or 0-13-629031-0 PBK Somewhat of a classic work. Examples are written in Eiffel. 6. Data Abstraction and Object-Oriented Programming in C++, Keith E. Gorlen, Sanford M. Orlow and Perry S. Plexico, John Wiley & Sons 1990, ISBN 0 471 92346 X pbk or 0 471 92751 1. The book that describes the class library NIH. Includes many good examples. 7. Object-Oriented Design with Applications, Grady Booch, Benjamin/Cummings 1991, ISBN 0-80530091-0. Treats the design and implementation of software in various object-oriented languages.

8. Recommended C Style and Coding Standards, Bell Labs, Zoology Computer Systems University of Toronto, CS University of Washington, November 18, 1989. A collection of rules for programming in C. Contains a good section on portability. 9. A Guide to Natural Naming, Daniel Keller, ETH, Projekt-Zentrum IDA, CH-8092 Zurich, Switzerland A guide on how to choose good names for functions and variables. Not adapted to object-oriented programming. 10. Advanced C++, Jonathan E. Shopiro, Binder with material from course held in Lund (Sweden) from June 4 to June 7, 1991. Filled with warnings and tips. 11. Objektorienterad programmering och biblioteksuppbyggnad i C++, Martin Carrol. Material from course held in Stockholm (Sweden) on April 18, 1991. Presents useful viewpoints on problems which may arise when designing a class library. 12. Automatic Detection of C++ Programming Errors: Initial Thoughts on a lint++, Scott Myers/Moises Lejter, Usenix C++ Conference Proceedings, Spring 91. Article which describes some programming rules for C++. 13. Code-Style Prescriptions Carl R. Dickler, Unix Review, 9(9), 1991, pages 41-45. Article which describes a number of programming rules for C and which discusses why programming rules are needed.

Related Documents