CHUONG TRINH TRONG C

++
CÁC QUI TAC VÀ NHÙNG DE CU.

Tác gia: Mats Henricson and Erik Nyquist.
Giáo viên huóng dân: Thây Nguyên Tân Trân Minh Khang.
Sinh viên dich: Lê Quang Song.

Bang các nôi dung:
• 1.Giói thiêu(Introduction)
• 2.Thuât ngü(Terminology)
• 3.Dê cu chung(General Recommendations)
• 4.Mã nguôn trong nhüng file(Source Code in Files)
* 4.1.Câu trúc mã(Structure of Code)
* 4.2.Tên nhüng file(Naming Files)
* 4.3.Nhüng lòi giai thích(Comments)
* 4.4.Include nhüng file(Include Files)
• 5.Nhüng tên gán(Assigning Names)
• 6.Phong cách(Style)
* 6.1. Các lóp(Classes)
* 6.2.Các hàm(Functions)
* 6.3.Khôi lênh diêu khiên(Flow Control Statements)
* 6.4.Con tro và tham chiêu(Pointers and References)

* 7.1.Quyên truy câp(Considerations Regarding Access Rights)
* 7.2.Hàm Inline(Inline Functions)
* 7.3.Các hàm ban(Friends)
* 7.4.Hàm hàng thành viên(const Member Functions)
* 7.5.Hàm khoi tao.hàm huy(Constructors and Destructors)
* 7.6.Toán tu gán(Assignment Operators)
* 7.6.Quá tai toán tu(Operator Overloading)
* 7.7.Kiêu tra vê cua hàm thành viên(Member Function Return Types)
* 7.8.Kê thùa(Inheritance)
• 8.Lóp templates(Class Templates)
• 9.Hàm(Functions)
* 9.1.Dôi sô cua hàm(Function Arguments)
* 9.2.Quá tai hàm(Function Overloading)
* 9.3.Dôi sô hình thúc(Formal Arguments)
* 9.4.Giá tri và kiêu tra vê(Return Types and Values)
* 9.5.Hàm inline(Inline Functions)
* 9.6.Nhüng dôi tuong tam thòi(Temporary Objects)
* 9.7.Tông quan(General)
• 10.Hàng(Constants)
• 11.Biên(Variables)
• 12.Con tro và tham chiêu(Pointers and References)
• 13.Ép kiêu(Type Conversions)
• 14.Khôi câu trúc diêu khiên(Flow Control Structures)
• 15.Biêu thúc(Expressions)
• 16.Câp phát bô nhó(Memory Allocation)
• 17.Mã linh dông(Portable Code)
* 17.1.Dü liêu trùu tuong(Data Abstraction)
* 17.2.Kíck cõ cua kiêu(Sizes of Types)
* 17.3.Chuyên dôi kiêu(Type Conversions)
* 17.4.Mô ta dü liêu(Data Representation)
* 17.5. Underflow/Overflow
*17.6.Dôi tuong tam thòi(Temporary Objects)
*17.7.Con tro sô hoc(Pointer Arithmetic)
• 18.Sách tham khao(References)



















1.GIÓI THIEU(INTRODUCTIONS)
Muc dích cua tài liêu này là xác dinh môt phong cách lâp trình trong C++.Nhüng qui tàc và nhüng dê
cu o dây không phai là tât ca nhung nó cung câp nhüng kiên thúc co ban dê làm viêc vói C++.Tâp hop
nhüng qui tàc này sê là nhüng tài liêu nàng dông.khuyên khích su phat triên thêm.Nhüng yêu câu vê
nhüng qui tàc mói hay nhüng su thay dôi các qui tàc duoc kê dên nhu là phu luc cua tàu này.Nhüng dê
nghi cüng có thê goi dên chúng tôi qua dia chi mail nhu sau :
• erik.nyquist@eua.ericsson.se
• mats.henricson@eua.ericsson.se
Nhüng chuong trình duoc phát triên theo các qui tàc và nhüng tiên cu o dây sê:
` Dúng.
* Mang tính tái su dung
Dê dat dên su chính xác.chuong trình nên :
* Có môt phong cách nhât quán.
* Dê dàng doc và hiêu.
` Kha nàng chuyên dôi giüa các ngôn ngü.
` Tao ra nhüng thông báo lôi phô biên.
` Có thê duy trì boi nhüng nhà lâp trình khác nhau.
Nhüng câu hoi trong viêc thiêt kê nhu là :làm thê nào dê thiêt kê môt lóp hoàc dàng câp cua lóp nàm
ngoài tài liêu này.Có thê tham khao nhüng sách trong duoc giói thiêu cuôi tài liêu này.
Nhüng gì chúa dung bên trong tài liêu này sê chi ra cách nhu thê nào dê giai quyêt có hiêu qua nhüng
khía canh khó khàn nhât trong C++.Cân phai nàm bàt và hoc ki nhüng ví du vê nhüng doan mã ví du
duoc cung câp o dây.










2.THUAT NGÙ(TERMINOLOGY)

1. Môt biên,hàng .hàm hoàc môt kiêu trong C++ dêu có môt dinh danh (identifier) hay là môt tên
riêng .Khi cân thiêt, môt dinh danh có câu trúc nôi bô có nghia là có các tiên tô .tên và các hâu tô trong
dó.(Theo thú tu)

2.Class là môt kiêu dü liêu do nguòi dùng tu dinh nghia bao gôm các dü liêu và các hàm thuc hiên trên
các dü liêu dó.Trong C++ ,dây có lê duoc khai báo nhu môt lóp . nó cüng duoc khai báo nhu môt câu
trúc(struct) hay môt union .Dü liêu duoc dinh nghia trong lóp duoc goi là dû liêu thành viên (member
data) .Và nhüng hàm duoc dinh nghia trong lóp duoc goi là các hàm thành viên(member functions) .

3.Môt class/struct hoàc union duoc nói là các kiêu dü liêu trùu tuong(abstract data type) chúng không có
bât kì môt dû liêu công công và bao vê thành viên nào. (public or protected member data.)

4.Môt struct cüng là môt kiêu dü liêu do nguòi dùng dinh nghia nhung chúng chi chúa dü liêu công
công (public data)mà thôi.

5. Public members cua môt lóp là các dü liêu thành viên ( member data)và các hàm thành viên(member
fuctions) cái mà có thê duoc su dung moi noi .

6.Protected members cua môt lóp là các member data và các member functions mà các hàm thành viên
cua lóp gôc mói truy câp duoc .

7.Môt class template dinh nghia môt ho cua nhüng lóp .Môt lóp mói duoc sê duoc tao tù class template
bàng viêc cung câp môt sô các dôi sô.Nhüng giá tri này có thê là tên cua nhüng kiêu hay các biêu thúc
hàng.

8.Tuong tu môt functions template dinh nghia môt ho cua nhüng hàm.Môt hàm mói sê duoc tao tù
functions template bàng viêc cung câp môt sô các dôi sô.Nhüng giá tri này có thê là tên cua nhüng kiêu
hay các biêu thúc hàt kiêu enumeration type là môt khai báo rõ ràng tâp hop dây du kí hiêu hàng.
Trong C++ nó duoc khai báo là enum.

10.Môt typedef là môt tên khác cho môt kiêu dü liêu .trong C++ thì khai báo là typedef .

11.Môt tham chiêu(reference) là môt tên khác cho môt biên.Trong C++ .toán tu dia chi (&) duoc khai
báo ngay sau kiêu dü liêu dê chi ràng dã khai báo môt biên .hàng.dôi sô cua hàm là môt tham chiêu.

12.Môt (macro) là tên cho môt chuôi vàn ban cái mà duoc dinh nghia trong khai báo #define .
Khi tên này xuât hiên trong doan mã.trình biên dich sê thay thê nó duói dang vàn ban.

13 Constructor là môt hàm khoi tao cho môt dôi tuong.

14.Copy constructor là hàm tao ban sao dó là môt hàm khoi tao trong dó dôi sô dâu tiên tham chiêu dên
dôi tuong cùng kiêu vói dôi tuong duoc khoi tao .

15.Hàm khoi tao màc dinh là hàm không có dôi sô.

16.Overloaded function name là quá tai tên hàm có nghia là tên duoc su dung cho hai hay nhiêu hàm
nhung khác tham sô truyên vào và kiêu tra vê.

17.Overridden là hàm chông có nghia là môt hàm thành viên trong lóp co so duoc dinh nghia lai tù lóp
gôc.Chúng là các hàm ao(virtual).

18.Pre-defined data type là kiêu dü liêu có trong ngôn ngü .ví du int ,float…

19.User-defined data type là kiêu dü liêu do nguòi dùng dinh nghia nhu là :class,struct…

20.Abstract base class là môt lóp mà không dôi tuong nào có thê tao .nó chi duoc su dung nhu môt lóp
co so cho viêc tìm ra môt lóp khác.




3.DE CU CHUNG(General Recommendations)
Dê cu 1:
Tôi uu mã khi ban chi khi ban biêt ban có su thuc thi có vân dê. Suy nghi hai lân truóc khi
ban bàt dâu.
Dê cu 2:
Nêu ban su dung trình biên dich C++ trên Cfront .luôn luôn biên dich vói cò hiêu +w thiêt
lâp các yêu tô loai bo khi môt vài báo dông có thê.


Nhiêu cuôc kiêm tra cho thây nói chung nhiêu nhà lâp trình dã tôn rât nhiêu thòi gian dê tôi uu nhüng
doan mã cái mà chua bao giò duoc chay.Nêu chuong trình cua ban quá châm .su dung gprof++ hoàc
công cu tuong tu dê xác dinh chính xác ban chât cua nhüng vân dê truóc khi tôi uu.




4.MÄ NGUON TRONG NHÙNG FILE(Source Code in Files)


4.1.Câu trúc cua mã:
Qui tàc 1:
Nhüng file chèn vào trong C++ luôn luôn có tên file có duôi mo rông “.h”.
Qui tàc 2:
Nhüng file thuc thi trong C++ luôn luôn có tên file có duôi mo rông “.cpp”.


Dê cu 3:
Môt include file không nên chúa nhiêu hon môt lòi dinh nghia lóp.
Dê cu 4:
Chia nhüng dinh nghia cua nhüng hàm thành viên hay nhüng hàm thành nhiêu
file khác nhau nêu có thê.
Dê cu 5:
Dàt nhüng mã máy dôc lâp lên nhüng file khác nhau dê dê dàng xác dinh vi trí khi
mang dên máy khác.

Muc dích cua nhüng qui uóc này là dê cung câp su thê hiên dông nhât cua nhüng tên file. Môt lí do cho
diêu này dó là dê dàng thao tác nhüng công cu trên tên file có duôi mo rông dó.
Có hai loai file include trong C++ :Nhüng cái duoc châp nhân trong ca trình biên dich ANSI-C và
C++ va nhüng thú chi duoc châp nhân trong trình biên dich C++ mà thôi.Do dó phai phân biêt dê
tránh lôi trong các file include(do su dung sai loai file chèn vào).

Nêu nhu môt file có duôi là .cpp chúa nhiêu dinh nghia hàm .môt file dôi tuong duoc tao ra lón không
cân thiêt.Dê thu duoc môt file thi hành nho nhât có thê thì cân phai dinh nghia nhüng hàm trên nhüng
file riêng biêt.Nguoc lai.có nhüng vân dê trong viêc quan lí môt sô lón các file dó ,thòi gian cân thiêt dê
biên dich các file dó sê rât lâu.

Môt vài chuong trình gõ rôi sê không gõ rôi duoc bên trong thân cua nhüng hàm .Bàng cách dàt nhüng
hàm dó trong nhüng file khác biêt và include nó vào file biên dich ,vì vây sê xu lí thân các hàm nhu
nhüng hàm thông thuòng và do dó sê go rôi duoc nhüng hàm trong khi kiêm tra chuong trình..Dê làm
công viêc này môt công nghê xu lí dàt biêt phai duoc su dung.
Khi nhüng công cu quan lí mã C++ là không thê.thât là dê dàng hon cho nhüng ai su dung và bao trì
nhüng lóp nêu chi có môt lóp trên môt file riêng biêt và nêu su thi hành nhüng hàm thành viên trong
nhüng lóp khác nhau hiên tai không nàm cùt file.

4.2.Tên file
Dê cu 6:
Luôn luôn dàt tên file cái mà dôc nhât trong môt ngu canh lón có thê.
Dê cu 7:
Môt file chèn vào cho môt lóp có tên có dang :<tên lóp• +duôi mo rông . Su dung
nhüng kí tu hoa và thuòng theo cùng môt cách nhu trong mã nguôn.

Tù khi tên cua nhüng lóp phai su dung thông nhât trong môt ngü canh lón .thât là thích hop dê su
dung nhüng dàc diêm này cho viêc dàt tên cua nhüng file chèn vào.Diêu này sê giúp nhüng công cu file
co ban dinh vi lóp môt cách dê dàng.


4.3.Nhüng lòi chú thích(Comments)
Qui tàc 3:
Môi file chúa dung mã nguôn phai có môt tài liêu trong dó có nhüng lòi chú thích
giói thiêu vê các thông tin cua file và nôi dung cua nó.
Qui tàc 4:
Tât ca các file chèn vào phai bao gôm thông tin vê ban quyên.
Qui tàc 5:
Tât ca các lòi giai thích phai viêt bàng tiêng €nh.

Dê cu 8:
Viêt môt vài chú thích mô ta truóc môi hàm.
Dê cu 9:
Su dung •• cho lòi chú thích.


Dó là su cân thiêt cho môt tài liêu mã nguôn .Diêu này duoc chàt chê và dê tìm.Viêc chon dúng cách
cho nhüng tên biên . hàm và lóp và dúng cách câu trúc mã thì sê cân ít lòi giai thích trong doan mã.
Chú ‚ ràng nhüng lòi giai thích trong nhüng file chèn vào là có ‚ nghia cho nguòi su dung nhüng
lóp .trong khi dó nhüng lòi giai thích trong file thi hành có ‚ nghia cho nhüng nguòi bao quan lóp.

Tât ca doan mã cua chúng ta phai có ban quyên rõ ràng.Nêu nhüng doan mã duoc phát triên quá
môt chu kì nhüng nàm.môi nàm phai bàt dâu.

Nhüng lòi giai thích thuòng dê câp nhüng chiên luoc và sách luoc .Môt lòi giai thích chiên luoc mô
ta hàm là gì và phân gì cua doan mã duoc du dinh dê làm và nhüng gì duoc thay thê sau doan mã
này.Môt lòi giai thích sách luoc mô ta môt dƒng don cua mã nhüng gì duoc du dinh làm và nhüng
gì duoc thay thê .nêu có thê , cuôi môi dƒng này.
Tiêc thay ,nêu quá nhiêu lòi chú thích nhu vây sê làm cho nhüng doan mã khó doc.Dôi vói lí do
này ,có môt dê cu là chu yêu su dung nhüng lòi giai thích chiên luoc .trù khi cô giai thích nhüng
doan mã rât phúc tap.

Nêu nhu nhüng kí tu // nhât quán su dung cho nhüng lòi giai thích .sau dó có thê su dung su kêt
hop /* */ dê làm nhüng lòi giai thích ngoài toàn bô phân mã trong suôt giai doan phát triên và gõ
rôi.

Ví du 1: Tài liêu cua file:
//
// File: test.cc
// Mô ta: This is a test program
// Rev: A
// Duoc tao: Thur. Oct 31, 1991, 12:30:14
// Tác gia: Erik Nyquist
// mail: erik.nyquist@eua.ericsson.se
//
// Ban quyên: 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.
//


Ví du 2:Lòi giai thích chiên luoc và sách luoc(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.Nhüng file chèn vào(Include files)
Qui tàc 6:
Môi file chèn vào phai chúa môt co chê ngàn chàn tính bôi cua các file chèn vào dó.
Qui tàc 7:
Theo nhüng loai dinh nghia duoc su dung(trong file biên dich và file chèn
vào) .chúng phai duoc chèn vào môt cách tách biêt:
• Nhüng lóp duoc su dung nhu nhüng lóp co so.
• Nhüng lóp duoc su dung nhu nhüng biên thành viên.
• Nhüng lóp xuât hiên nhu kiêu tra vê hoàc nhu môt kiêu dôi sô trong nguyên
mâu hàm hoàc hàm thành viên.
• Nguyên mâu hàm cho hàm hay hàm thành viên su dung trong hàm thành viên
inline duoc dinh nghia trong môt file.

Qui tàc 8:
Nhüng dinh nghia cua nhüng lóp cái mà chi duoc truy xuât qua con tro (*) hay
tham chiêu(&) sê không duoc chèn vào trong file chèn.
Qui tàc 9:
Không bao giò chi dinh nhüng thú liên quan dên tên UNIX trong chi thi #include
Qui tàc 10:
Môi file thi hành là bao gôm nhüng file liên quan :
• Nhüng khai báo cua nhüng kiêu và nhüng hàm su dung trong nhüng hàm duoc
thuc thi trong file.
• Nhüng khai báo cua nhüng biên và cua nhüng hàm thành viên su dung trong
nhüng hàm duoc thuc thi trong file.





Dê cu 10:
Su dung chi thi #include ” filename.h ”cho nhüng file chèn vào.
Dê cu 11:
Su dung chi thi #include < filename.hh >cho nhüng file trong thu viên.
Dê cu 12:
Dùng bao giò chèn file khác trong file “.cpp”


-Môt cách dê nhât dê không bi làp lai các file chèn vào thì dùng khôi # ifndef #define
vào dâu cua file và #endif cuôi file.

-Sô file chèn vào nên nho.nêu nhu môt file duoc chèn vào trong môt include file. sau dó trong
môi file thi hành dua vào nhüng file chèn lân thú hai và nó sê biên dich lai môi khi file dâu tiên bi thay
dôi. Môt su thay dôi don gian trong môt file có thê làm nó cân thiêt dê biên dich lai môt sô file lón hon.

- Nêu môt file chi chúa nhüng thông tin chi cân cho cho file biên dich thì không nên dua vào
bât cú file chèn nào.
-Phan biêt su khác nhau giüa nhüng chi thi chèn vào là cua nguòi dùng tu dinh nghia hay lây tù
thu viên.Nêu tên file chèn vào nàm giüa hai dâu “< “ và” >” thì bô tiên xu lí sê không tìm thây file này
trong thu muc màc dinh .Diêu này sê dân dên môi nguy hiêm không báo truóc duoc là su xung dôt lân
nhau giüa tên do nguòi dùng dinh nghia và tên trong thu viên chèn vào.
-Bàng viêc khai báo chuôi hàng cuc bô.trình biên dich tro nên nhanh hon.Diêu này có lê dê dàng
xác dinh phiên ban cua chuong trình duoc su dung.Chuôi phai bàt dâu boi kí tu “@(#) ”(Ví du 5)

Ví du 3:K„ thuât ngàn chàn su trùng tên cua nhüng file chèn vào:


#ifndef FOO_HH
#define FOO_HH
// Chú ‚ cuôi file phai có

#endif

Ví du 4: Dùng bao giò su dung duòng dân tuyêt dôi nhu:
//Không dê cu và không nên thuc hiên:

#include <../include/fnutt.h>
#include <sys/socket.h>


Ví du 5 :Môt hàng chuôi cuc bô dê nhân ra file thi hành
static const char* sccsid =
"@(#) Exception.cpp, rev. A, Copyright Ellemtel Utvecklings AB 1991";
Ví du 6: File chèn vào cho lóp 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

Ví du 7:File thi hành cho lóp 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 )
{
// ...
}




….Gán tên :


Qui tàc 10:
Tù dinh danh cho nhüng lóp toàn cuc. kiêu liêt kê. kiêu dinh nghia.hàm .hàng và
nhüng biên trong môt thu viên lóp tiên tô dó là unique cho thu viên.
Qui tàc 11:
Tên cua nhüng biên .nhüng hàng.nhüng hàm duoc bàt dâu vói môt chü cái
thuòng.
Qui tàc 12:
Tên cua nhüng kiêu dü liêu trùu tuong .nhüng câu trúc.kiêu dinh nghia.kiêu liêt
kê duoc bàt dâu vói chü cái hoa.
Qui tàc 13:
Trong nhüng tên nhiêu hon môt tù .nhüng tù duoc viêt liên nhau và môi tù phai
bàt dâu vói môt chü cái viêt hoa.
Qui tàc 14:
Không duoc su dung tù dinh danh vói môt hay hai duòng gach duói(‘_’ hay ’__’).
Qui tàc 15:
Môt tên tách biêt vói tiên tô cua nó là môt dâu gach duói(‘_’).
Qui tàc 16:
Môt tên bàt dâu vói môt chü cái hoa duoc xuât hiên ngay sau tiên tô cua nó.
Qui tàc 17:
Môt tên bàt dâu vói môt chü cái thuòng tách bach vói tiên tô cua nó boi dâu(‘_’).


Dê cu 13:
Không duoc su dung nhüng kiêu tên mà chi có khác nhau vê nhüng chü hoa và
chü thuòng.
Dê cu 14:
Tên không nên bao gôm nhüng chü viêt taàt mà không duoc châp nhân chung.
Dê cu 15:
Chon tên nhüng biên mà có tính chât goi ‚ su dung.
Dê cu 16:
Gói gon nhüng biên toàn cuc và nhüng hàng .kiêu liêt kê.kiêu dinh nghia trong
môt lóp.



Trong chuong này . thât là quan trong dê phân biêt giüa nhüng tù dinh danh và nhüng tên.
Tên là môt phân cua tù dinh danh cái mà biêu thi nghia cua nó.Môt tù dinh danh bao gôm môt tiên
tô.môt tên và môt hâu tô(theo thú tu).Tiên tô và hâu tô là tùy chon.Môt hâu tô chi duoc su dung boi
công cu mã C++ tông quát .dê tránh xung dôt giüa vói nhüng mã C++ do nguòi su dung viêt.
Su dung hai dâu gach duói (‘__’) trong tù dinh danh duoc dành riêng bên trong biên dich su dung theo
ANSI-C chu†n.
Nhüng dâu gach duói (‘_’) thuòng duoc su dung trong nhüng tên cua nhüng hàm thu viên (nhu là
“_main” và”_exit”).Dê tránh su xung dôt .không duoc bàt dâu tù dinh danh vói môt dâu gach.
Môt qui tàc chính yêu là dàt môt tên mà không duoc xác dinh rõ ràng là môt cách dàt tên tôi tê.Môt cái
tên dài thông thuòng tôt hon tên ngàn.tên khó hiêu.su càt x‡n cüng là vân dê cân phai xem x‡t.Nhüng
chü viêt tàt có thê luôn luôn gây su hiêu lâm.Nhüng biên toàn cuc,nhüng hàm .nhüng hàng phai là môt
cái tên du dài dê tránh su xung dôt nhung không quá dài.
Có rât nhiêu lóp có thê tân dung trong thu viên và gia su trong môt proˆect có hàng ngàn lóp .do vây
thât là quan trong dê dàt tên dê tránh su xung dôt xay ra.Môt cách dê ngàn chàn su xung dôt là phai có
môt qui tàc nghiêm khàc cho viêc gán tên dôi vói nhüng dôi tuong toàn cuc có thê thây duoc.Theo cách
này nhüng lóp tù trong thu viên có thê duoc su dung cùng môt lúc.

Tên cua nhüng kiêu sau dây phai có tiên tô:
• Tên kiêu(classes, typedefs, enums, structs, unions, etc).
• Nhüng hàng và nhüng biên toàn cuc.
• Nhüng tên hàm(không là các hàm thành viên)
• Các chi thi(#define)
Nhüng biên tinh trong môt lóp nên duoc su dung thay vì nhüng hàng .biên toàn cuc .kiêu dü liêu liêt kê
và dinh nghia.


Ví du 8: Chon tên:
int groupID; // instead of grpID
int nameLength; // instead of namLn
PrinterStatus resetPrinter; // instead of rstprt
Ví du 9:Nhüng tên mo hô:
void termProcess(); // Terminate process or
// terminal process?
Ví du 10: Tên vói nhüng kí tu sô có thê là nguyên nhân lôi vì khó dinh vi:
int I0 = 13; // Names with digits can be
int IO = I0; // difficult to read.





Ví du 11:Dinh nghia lóp trong lóp thu viên:
class Emc2Class
{
public:
Emc2Class(); // Default constructor
// ...
private:
int id;
// ...
};



Ví du 12:Môt cách dê tránh các hàm và các lóp toàn cuc:

// Thay vì khai báo:
void Emc2_myFunc1();
void Emc2_myFunc2();
class Emc2MyClass { /* ... */ };

//Gói gon nhüng hàm su dung lóp trùu tuong:
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;


‰.Phong cách(Style)

6.1.Nhüng lóp(Classes)



Qui tàc 18:
Nhüng thành phân protected ,public .và private trong môt class duoc khai báo theo
thú tu dó(dâu tiên là public dên protected và cuôi cùng là private).
Qui tàc 19:
Không môt hàm thành viên nào duoc dinh nghia trong môt lóp.


Viêc dàt khai báo public dâu tiên .moi thú quan tâm boi nguòi dùng duoc tâp hop trong diêm
bàt dâu cua viêc khai báo lóp. Phân protected có lê cüng duoc quan tâm boi nguòi thiêt kê khi xem x‡t
tính kê thùa cua môt lóp.Phân private chúa nhüng chi tiêt thuòng ít quan tâm hon.

Nhüng hàm thành viên duoc dinh nghia trong môt lóp tu dông tro thành hàm inline .Lòi dinh
nghia lóp là k‡m chàt chê và gàp nhiêu khó khàn dê doc khi dinh nghia chúng trong dó.Và nguoc lai
khi khai báo nhüng hàm thành viên inline o ngoài dinh nghia lóp thì nó sê tro thành nhüng hàm thông
thuòng.

Ví du 12:Môt dinh nghia lóp theo qui tàc cua phong cách :


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;
// ...
};


Ví du 13:Không dinh nghia hàm thành viên trong khai báo lóp:
// Thay vì viêt nhu sau:
class String
{
public:
int length() const // KHÔNG !!
{
return len;
}
// ...
private:
int len;
};

// Nên khai báo nhu sau:
class String
{
public:
int length() const;
// ...
private:
int len;
};

inline
int
String::length() const
{
return len;
}

6.2.Nhüng hàm(Functions)
Dê cu 17:
Khi khai báo môt hàm thì dâu ngoàc dâu tiên và dôi sô dâu tiên(nêu có) phai duoc
viêt trên cùng môt dƒng vói tên hàm. Nêu khoang trông cho ph‡p thì dâu ngoàc dóng
và các dôi sô khác cüng cùng môt dƒng.Cách khác môi dôi sô duoc viêt môt dƒng.
Dê cu 18:
Trong dinh nghia hàm thì kiêu tra vê phai phai viêt o môt dƒng cách biêt.
Dê cu 19:
Luôn luôn viêt dâu ngoàc bên trái ngay sau tên hàm.


Ví du 14:Dâu ngoàc trái luôn luôn viêt ngay sau tên hàm:

Void foo (); // KHŠNG TH‹!!
void foo(Œ• •• TŽT HON!
Ví du 15:Cách khai báo dúng và sai nhüng dôi sô trong dinh nghia hàm:
// Dúng:
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.3.Khôi lênh diêu khiên :
Dê cu 20:
Nhüng khôi lênh diêu khiên nhu if , else , for , while ,do… nên duoc theo sau boi môt
khôi ngay ca khi chúng trông.

Khi mà không có môt khôi thì ta có thê dê dàng dàt sau nó môt dâu châm ph†y và diêu này sê dân dên
su hiêu lâm khi doc mã và có thê dân dên chuong trình bi sai mà ta khó thây duoc.



Ví du 16:Câu trúc khôi lênh khi không có lênh bên trong:

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

// Empty block - better!
while ( /* Something */ )
{
// Empty !
}

6.4.Con tro và tham chiêu:
Dê cu 21:
Toán tu tro (*) và toán tu dia chi (&) nên dàt ngay sau kiêu tên trong khai báo và
dinh nghia.


Các kí tu ‘ * ’ và ‘ & ’ nên dàt ngay sau kiêu cua biên thay vì sau tên biên dê nhân manh ràng
chúng là phân cua kiêu dinh nghia.Thay vì khai báo ràng
*i là kiêu int thì khai báo int*.
Trong nhüng câu khai báo kiêu cua biên thì phai khai báo toán tu trong ngay sau tên biên dê
làm giam xác suât lôi.

Ví du 16: Khai báo vói ‘ & ’ và ‘ * ’ :

char*
Object::asString()
{
// Something
};

char* userName = 0;
int sfBook = 42;int& anIntRef = sfBook;

Ví du 17:Khai báo vài biên trong câu lênh có ( * ):
••Không nên khai báo
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)
Qui tàc 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 su dung biên toàn cuc (public variable) không duoc khuyênh khích bòi vì nhüng lí do sau dây:

1. Viêc su dung biên toàn cuc sê vi pham môt trong nhüng nguyên tàc co ban cua lâp
trình huóng dôi tuong – dó là tính bao dóng ( encapsulation). Ví du, nêu có môt lóp có kiêu là
BankAccount, trong dó account_balance là môt biên toàn cuc ( public variable), thì giá tri cua biên này
có thê bi thay dôi boi bât cú su truy câp nào tù bên ngoài. Tuy nhiên, nêu biên duoc khai bò là private,
giá tri cua nó chi có thê bi thay dôi boi nhüng hàm thành phân trong lóp dó
2. Bât cú hàm nào trong môt chuong trình üng có thê thay dôi giá tri cua public data.
Viêc này có thê gây ra nhüng lôi mà ta khó có thê xác dinh duoc.
3. Khi mà môt public data không duoc su dung, thì viêc thay dôi dü liêu cua biên này sê
không làm cho các class su dung class này phai thay dôi lai code cua mình. Tóm lai thì ta nên hiên thuc
môt lóp sao cho moi su thay dôi trong su hiên thuc cua lóp này sê không làm thay dôi nhüng lóp su
dung nó.
Viêc su dung nhüng biên protected trong môt class cüng không nên duoc khuyên khích, boi vì
nhüng biên protected này sê tro nên visible dôi vói nhüng lóp dân xuât ( derived class) cua nó. Tên cua
kiêu ( type) và biên ( variable) trong lóp co so ( base class) không nên thay dôi boi vì nhüng lóp dân
xuât ( derived class) có thê phu thuôc vào chúng. Nêu trong mô truòng hop nào dó, lóp dân xuât truy
xuât dên data trong lóp co so ( base class), môt giai pháp là viêt môt hàm protected trong base class tra
vê nhüng private data trong base class.
Han chê su dung struct boi vì nó chi chúa public data.

Ví du 18:Duói dây là cách dê dóng gói dü liêu ( encapsulate) sao cho có thê thay dôi 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 duoc chinh sua:
// Lâp trình viên chon thay dôi private data tù kiêu nguyên sang enum. Môt user cua class ‘Priority’
không phai thay dôi code, boi vì giá tri tra vê enum tù hàm thành phân ( member function)
priority()duoc tu dông chuyên sang kiêu 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 :
Dê cu 21:
Access functions nên là inline.
Dê cu 22:

Nhüng hàm chuyên tiêp nên inline.
Dê cu 23:

Constructor và destructor không nên là inline.

Lý do dê khai báo môt hàm là inline là dê tàng tôc dô thuc thi cua nó.
Nhüng hàm nho, chàng han nhu access function, tra vê giá tri cua môt thành phân ( member)
cua môt class và nhüng hàm forwarding sê thuc thi môt hàm khác ( cüng là hàm inline).
Viêc su dung hàm inline dúng chô sê dân dên viêc giam kích thuóc cua code.


Chú ý: - Nhüng hàm mà goi hàm inline khác thì sê tro nên phúc tap cho trình biên dich trong
viêc làm cho chúng inline, màc dù nhüng hàm này chi là nhüng hàm nho.
- Dây là vân dê thuòng hay gàp dôi vói constructor và destructor. Môt constructor luôn luôn goi
thuc thi môt constructor cua lóp co so ( base class) và nhüng dü liêu thành phân ( member data) truóc
khi thuc thi code cua nó. Nên tránh inline constructor và destructor.

7.3 Friends:

- Friends cua môt class nên cung câp thêm nhüng hàm mà duoc giü o ngoài class.
- Nhüng operation trên môt class dôi lúc duoc cung câp boi môt tâp hop cua class và hàm.
- Môt friend không phai là môt member cua môt class và duoc phép truy câp dên non-
public members cua class. Friends cung câp môt cách dê có thê “di ngõ sau” dôi vói su bao dóng dü liêu
( data encapsulation) cua môt class. Môt friend class duoc su dung dê cung câp hàm yêu câu dü liêu
hon là nhüng hàm cân thiêt boi class nhu thông thuòng.
- Gia su có môt class list cân môt con tro ( pointer) dê duyêt tât ca các element cua list. Con
tro này thi không cân thiêt cho các operation khác trên list. Trong môt vài truòng hop, chàng han nhu
cân tìm phân tu nho nhât cua list, thì thay vì tao môt iterato, chúng ta chúa con tro tro dên các element
cua list.
- Môt vân dê vói giai pháp này là class iterator không thê truy xuât dên câu trúc dü liêu
duoc su dung dê represent list ( boi vì chúng ta dã khuyênh khích dùng private date).
- Bàng cách khai báo iterator class nhu là môt friend class, vân dê này có thê duoc giai
quyêt mà không có vi pham tính bao dóng cua dü liêu ( data encapsulation).
- Su dung friend thì tôt nêu duoc su dung dúng lúc.


7.4 Hàm hàng thành viên:
Qui tàc 21:

- Môt hàm thành phân mà không thay dôi biên cua môt object thì duoc khai báo là const.
Qui tàc 22:
- Nêu hành dông cua môt object phu thuôc vào data bên ngoài objct thì data này không
nên duoc chinh sua ( modified) boi hàm thành phân const.

- Hàm thành phân ( member function) duoc khai báo là const không duoc chinh sua nhüng dü
liêu thành phân và chi nhüng hàm duoc goi trên nhüng dôi tuong hàng ( const object). ( Nhüng object
nhu vây coi nhu vô dung ( unusable ) nêu không có const method. Viêc khai báo const dam bao cho
object không bi chinh sua ( modified). Môt thuân loi lón duoc cung câp boi C++ là kha nàng overload
function dôi vói “tính chât hàng” ( const-ness) cua chúng. ( Hai hàm thành phân có thê có cùng tên ,
trong dó môt hàm là const và hàm còn lai thì không).
- Hoat dông cua môt object có thê bi anh huong boi dü liêu bên ngoài object. Nhüng dü
liêu nhu vây không nên duoc chinh sua boi môt const member function.




Ví du 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í du 20: Overloading an operator/function with respect to const-ness

#include <iostream.h>
#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:
Qui tàc 23:

- Môt class mà su dung “new” dê câp phát môt thuc thê (instance) duoc quan lý boi class,
phai dinh nghia môt constructor.
Qui tàc 24:
- Tât ca các class duoc su dung nhu môt base-class ( có hàm ao – virtual machine), phai
dinh nghia môt virtual destructor.
Dê cu 24:
- Tránh su dung dôi tuong toàn cuc ( global object) trong constructor và destructor.

- Môt copy cua constructor duoc khuyên khích dê truòng hop môt object duoc khoi tao su dung
môt object cùng kiêu. Nêu môt object quan lý su câp phát ( allocation) và hu• ( deallocation) môt object
trên vùng heap (dôi tuong quan lý su dung môt con tro tro dên object duoc tao boi constructor cua
class), chi nhüng giá tri cua con tro sê duoc copy. Diêu này có thê dân dên su hai invocation cua
destructor cho cùng môt object ( trên vùng heap), sê dân dên run-time error.

- Vân dê tuong tu xay ra dôi vói toán tu gán (“=”)

- Nêu môt class, có môt hàm ao nhung không có destructor ao, duoc su dung, there may be a
surprise if nhüng con tro tro dên class duoc su dung. Nêu môt con tro nhu vây duoc gán cho môt thuc
thê (instance) cua môt lóp dân xuât và nêu delete duoc su dung trên object này, chi destructor cua base
class duoc thuc thi. Nêu chuong trình phu thuôc vào su thuc thi destructor cua lóp dân xuât, chuong
trình sê fail.

- Liên quan dên su khoi tao cua nhüng object duoc câp phât tinh ( statically allocated object),
không có gì chàc chàn ràng nhüng dôi tuong tinh (static object) khác sê duoc khoi tao ( ví du, global
object). Boi vì thú tu khoi tao cua object tinh ( cái mà duoc dinh nghia trong nhüng don vi biên dich
khác nhau), thì không duoc dinh nghia trong dinh nghia cua ngôn ngü.
- Ban phai biêt nhüng gì ban dang làm nêu ban goi môt hàm ao tù môt constructor trong môt
class. Nêu môt hàm ao trong môt lóp dân xuât duoc overridden, dinh nghia ban dâu (original definition)
trong base class sê vân duoc thuc thi boi constructor cua base class. Override, then, không luôn luôn
work khi goi hàm ao trong constructor . Xem VD 30.
Ngoai lê dôi voi Rule 24:
- Dôi khi chúng ta muôn nhüng object trong môt class chia sê du liêu. Trong truòng
hop nhu vây, không cân thiêt phai dinh nghia môt copy constructor.

Ví du 21:Môt dinh nghia lóp “nguy hiêm” 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)] ) // Constructor
{
strcpy(sp,cp);
}
String::~String() // Destructor
{
delete sp;
}

// "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í du 22:Lóp “an toàn” có copy contructor và contructor màc dinh :

#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í du 23: Dinh nghia 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í du 24:Môt cách bao dam ràng môt dôi tuong toàn cuc duoc khoi tao :

// WARNING!!! Mã này không cho nguoi bát dâu hoc !!!

// 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 <new.h>

// ...
PortSetupInit::PortSetupInit() // Default constructor
{
if (!isPortSetup)
{
new (&portSetup) PortSetup;
isPortSetup = 1;
}
}

Ví du 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 tu gán:
Qui tàc 25:

- Môt class su dung “new” dê câp phát môt thuc thê duoc quan lý boi class, phai dinh
nghia toán tu gán.
Qui tàc 26:

- Môt toán tu gán thuc hiên môt destructive action phai duoc bao dam là không có thuc
hiên destructive trên object mà nó dang tác dông.
Dê cu 25:
- Môt toán tu gán phai tra vê tham chiêu hàng ( const reference) dên dôi tuong
gán (assigning object).
- Toán tu gán không duoc kê thùa nhu nhüng toán tu khác. Nêu toán tu gán không duoc dinh
nghia môt cách tuòng minh (explicitly), thì môt toán tu gán khác sê duoc tu dông dinh nghia. Nhüng
toán tu gán nhu vât không thuc hiên bit-wise copy dü liêu thành phân; thay vào dó, toán tu gán (duoc
dinh nghia) cho môi kiêu dü liêu thành phân duoc goi. Bit-wise copying chi duoc thuc hiên dôi vói dü
liêu thành phân có kiêu dü liêu nguyên thu• ( primitive).

- Môt hê qua cua viêc này là bit-wise copying duoc thuc hiên dôi vói dü liêu thành phân có kiêu
con tro. Viêc này sê dân dên môt vân dê: hoàc là goi destructor cho dôi tuong duoc quan lý nhiêu lân
hoàc là cô gàng su dung dôi tuong dã duoc hu• ( deallocated object). See Rule 25.

- Nêu môt toán tu gán duoc overload, lâp trình viên phai dam bao ràng lóp co so và toán tu gán
cua member chay.
- Môt lôi thuòng gàp là gán môt object cho chính nó. Bình thuòng, destructor môt thuc thê cái
mà duoc câp phát trên vùng nhó heap duoc goi truóc khi viêc gán duoc thuc thi. Nêu môt object duoc
gán cho chính nó, giá tri cua biên thuc thê sê bi mât boi vì nó duoc gán. Viêc này sê dãn dên run-time
errors. If a =a duoc dò ra, dôi tuong duoc gán không thay dôi.

Ví du 26: Giá tri tra vê dúng và không dúng tù toán tu 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í du 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á tai toán tu
Dê cu 26:

- Khi hai toán tu là nguoc nhau ( ví du nhu == va !=) thì nên dinh nghia ca hai.

- Operator Overloading có màt thuân loi lân bât loi. Môt thuân loi là code su dung class có
overloaded operators sê dê doc hon. Môt thuân loi khác là ngü nghia ( semantic) thì don gian và tu
nhiên. Môt bât loi là dê bi hiêu nhâm ý nghia cua overloaded operator ( nêu lâp trình viên không su
dung nghia thông thuòng). Ví du nhu toán tu công thì duoc dinh nghia lai vói ý nghia là trù và toán tu
trù duoc dinh nghia lai vói nghia là công .
- Dinh nghia môt thu viên class thì giông nhu viêc dinh nghia môt ngôn ngü. Nêu su dung
operator overloading, su dung nó theo lôi hiêu thông thuòng, không su dung nó nêu viêc này có thê dân
dên hiêu lâm.

7.8 Hàm thành phân tra và kiêu tra vê:
Qui tàc 27:

- Môt public member function không nên tra vê môt non-const reference hoàc con tro
dên dü liêu thành phân.
Qui tàc 28:
- Môt pubic member function không tra lai môt non-const reference hoàc môt con tro dên
dü liêu bên ngoài cua object ngoai trù truòng hop object chia s• dü liêu vói nhüng dôi
tuong khác.


- Bàng cách cho phép truy suât truc tiêp dên môt private member data cua môt object tù bên
ngoài, dü liêu này có thê bi thay dôi theo cách mà không dúng vói ý dinh thiêt kê class cua nguòi thiêt
kê. Viêc này làm giam su tin cây cua designer’s code.
- Môt truòng hop nguy hiêm nüa là su dung nhüng con tro tro dên vùng nhó dã bi hu• .
Rule 29 và 30 sê tránh truòng hop này.


Ví du 28:Dùng bao giò tra vê môt tham chiêu không phai là hàng dên dü liêu thành viên
tù hàm public:
class Account
{
public:
Account( int myMoney ) : moneyAmount( myMoney ) {};
const int& getSafeMoney() const { return moneyAmount; }
int& getRiskyMoney() const { return moneyAmount; } // No!
// ...
private:
int moneyAmount;
};

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 Kê thùa
Dê cu 27:

- Tránh su thùa kê cho quan hê parts-of ( cái này chi là thành phân cua cái kia).
Dê cu 28:
- Chi nên cho phép lóp dân xuât truy xuât dên dü liêu cua lóp co so bàng cách khai báo
protected access function.

- Môt lôi thuòng gàp nüa là su dung nhiêu lân su kê thùa cho quan hê parts-of ( khi môt object
chúa môt vài object khác, nhüng object này duoc kê thùa thay vì su dung nhüng biên thành phân. Diêu
này có thê dân dên môt câu trúc class la màt và code thì không có kha chuyên ( flexible) . Trong C++,
có thê có môt sô luong bât k‘ cua sô luong thuc thê cua môt kiêu dü liêu cho s’n; nêu su kê thùa duoc
su dung, su kê thùa truc tiêp tù môt class chi duoc su dung môt lân.

- Môt lóp dân xuât thuòng cân truy câp dên dü liêu thành phân cua lóp co so dê tao ra môt hàm thành
phân. Thuân loi trong viêc su dung hàm thành phân protected là tên cua dü liêu cua lóp co so không có
visible (duoc nhìn thây) trong lóp dân xuât và vì vây có thê bi thay dôi. Nhüng hàm truy xuât (access
function) nên tra lai giá tri cua dü liêu thành phân ( read-online acccess). Diêu này duoc thuc hiên môt
cách don gian bàng cách khai báo const function cho dü liêu thành phân.


8 . Lóp Template:
Dê cu 29:

- Không nên cô gàng dê tao môt thuc thê cua môt template class su dung kiêu mà không
dinh nghia nhüng hàm thành phân mà class template yêu câu.
Dê cu 30:

- C†n thân tránh dinh nghia nhiêu lân ( multiple definition) nhüng overloaded function
cùng vói su khoi tao cua class template.


- Trong C++ thì không thê chi rõ yêu câu cho kiêu cua dôi sô cua class template và function
template. Viêc này có nghia là kiêu thì duoc chon boi user, không tuân theo interface nhu yêu câu boi
template. Ví du, môt class template yêu câu kiêu dôi sô có toán tu so sánh duoc dinh nghia.
- Môt vân dê vói type template có thê nay sinh dôi vói overloaded function. Nêu môt hàm
duoc overload, có thê sê có xung dôt nêu kiêu dü liêu thành phân ( element type) xuât hiên tuòng minh
trong môt trong nhüng sô dó. Sau khi khoi tao, có thê có hai hàm có kiêu nguyên int nhu là môt dôi sô.
Trình biên dich có thê sê thông báo lôi, nhüng thât là nguy hiêm nêu nguòi thiêt kê class không chú ý
nó.
Ví du 29:Vân dê khi su dung kiêu tham sô:
template <class ET>
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 Dôi sô cua hàm ( function argument)
Qui tàc 29:

- Không su dung dôi sô cua hàm mà không chi rõ kiêu dü liêu ( kí hiêu dâu châm lung ).
Qui tàc 30:

- Tránh nhüng hàm có nhiêu dôi sô.
Qui tàc 31:

- Nêu môt hàm chúa môt con tro tro dên môt object (duoc truy câp thông qua dôi sô) thì
nên khai báo dôi sô có kiêu con tro. Su dung reference argument trong nhüng truòng
hop nhu thê này.
Dê cu 31:

- Su dung tham chiêu hàng ( const reference) ( const &) thay vì goi-bàng-giá -tri ( call-by-
value), trù khi su dung nhüng kiêu dü liêu duoc dinh nghia truóc hay con tro.

- Hàm thông dung su dung dôi sô không chi rõ (unspecified argument) là printf(). Viêc su dung
nhüng hàm nhu vây thì không nên duoc khuyên khích boi vì viêc kiêm tra kiêu khàc khe trong
C++.Trong môt vài truòng hop thì viêc su dung dôi sô không chi rõ (unspecified argument) có thê duoc
thay thê bàng chông hàm( overloading function) hoàc su dung dôi sô màc dinh ( default argument).


- Hàm vói môt danh sách dôi sô dài thì nhìn có v• phúc tap, khó dê doc và khó dê bao trì sau này. -
Bàng cách su dung tham chiêu ( reference) thay vì con tro nhu là dôi sô cua hàm thì code dê doc hon.
Môt bât loi là không dê dàng thây duoc hàm nào thay dôi giá tri cua dôi sô cua nó.

- Môt khác biêt giüa tham chiêu và con tro là không có tham chiêu null trong ngông ngü, trong khi có
null-pointer. Diêu này có nghia là môt dôi tuong phai duoc câp phát truóc khi truyên nó dên hàm.
Thuan loi o dây là không cân thiêt kiêm tra su tôn tai cua dôi tuong trong hàm.

- C++ goi hàm theo kiêu goi-bàng-tri ( call-by-value). Diêu này có nghia là nhüng dôi sô cua hàm
duoc copy vào stack thông qua viêc goi copy constuctor, viêc này sê dân dên giam hiêu qua thuc thi nêu
nhüng object dó là nhüng object lón. Ngoài ra, destructor sê duoc goi khi tôn tai hàm. Dôi sô “const &
“ có nghia là chi nhüng tham chiêu dên dôi tuong trong vân dê dang nói dên duoc dàt vào stack ( call-
by-reference) và trang thaía cua object( biên cua thuc thê) không thê chinh sua duoc .
Ví du 30 :Tham chiêu thay vì con tro :
// 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í du 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 Chông hàm ( Function overloading)

- Khi chông hàm thì moi biên thê nên có cùng chung môt ngü nghia (duoc su dung cho cùng môt
muc dích).
- Chông hàm là môt công cung manh dê tao ra môt ho nhüng hàm liên quan vói nhau mà chi
khá nhau o kiêu dü liêu cung câp boi dôi sô. Nêu không su dung nó môt cách hop lý ( chàng han nhu
nhüng hàm giông nhau vê tên duoc dùng cho nhüng muc díc khác nhau), có thê gây ra su nhâm lân.
Ví du 32:Ví du cho cách su dung dúng cua quá tai hàm:
class String
{
public: // Used like this:
// ... // String x = "abc123";
int contains( const char c ); // int i = x.contains( 'b' );
int contains( const char* cs ); // int j = x.contains( "bc1" );
int contains( const String& s ); // int k = x.contains( x );
// ...
};

9.3 Dôi sô hình thúc:
Qui tàc 32:

- Tên cua formal arguments dôi vói môt hàm duoc chi rõ và có thê giông nhau trong khai
báo hàm vâ trong dinh nghia cua hàm.

- Tên cua formal arguments duoc chi rõ trong dinh nghia hàm và trong khai báo hàm trong C++.
Cung câp tên cho dôi sô hàm là môt phân cua function documention. Tên cua dôi sô nên phan ánh duoc
dôi sô duoc su dung nhu thê nào, giam duoc viêc phai viêt comment, ví du, môt dinh nghia lóp.




Ví du 33 :Dôi sô hình thúc :
int setPoint( int, int ); // No !
int setPoint( int x, int y ); // Good

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

9.4 Giá tri và kiêu tra vê:
Qui tàc 33:

- Luôn luôn chi rõ môt cách tuòng minh kiêu tra vê cua môt hàm .
Qui tàc 34:

- Môt public function không nên tra lai tham chiêu hay con tro dên biên cuc bô.

- Hàm mà không có chi rõ kiêu tra vê trong khai báo thì sê ngâm dinh nhân kiêu tra vê là int.
Diêu này có thê gây nhâm lân, boi vì compiler sê warning là thiêu kiêu tra vê. Boi vì diêu này, nhüng
hàm khôgng có tra vê giá tri nào nên chi rõ kiêu tra vê là void.

- Nêu môt hàm tra vê tham chiêu hoàc con tro dên môt biên cuc bô, bô nhó mà nó tro tói sê bi
hu• khi tham chiêu hoàc con tro duoc su dung. Trong môt sô truòng hop thì Compiler sê give a
warning cho truòng hop này.


9.5 Hàm inline:
Qui tàc 35:

- Không su dung preprocesso directive #define dê làm cho code hiêu qua hon, thay vào dó,
su dung inline function.
Dê cu 32:
- Su dung inline function khi thât su cân thiêt.

- Inline function có thuân loi là nhanh hon hàm bình thuòng. Bât loi cua inline function là viêc
hiên thuc tro nên quá exposed, boi vì dinh nghia môt inline function phai duoc dàt trong môt include
file cua class, trong khi dinh nghia cua môt hàm bình thuòng duoc dàt trong môt file riêng biêt.
- Kêt qua là nhüng thay dôi trong su hiên thuc ( implementation) cua môt inline function
yêu câu re-compiling khi include file thay dôi. Viêc này chi dúng cho nhün môi truòng lâp trình dua
trên fiel ( file-based programming enviroment) su dung nhüng co chê nhu vây khi make for
compilation.
- Compiler không bàt buôc phai make môt function inline. Quyêt dinh cho vân dê này tu‘
thuôc vào compiler. Nhüng thông thuòng thì sê 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ó thê dân dên nhüng chuong
trình lón và châm môt cách không cân thiêt.
- Sê là hop lí nêu tách dinh nghia cua inline function ra khoi dinh nghia cua class và dàt
chúng vào môt file riêng biêt.

Ví du 34:Hàm inline tôt hon macro

// Ví du có vân dê voi #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 Dôi tuong tam thòi:
Dê cu 33:

- Giam thiêu sô object tam thòi duoc tao ra nhu là giá tri tra vê tù nhüng hàm hoàc nhu
là nhüng dôi sô cua hàm.

- Dôi tuong tam thòi thuòng duoc tao ra khi môt obect duoc tra vê tù môt hàm hoàc khi dôi
tuòng duoc truyên nhu là môt dôi sô cua hàm. Trong ca hai truòng hop, môt constructor cho object
duoc goi truóc, sau dó, destructor duoc goi. Nhüng dôi tuong tam vói kích thuóc lón làm cho code kém
hiêu qua. Trong môt vài truòng hop sê xuât hiên lôi khi dôi tuong tam duoc tao. Và môt diêu quan
trong nüa là không nên dùng con tro tro dên dôi tuong tam , boi vì thòi gian sôn ( lifetime) cua môt dôi
tuòng tam thi không xác dinh.( Xem 18.7)
Ví du 35 :Dôi tuong tam và môt cách dê loai 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 Tông quan:
Dê cu 34:

- Tránh nhüng hàm dài và phúc tap

- Nhüng bât loi cua môt hàm dài:
1. Nêu môt hàm quá dài thì sê khó dê hiêu khi doc.
2. Trong truòng hop có lôi trong môt hàm rât dài thì sê khó dê có thê xác dinh lôi và
“undo” truóc khi report the error to the calling function. Bàng cách su dung nhüng
hàm ngàn thì nhüng lôi này có thê dê dàng xác dinh duoc.
3. Nhüng hàm phúc tap thì khó dê test. Nêu môt hàm chúa dên 15 câu lênh if lông nhau
thì sê có 2^15 = 32768 nhánh khác nhau dê kiêm tra trong môt hàm.





10. Hàng (Constant)
Qui tàc 36:

Constant nên duoc dinh nghia su dung constant hoàc enum, thay vì # define.
Qui tàc 37:

Tránh su dung nhüng giá tri sô (numeric value) trong code. Thay vào dó nên su dung symbol
value.

Bô tiên xu lý ( preprocessor) thuc hiên su thay thê cho nhüng macro trong source code, rôi sau
dó source code duoc compile. Viêc này gây ra môt sô hâu qua không mong muôn. Ví du, nêu môt hàng
sô duoc dinh nghia dùng #define, tên cua hàng không duoc nhân ra trong nhiêu trình gõ rôi
( debugger). Nêu hàng duoc thay thê boi môt expression, thì expession này có thê duoc tính toán khác
nhau cho nhüng lân khoi tao khác nhau,tu‘ thuôc vào tâm vuc ( scope) cua tên biên.
Numerical value trong code ( thuòng duoc goi là “Magic Numbers”) nên tránh su dung boi vì nó có thê
gây ra nhüng khó khàn nêu chúng ta cân thay dôi giá tri cua chúng. Môt luong lón code có thê phu
thuôc vào môt giá tri (giá tri này không bao giò thay dôi), giá tri này có thê duoc su dung tai nhiêu vi
trí khác nhau trong code ( sê khó khàn dê xác dinh vi trí cua tât ca chúng), và nhüng giá tri nhu vây
hiêm khi anonymous ( có thê xay ra truòng hop là môi sô ‘2’ trong code không nhât thiêt phai duoc
thay thê boi tât ca các sô ‘3’).
Ví du 36:Nhiêu cách khác nhau dê khai báo hàng :
// 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. Biên(Variable)
Qui tàc 38:

Biên nên duoc khai báo vói tâm vuc nho nhât có thê.
Qui tàc 39:

Môi biên duoc khai báo bàng môt dòng riêng biêt.
Qui tàc 40:

Môi biên duoc khai báo nên duoc khoi tao môt giá tri nào dó truóc khi nó duoc su dung.


Qui tàc 41:

Nêu có thê thì su dung khoi tao ( initializatio) thay vì phép gán (assignment).


Môt biên nên duoc khai báo vói tâm vuc nho nhât có thê dê có thê nâng cao tính dê doc cua code, và
dê cho biên không duoc câp phát không cân thiêt. Khi môt biên duoc khai báo tai dâu cua môt hàm
duoc su dung o môt noi nào dó trong code, thì sê không dê dàn dê biêt truc tiêp kiêu cua biên dó. Ngoài
ra, còn có môt nguy co nüa là nhüng biên nhu vây thì tình cò bi †n nêu nó là biên cuc bô, có cùng tên,
duoc khai báo o môt khôi bên trong ( internal block).
Môt biên phai duoc khoi tao truóc khi su dung. Bình thuòng thì trinh biên dich sê canh báo nêu
môt biên chua duoc dinh nghia. Nhüng cüng nên c†n thân trong nhüng truòng hop nhu vây boi vì su
c†n thân vân không thùa. Thuc thê cua môt lóp thuòn duoc
khoi tao nêu không có dôi sô duoc cung câp trong phân khai báo ( empty constructor sê duoc goi). Dê
khai báo môt biên mà duoc khoi tao trong môt file khác, the keyword extern duoc su dung.
Bàng cách khoi tao môt biên truóc khi su dung, thay vì gán giá tri cho chúng truóc khi chúng
duoc su dung, code sê hiêu qua hon boi vì không có dôi tuong tam duoc tao ra trong su khoi tao. Dôi
vói nhüng object chúa môt luong lón dü liêu, viêc này có thê giúp nâng cao dáng kê tôc dô cua chuong
trình.
Chú ý: Trong môt sô truòng hop, môt biên duoc gánn giá tri cua môt biêu thúc phúc tap ;lúc dó
sê không cân thiêt khoi tao giá tri ban dâu cho biên. Xem VD 37
Ví du 37:Khoi tao thay vì gán:

//Không nên làm diê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 tro và tham chiêu:

Qui tàc 42:

Không so sánh con tro NULL hoàc gán NULL cho môt con tro, thay vì vây su dung 0.
Dê cu 35:

Con tro tro dên con tro nên tránh nêu có thê duoc.
Dê cu 36:

Su dung typedef dê don giam syntax cua progam khi khai báo môt con tro hàm.


Trong ANSI-C standard, NULL duoc dinh nghia hoàc là (void *) 0 hoàc 0. Nêu dinh nghia này
vân còn dúng trong ANSI-C++ thì sê nay sinh ra vân dê. Nêu NULL duoc dinh nghia là kiêu “void*),
nó không thê duoc gán cho bât cú con tro nào mà không ép kiêu môt cách tuòng minh (explicit type
conversion). Vì lí do này, nên so sánh vói 0 ít nhât cho dên khi ANSI-C++ committee dua ra quyêt dinh.
Con tro tro dên con tro thì thuòng không duoc su dung. Thay vì vây, môt lóp nên duoc khai báo,
trong dó có chúa môt biên thành phân là kiêu con tro. Viêc này nâng cao tính dê doc cua code và
khuyênh khích trùu tuong hoá dü liêu ( data abstraction). Bàn cách cai thiên tinh dê doc cua code, xác
xuât dê môt chuong trình chay dúng sê duoc nâng cao hon.

Môt hàm thay dôi giá tri cua con tro duoc cung câp duói dang dôi sô, nên khai báo dôi sô có
tham chiêu dên con tro ( e.g. char & c) .

Typedef là môt cách hay dê giúp code dê bao trì và kha chuyên ( portable). Xem 18.1,
Port.Rec.1. Môt lý do khác dê su dung typedef là tính dê doc cua code duoc cai thiên.
Con tro hàm có thê duoc su dung nhu hàm bình thuòng; chúng không cân dereferenced.
Ví du 38:So sánh su khác biêt cua nhüng con tro:
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í du 39:Con tro tro tói con tro là không cân thiêt:
#include <iostream.h>

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ê duoc viêt lai 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í du 40:Nhüng khai báo phúc tap:

// func1 là môt hàm: int -> (function : const char* -> int)
// tuc là hàm có môt dôi sô cua kiêu int và kiêu tra vê
// là môt con tro dên hàm có môt dôi sô kiêu const char*
// và tra 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í du 41:Cú pháp don gian nhüng hàm con tro su dung 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 kiêu:
Qui tàc 43:

Tránh su dung ép kiêu tuòng minh (explicit type conversion) ( casts).


Qui tàc 44:
Không viêt code phu thuôc vào nhüng hàm su dung ép kiêu không tuòng minh.

Qui tàc 45:
Không bao giò chuyên con tro tro dên dôi tuong cua lóp dân xuât thành con tro
tro dên dôi tuong cua lóp co so ao ( virtual base class)
Qui tàc 46:

Không chuyên môt const thành môt non-const


Môt su ép kiêu tuòng minh hoàc không tuòng mình, phu thuôc vào viêc nó duoc ordered bòi lâp
trình viên hoàc trình biên dich. Ép kiêu tuòng minh ( casts) duoc su dung khi lâp trình viên muôn get
around hê thông kiêu cua trình biên dich. Ép kiêu tuòng minh giüa nhüng dôi tuong khác kiêu sê làm
cho code khó dê doc.
Ép kiêu tuòng minh ( casts) nên duoc su dung trong truòng hop con tro lóp co so tro dên lóp
dân xuât duoc dùng. Viêc này xay ra khi, ví du, môt heterogeneous container class duoc su dung dê
hiên thuc môt container class dê chúa con tro dên dôi tuong dân xuât. Lóp mói này có thê duoc làm
“type-safe” nêu programmer exclude object khác hon là con tro lóp dân xuât from being stored. Dê su
thuc thi này hoat dông, diêu cân thiêt là con tro lóp co so duoc chuyên sang con tro lóp dân xuât khi
chúng duoc removed khoi heterogeneous container class.
Hai lý do trên cho viêc su dung explicit casts hoàn toàn không xuât hiên nüa khi template duoc
dua vào hoat dông trong C++.
Có hai kiêu ép kiêu không tuòng minh: hoàc là có môt su chuyên cua môt hàm tù kiêu này
thành kiêu khác, duoc viêt boi programmer, hoàc là trình biên dich sê thuc hiên nó theo chu†n cua
ngôn ngü. Nhung ca hai truòng hop có thê phát sinh vân dê.
C++ là môt ngôn ngü dê dãi trong vân dê biên mà duoc su dung nhu là dôi sô cua môt
hàm. Nêu không có hàm mà phù hop vói kiêu cua dôi sô thì compiler sê cô gàng dê convert kiêu dê tìm
môt kiêu phù hop. Cái bât loi o dây là nêu có nhiêu hon môt hàm phù hop duoc tìm thây, môt lôi biên
dich sê duoc phát sinh. Tê hon nüa là code mà compiler cho phép trong ngü canh này sê chúa lôi mà
khi môt su ép kiêu không tuòng minh duoc dùng trong code này.
Môt hiêu úng lê khác cua viêc ép kiêu không tuòng minh là dôi tuong tam duoc tao ra trong viêc
chuyên kiêu. Dôi tuong này sê là dôi sô cua hàm, không phai là dôi tuong gôc duoc truyên. Dinh nghia
cua ngôn ngü ngàn câm viêc gán môt dôi tuong tam cho môt non-constant reference, nhung phân lón
compiler vân cho phép diêu này. Trong phân lón truòng hop, viêc này có nghia là chuong trình sê
không hoat dông môt cách hoàn hao. Nên c†n thân vói constructor mà su dung chi môt dôi sô, boi vì
viêc này sê dân dên môt su ép kiêu mói mà trình biên dich có thê su dung môt cách không mong muôn
khi nó thây hop lý trong môt tình huông xác dinh.

Ngoai lê dôi vói Rule 43

Lóp co so ao cüng gây ra vân dê ép kiêu. Có thê chuyên môt con tro, tro dên môt thuc thê cua
môt class có lóp co so ao, dên môt con tro tro dên môt dôi tuong cua lóp co so ao. Su chuyên nguoc lai
không duoc phép, i.e. su chuyên kiêu không có tính dao nguoc. Vì lí do này, chúng ta không nên chuyên
môt con tro tro dên lóp lóp dân xuât tro dên môt con tro cua lóp co so ao.

Dê có thê tra vê dôi tuong tam non-const, dôi lúc viêc ép kiêu tuòng minh duoc su dung dê chuyên môt
const member data thành môt non-const. Dây không phai là môt thói quen lâp trình tôt, boi vì có thê là
trình biên dich sê câp phát nhüng hàng sô trên ROM.
Exception to Rule 44:

Ép kiêu tuòng minh duoc su dung dê chuyên môt con tro tro dên lóp co so thành môt con tro
tro dên lóp dân xuât trogn type-safe container class mà duoc hiên thuc
su dung heterogeneous container class.
Ép kiêu tuòng minh duoc su dung dê chuyên môt anonymous bit-stream thành môt object. Viêc
này xay ra khi unpacking môt message thành môt message buff•. Tóm lai, Ép kiêu tuòng minh duoc su
dung dê doc môt external representation cua môt object.
Exception to Rule 45:

Nêu môt lóp co so ao chúa môt hàm ao, mà hàm ao này chuyên con tro tro dên lóp co so thành
con tro tro dên lóp dân xuât, viêc này có thê thuc hiên bàng cách dinh nghia hàm trong lóp dân xuât.
Chú ý ràng viêc này có nghia là tât ca lóp dân xuât phai duoc hiêu trong lóp co so ao.
Ví du 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í du 43:Môt cách su dung ép kiêu †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í du 44:Khi ép kiêu †n cho kêt qua 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 ); // iu gì xy ra ây:
// int T = int( ui ); // Implicit conversion
// mySwap( i, T ); // ui is of course not changed!
// Fortunately, the compiler warns for this !
Ví du 45:Ép kiêu tù con tro cua lóp gôc dên con tro cua lóp ao là không thê thay dôi
duoc
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í du 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í du 47:Cho viêc thi hành hiêu qua hon, gõ bo nhüng const-ness khi su dung kêt qua
trung gian:
//Doan mã này không duoc dê cu

#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í du 48: Liên tuc loai bo const-ness cho viêc thuc thi có hiêu qua
// Doan mã này là an toàn hon ví du 47 nhung có thê kém hiêu qua

#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 diêu khiên (Flow Control Structures)
Qui tàc 47:

Code sau label case phai luôn luôn duoc kêt thúc boi break.
Qui tàc 48:

Môt phát biêu switch phai luôn luôn chúa môt default branch (dê dê phòng
truòng hop ngoai lê phát sinh).
Qui tàc 49:

Không bao giò su dung goto.
Qui tàc 50:

Viêc lua chon câu trúc làp ( for, while, do-while) phu thuôc vào dàc diêm cua vòng làp.

Dê cu 37:

Luôn luôn su dung unsigned cho biên mà không có giá tri âm
Dê cu 38:
Nên su dung inclusive lower limit và exclusive upper limits.
Dê cu 39:
Tránh su dung continue
Dê cu 40:

Su dung break dê thoát khoi vòng làp nêu vi“c này tránh su dung cò.
Dê cu 41:

Không viêt biêu thúc lô-gíc theo kiêu if (test) or if (!test) khi test là môt pointer.


Môi câu trúc làp có môt su hüu dung riêng. Câu trúc for duoc su dung khi biên làp ( loop
variable) tàng môt luong không dôi cho môi lân làp và khi diêu kiên kêt thúc cua vòng làp duoc xác
dinh boi môt biêu thúc hàng. Trong truòng hop khác, while or do-while nên duoc su dung. Khi diêu
kiên kêt thúc duoc tính toán tai dâu cua vòng làp, while nên duoc su dung; do-while duoc su dung khi
diêu kiên kêt thúc duoc tính toán tai cuôi vòng làp.
Goto thoát khoi luông diêu khiên ( flow control) và có thê dân dên viêc khó hiêu code. Ngoài ra,
có su giói han khi goto duoc su dung. Ví du, không duoc phép nhay tro lai môt câu lênh mà khoi tao
môt object cuc bô có destructor.
Nhüng biên mà thuòng duoc dùng dê miêu ta kích thuóc và chiêu dài thuòng duoc khai báo là
unsigned. Bàng cách su dung cách này có thê tránh duoc môt vài lôi khó chiu phát sinh mà ta không
kiêm soát duoc.
Tôt nhât là nên su dung inclusive lower và exclusive upper limits. Thay vì nói ràng biên x
trong khoang x>=23 và x<=42, su dung giói hàn x>=23 và x<43. Viêc này có nhüng loi ích sau:
+ Kích thuóc cua khoang biên thiên cua x là hiêu cua hai giói han ( 43-23).
+ Giói han bàng nhau nêu khoang biên thiên là rông.
+ Giói han trên không bao giò nho hon giói han duói.
Bàng cách trên thì nhiêu lôi có thê tránh duoc.
Nêu code sau lable case không kêt thúc boi break, viêc thuc thi tiêp túc sau lable case kê tiêp.
Viêc này sê gây ra lôi cho chuong trình.
Continue có thê duoc su dung dê thoátt khoi vòng làp. Tuy nhiên, code có thê sê dê hiêu hon
bàng cách su dung else boi .
Chú ý dên tâm vuc mà biên chay ( iteratioin variable) visible. Môt biên duoc khai báo trong
vong for thì chi visible trong khôi duoc bao boi càp dâu “{}” cua vòng for dó.
Exception to Rule 47:
Khi môt vài label case có su dung chung môt block code, chi môt phát biêu break là cân thiêt.
Ví du 49:Vân dê su dung kiêu unsigned trong biên cua vòng làp:
for( unsigned int i = 3; i >= 0; --i )
{
// Vòng làp sê không bao giò dùng, tù khi i di 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í du 50:Khai báo dã duoc nhìn thây trong vòng for:
for ( int index = 0; index < 10; index++ )
{
cout << index;
}

int index = 3; // LÓI, DÂY LÀ MOT SU KHAI BÁO LAI KHÔNG HOP LÍ CUA index
// BOI VÌ index DUOC KHAI BÁO TRONG VÒNG FOR.

Ví du 51:Câu lênh switch/case và su nguy hiêm
switch ( tag )
{
case A:
{
// Không làm cái gì
// Lênh kê tiêp duoc goi dên foo()trong case kê tiêp
}

case B:
{
foo();
// Không làm cái gì
break; // Bây gio thi chúng ta thoát lênh switch
}

default:
{
// If no match in above cases, this is executed
exit( 1 );
}
}

Ví du 52:Nhüng cách tôt và xâu su bô trí có giói han cho nhüng biên trong vòng làp
int a[10];
int ten = 10;
int nine = 9;

// Cách tt làm iu này:
for( int i = 0; i < ten; i++ ) // Loop runs 10-0=10 times
{
a[i] = 0;
}

// Xu khi làm nh sau:
for( int j = 0; j <= nine; j++ ) // Loop runs 10 times, but 9-0=9 !!!
{
a[j] = 0;
}

Ví du 53:Su dung break dê thoát vòng làp ,không flags cân thiêt

do // Cách này:
{
if ( Something )
{
// Do something
break;
}
} while( someCondition );


int endFlag = 0; // là tôt hon cách sau:
do
{
if ( /* Something */ )
{
// Do something
endFlag = 1;
}
} while( someCondition && !endFlag );

Ví du 53:Bàng cách thêm vào else, continue cân tránh dê code dê hiêu hon:

while( /* Something */ ) //Cách này rõ ràng
{
if( /* Something */ )
{
// Do something
}
else
{
// Do something else
}
}


while( /* Something */ ) // hon su dung continue
{
if( /* Something */ )
{
// Do something
continue; // Không duoc!
}
// Do something else
}







15. Biêu thúc(Expression)
Dê cu 42:

Su dung dâu ngoàc don dê làm rõ ràng thú tu tính toán cua toán tu trong biêu thúc.

Cô môt vài lôi hay gàp trong viêc tính toán môt biêu thúc. Toán tu hai ngôi ( binary operator)
trong C++ có tính kêt hop ( trái hoàc phai) và dô uu tiên. Nêu môt toán tu có tính kêt hop trái và xuât
hiên o hai bên cua môt biên trong môt biêu thúc, thì biên thuôc vê cùng môt phàn cua biêu thúc nhu là
toán tu bên phía trái cua nó.
Môt nhâm lân phô biên hay gàp là toán tu gán(assignment) và toán tu bàng( equality). Ví du,
toán tu << ( shift left) và >> ( shift right) thuòng duoc su dung trong input và output. Boi vì dây là
nhüng toán tu bit, chúng có dô uu tiên cao hon so vói toán tu quan hê ( relational operator). Diêu này
có nghi là dâu ngoàc don phai duoc su dung khi xuât giá tri cua biêu thúc logic.
Ví du 54:Vân dê khi uóc luoc các dâu ngoàc

// Interpreted as ( a<b ) < c, not ( a<b ) && ( b<c )
if ( a < b < c )
{
// ...
}

// Interpreted as a & ( b < 8 ), not ( a & b ) < 8
if ( a & b < 8 )
{
// ...
}
Ví du 55:Dâu ngoàc don duoc dê cu

int i = a >= b && c < d && e + f <= g + h; // Không nên!
int j = ( a >= b ) && ( c < d ) && (( e + f ) <= ( g + h )); // Tt hn




16. Câp phát bô nhó:
Qui tàc 51:

Không su dung malloc, realloc or free.
Qui tàc 52:

Luôn luôn dùng empty brackets (“[]”) cho delete khi deallocate môt array.
Dê cu 43:

Tránh su dung dü liêu toàn cuc nêu có thê.
Dê cu 44:

Dùng có câp phát bô nhó và hy vong ràng sê có ai dó deallocate nó sau này.
Dê cu 45:

Luôn luôn gán môt giá tri mói cho môt con tro mà tro dên vùng nhó dã bi deallocate.


Trong C++ dü liêu có thê duoc câp phát, dông trên stack, hoàc dông trên heap. Có ba kiêu dü
liêu tính: dü liêu toàn cuc, dü liêu lóp toàn cuc ( global class data) và dü liêu tinh cuc bô dôi vói môt
hàm ( static data local to a function).

Sê là nguy hiêm nêu :
1. goi hàm delete môt con tro obtained vai maaloc/realloc,
2. goi hàm malloc/realloc cho nhüng lóp có constructor.
3. goi hàm free cho bât cú cái gì mà duoc câp phát boi “new”
Vì vây, tránh nêu có thê viêc su dung malloc, realloc, và frê.
Nêu môt array a có kiêu T duoc câp phát, viêc quan trong là goi delete theo dúng cách. Chi viêt
delete a, sê dân dên destructor duoc thuc hiên chi for first object cua kiêu T. Bàng cách viêt
delete [m] a, m là môt sô nguyên lón hon sô luòng dôi tuong duoc câp phát truóc dây,
destructor cua T sê duoc goi cho vùng bô nhó àm không represent lóp kiêu T. Cách don gian
nhât dê làm viêc này là viêt delete ou a; boi vì destructor sê duoc thuc thi chi cho nhüng object
dã duoc câp phát truóc dây.

Ví du 56: Cách dúng và sai dê xóa môt mang vói destructors
int n = 7;
T* myT = new T[n]; // T is a type with defined constructors and destructors
// ...
delete myT; // Không thê! Destructor chi duoc goi cho dôi tuong dâu tiên trong mang
delete [10] myT; // Không thê! Destructor called on memory out of bounds in array a

delete [] myT; // Tôt, và luôn luôn an toàn!

Ví du 57:Nhüng nguy hiêm khi câp phát bô nhó:
String myFunc( const char* myArgument )
{
String* temp = new String( myArgument );
return *temp;
//temp là không bao gio deallocated và nguoi su dung hàm myFunc không thê deallocate
// boi vì môt ban tam cua instance không duoc tra lai.
}






17. Mã linh dông(Portable Code)

17.1 Data Abstraction ( Trùu tuong hoá dü liêu)
Dê cu kha chuyên 1:
Tránh su dung truc tiêp nhüng kiêu dü liêu dã duoc dinh nghia truóc trong khai báo.

Môt cách tuyêt vòi dê chuyên your world thành “thung lüng nuóc màt” ( vale of tears) là su
dung truc tiêp nhüng dü liêu duoc dinh nghia s’n trong khai báo. Nêu sau này,trong truòng hop cân
thiêt, boi vì vân dê portability, dê thay dôi kiêu tra vê cua môt hàm, có thê sê thay dôi nhiêu noi trong
code. Môt cách dê tránh diêu này là khai báo môt kiêu tra vê mói su dung nhüng lóp hoàc typedef dê
miêu ta kiêu cua biên duoc su dung. Bàng cách này, ta có thê dê dàng tao su thay dôi hon. Viêc này có
thê duoc su dung dê gán môt don vi dü liêu vât lý, chàng han nhu kilogram hay meter. Nhüng doan
code nhu va”a thì dê dàng xem lai hon ( Ví du, khi code không chay tôt, có thê là môt biên miêu ta
meter duoc gán cho môt biên miêu ta kilogram). Chú ý ràng typedef không tao ra kiêu mói, chi là môt
cái tên khác cho môt kiêu. Có nghia là nêu khai báo typedef int Error, môt biên có kiêu Error có thê
duoc su dung o bât cú noi dâu mà biên ini duoc su dung
Ví du 58:Kiêu khai báo su dung typedef
// Thay vì
long int time;
short int mouseX;
char* menuName;

// Su dung (for example):
typedef long int TimeStamp;
typedef short int Coordinate;
class String { /* ... */ };

// và:
TimeStamp time;
Coordinate mouseX;
String menuName;

17.2 Kích thuóc cua kiêu:
Dê cu kha chuyên 2:
Không nên nghi ràng môt biên kiêu int và long có cùng kích thuóc.
Dê cu kha chuyên 3:
Không nên nghi ràng môt biên int dài 32 bits ( nó có thê chi dài có 16 bits).
Dê cu kha chuyên 4:
Không nên nghi ràng môt char là có dâu hay không dâu.
Dê cu kha chuyên 5:
Luôn luôn gán char to unsigned if 8-bit ASCII duoc su dung.

Trong dinh nghia cua ngôn ngü C++ thì môt char chua biêt là có dâu hay không dâu. Viêc này
phu thuôc vào compiler. Nêu su dung char theo cách này hay theo cách khác ( có dâu hay không có
dâu), thì có thê sê có bugs xuât hiên truogn chuong trình khi compiler khác duoc su dung.
Nêu 8-bits ASCII duoc su dung và phép so sánh hai kí tu duoc thuc hiên, thì unsigned char
duoc su dung.
17.3 Chuyên kiêu
Dê cu kha chuyên 6:
C†n thân nêu chuyên kiêu tù kiêu ngàn hon thành kiêu dài hon.
Dê cu kha chuyên 7:
Không nên nghi ràng pointer và integer có cùng kích thuóc.
Dê cu kha chuyên 8:
Su dung Ép kiêu tuòng minh cho nhüng phép tính sô hoc su dung giá tri không dâu và có dâu.


Kiên trúc cua bô vi xu lý thuòng câm viêc môt dü liêu có kích thuóc cô dinh duoc câp phát cho
môt dia chi bât kì nào dó. Ví du, môt tù phai bàt dâu bàng môt dia chi “chàng” fo MC680x0. Nêu có
môt con tro tro dên môt char mà duoc xác dinh là có dia chi “l•”, môt su chuyên dôi kiêu tù con tro tro
dên kí tu này thành con tro int sê là cho chuong trình dúng khi con tro int duoc su dung, boi vì viêc
này vi pham nguyên tàc cua bô xu lý trong viêc gán dü liêu.

17.4 Mô ta dü liêu (Data Representation)
Dê cu kha chuyên 9:
Không nên nghi ràng dü liêu kiêu long,float, double, hay long double bàt dâu o bât cu dia
chi nào.

Viêc biêu diên kiêu dü liêu trong bô nhó thì phu thuôc rât nhiêu vào máy tính. Bàng cách câp
phát data members cho môt vùng nhó nào dó, bô vi xu lý thuc thi code hiêu qua hon. Boi vì diêu này,
câu trúc dü liêu mà biêu diên môt lóp sê duoc chúa theo nhüng cách khác nhau trong nhüng kiên trúc
máy tính khác nhau. Code phu thuôc vào môt specific represention thì không thê nói là portable duoc.
17.5 Underflow/Overflow
Dê cu kha chuyên 10:
Không nên nghi ràng dôi tuong tinh duoc khoi tao theo môt trât tu cho truóc.

Nêu giá tri duoc chinh sua hai lân trong cùng môt biêu thúc, kêt qua cua biêu thúc thì không
duoc xác dinh ngoai trù khi thú tu tính toán duoc dam bao cho nhüng toán tu su dung nó.
Thú tu khoi tao nhüng dôi tuong tinh có thê sê làm phát sinh ra môt sô vân dê. Môt dôi tuong tinh
không duoc su dung trong constructor, nêu nó không duoc khoi tao cho dên sau khi constructor duoc
goi thuc thi. Lúc này, thù tu khoi tao cua nhüng dôi tuong tinh, duoc dinh nghia trong nhüng don vi
biên dich khác nhau, thì không duoc xác dinh. Viêc này dân dên nhüng lôi mà khó dê xác dinh . Có vài
ki thuât dê tránh tình trang này .





Ví du 59: Do not depend on the order of initialization in constructors.
#include <iostream.h>
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í du 60:Khoi tao môt dôi tuong tinh(static objects)

// Foo.hh

#include <iostream.h>
#include <string.h>

static unsigned int const Size = 1024;

class Foo
{
public:
Foo( char* cp ); // Constructor
// ...
private:
char buffer[Size];
static unsigned counter; // Number of constructed Foo:s
};

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"

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 Dôi tuong tam :
Dê cu kha chuyên 11:
- Không viêt code mà phu thuôc vào thòi gian sông cua dôi tuong tam.
- Dôi tuong tam thuòng duoc tao ra trong C++, chàng han nhu khi hàm tra vê môt giá tri. Nhiêu lôi
khó xác dinh có thê phát sinh khi có môt con tro tro dên môt dôi tuong tam.
Ví du 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
Dê cu kha chuyên 12:

Tránh su dung toán tu shift thay cho toán tu sô hoc
Tránh su dung pointer arithmetic
Pointer arithmetic thì linh dông. Toán tu “==” và “!=”duoc dinh nghia cho tât ca các pointer cua cùng
kiêu dü liêu, trong khi toán tu <,>,<=,>= thì linh dông chi khi chúng duoc su dung giüa nhüng con tro
mà tro dên cùng môt mang.



18.Sách tham khao

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 0-
210-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-8053-
0091-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.

Sign up to vote on this title
UsefulNot useful