You are on page 1of 24

Chng 8.

Ti nh ngha

Chng ny tho lun v ti nh ngha hm v ton t trong C++. Thut ng ti nh ngha (overloading) ngha l cung cp nhiu nh ngha. Ti nh ngha hm lin quan n vic nh ngha cc hm ring bit chia s cng tn, mi hm c mt du hiu duy nht. Ti nh ngha hm thch hp cho: nh ngha cc hm v bn cht l lm cng cng vic nhng thao tc trn cc kiu d liu khc nhau. Cung cp cc giao din ti cng hm.

Ti nh ngha hm (function overloading) l mt tin li trong lp trnh. Ging nh cc hm, cc ton t nhn cc ton hng (cc i s) v tr v mt gi tr. Phn ln cc ton t C++ c sn c ti nh ngha ri. V d, ton t + c th c s dng cng hai s nguyn, hai s thc, hoc hai a ch. V th, n c nhiu nh ngha khc nhau. Cc nh ngha xy dng sn cho cc ton t c gii hn trn nhng kiu c sn. Cc nh ngha thm vo c th c cung cp bi cc lp trnh vin sao cho chng cng c th thao tc trn cc kiu ngi dng nh ngha. Mi nh ngha thm vo c ci t bi mt hm. Ti nh ngha cc ton t s c minh ha bng cch s dng mt s lp n gin. Chng ta s tho lun cc qui lut chuyn kiu c th c s dng nh th no rt gn nhu cu cho nhiu ti nh ngha ca cng ton t. Chng ta s trnh by cc v d ca ti nh ngha mt s ton t ph bin gm << v >> cho xut nhp, [] v () cho cc lp cha, v cc ton t con tr. Chng ta cng s tho lun vic khi to v gn t ng, tm quan trng ca vic ci t chnh xc chng trong cc lp s dng cc thnh vin d liu c cp pht ng. Khng ging nh cc hm v cc ton t, cc lp khng th c ti nh ngha; mi lp phi c mt tn duy nht. Tuy nhin, nh chng ta s thy trong chng 8, cc lp c th c sa i v m rng thng qua kh nng tha k (inheritance).
Chng 8: Ti nh ngha
122

8.1. Ti nh ngha hm
Xem xt mt hm, GetTime, tr v thi gian hin ti ca ngy theo cc tham s ca n, v gi s rng cn c hai bin th ca hm ny: mt tr v thi gian theo giy tnh t na m, v mt tr v thi gian theo gi, pht, giy. R rng cc hm ny phc v cng mc ch nn khng c l do g li cho chng c nhng ci tn khc nhau. C++ cho php cc hm c ti nh ngha, ngha l cng hm c th c hn mt nh ngha:
long GetTime (void); // s giy tnh t na m void GetTime (int &hours, int &minutes, int &seconds);

Khi hm GetTime c gi, trnh bin dch so snh s lng v kiu cc i s trong li gi vi cc nh ngha ca hm GetTime v chn mt ci khp vi li gi. V d:
int h, m, s; long t = GetTime(); GetTime(h, m, s); // khp vi GetTime(void) // khp vi GetTime(int&, int&, int&);

trnh nhm ln th mi nh ngha ca mt hm c ti nh ngha phi c mt du hiu duy nht. Cc hm thnh vin ca mt lp cng c th c ti nh ngha:
class Time { //... long GetTime (void); // s giy tnh t na m void GetTime (int &hours, int &minutes, int &seconds); };

Ti nh ngha hm gip ta thu c nhiu phin bn a dng ca hm m khng th c c bng cch s dng n c cc i s mc nh. Cc hm c ti nh ngha cng c th c cc i s mc nh:
void Error (int errCode, char *errMsg = ""); void Error (char *errMsg);

8.2. Ti nh ngha ton t


C++ cho php lp trnh vin nh ngha cc ngha thm vo cho cc ton t xc nh trc ca n bng cch ti nh ngha chng. V d, chng ta c th ti nh ngha cc ton t + v cng v tr cc i tng Point:
class Point { public: Point (int x, int y) {Point::x = x; Point::y = y;}

Chng 8: Ti nh ngha

123

Point operator + (Point &p) {return Point(x + p.x,y + p.y);} Point operator - (Point &p) {return Point(x - p.x,y - p.y);} private: int x, y; };

Sau nh ngha ny th + v c th c s dng cng v tr cc im ging nh l chng c s dng cng v tr cc s:


Point p1(10,20), p2(10,20); Point p3 = p1 + p2; Point p4 = p1 - p2;

Vic ti nh ngha cc ton t + v nh trn s dng cc hm thnh vin. Mt kh nng khc l mt ton t c th c ti nh ngha ton cc:
class Point { public: Point (int x, int y) {Point::x = x; Point::y = y;} friend Point operator + (Point &p, Point &q) {return Point(p.x + q.x,p.y + q.y);} friend Point operator - (Point &p, Point &q) {return Point(p.x - q.x,p.y - q.y);} private: int x, y; };

S dng mt ton t ti nh ngha tng ng vi mt li gi r rng ti hm thi cng n. V d:


operator+(p1, p2) // tng ng vi: p1 + p2

Thng thng, nh ngha mt ton t xc nh trc th chng ta nh ngha mt hm tn operator . Nu l mt ton t nh hng:

operator phi nhn chnh xc mt i s nu c nh ngha nh mt thnh vin ca lp, hoc hai i s nu c nh ngha ton cc.

Tuy nhin, nu l mt ton t n hng:

operator phi nhn khng i s nu c nh ngha nh mt thnh vin ca lp, hoc mt i s nu c nh ngha ton cc.

Bng 8.1 tng kt cc ton t C++ c th c ti nh ngha. Nm ton t cn li khng c ti nh ngha l:


. .* :: ?: sizeof

Chng 8: Ti nh ngha

124

Bng 8.1

Cc ton t c th ti nh ngha.
n hng

+ new + = ==

* delete * += -= != <

! / /= >

~ % %= <=

& & &= >=

++ | |= & &

-^ ^= ||

() << << = []

-> >> >> = ()

->*

Nh hng

Ton t n hng (v d ~) khng th c ti nh ngha nh nh hng hoc ton t nh hng (v d =) khng th c ti nh ngha nh ton t n hng. C++ khng h tr nh ngha ton t new bi v iu ny c th dn n s m h. Hn na, lut u tin cho cc ton t xc nh trc c nh v khng th c sa i. V d, d cho bn ti nh ngha ton t * nh th no th n s lun c u tin cao hn ton t +. Cc ton t ++ v - c th c ti nh ngha nh l tin t cng nh l hu t. Cc lut tng ng khng c p dng cho cc ton t ti nh ngha. V d, ti nh ngha + khng nh hng ti += tr phi ton t += cng c ti nh ngha r rng. Cc ton t ->, =, [], v () ch c th c ti nh ngha nh cc hm thnh vin, v khng nh ton cc. trnh sao chp cc i tng ln khi truyn chng ti cc ton t ti nh ngha th cc tham chiu nn c s dng. Cc con tr th khng thch hp cho mc ch ny bi v mt ton t c ti nh ngha khng th thao tc ton b trn con tr.

V d: Cc ton t trn tp hp
Lp Set c gii thiu trong chng 6. Phn ln cc hm thnh vin ca Set c nh ngha nh l cc ton t ti nh ngha tt hn. Danh sch 8.1 minh ha.

Chng 8: Ti nh ngha

125

Danh sch 8.1 1 #include <iostream.h> 2 const maxCard = 100; 3 enum Bool {false, true}; 4 class Set { 5 public: 6 Set(void) { card = 0; } 7 friend Bool operator & (const int, Set&); 8 friend Bool operator == (Set&, Set&); 9 friend Bool operator != (Set&, Set&); 10 friend Set operator * (Set&, Set&); 11 friend Set operator + (Set&, Set&); 12 //... 13 void AddElem(const int elem); 14 void Copy (Set &set); 15 void Print (void); 16 private: 17 int elems[maxCard]; 18 int card; 19 };

// thanh vien // bang // khong bang // giao // hop

// cac phan tu cua tap hop // so phan tu cua tap hop

y, chng ta phi quyt nh nh ngha cc hm thnh vin ton t nh l bn ton cc. Chng c th c nh ngha mt cch d dng nh l hm thnh vin. Vic thi cng cc hm ny l nh sau.
Bool operator & (const int elem, Set &set) { for (register i = 0; i < set.card; ++i) if (elem == set.elems[i]) return true; return false; } Bool operator == (Set &set1, Set &set2) { if (set1.card != set2.card) return false; for (register i = 0; i < set1.card; ++i) if (!(set1.elems[i] & set2)) // s dng & ti nh ngha return false; return true; } Bool operator != (Set &set1, Set &set2) { return !(set1 == set2); // s dng == ti nh ngha } Set operator * (Set &set1, Set &set2) { Set res; for (register i = 0; i < set1.card; ++i) if (set1.elems[i] & set2) // s dng & ti nh ngha res.elems[res.card++] = set1.elems[i];

Chng 8: Ti nh ngha

126

return res;

Set operator + (Set &set1, Set &set2) { Set res; set1.Copy(res); for (register i = 0; i < set2.card; ++i) res.AddElem(set2.elems[i]); return res;

C php s dng cc ton t ny ngn gn hn c php ca cc hm m chng thay th nh c minh ha bi hm main sau:
int main (void) { Set s1, s2, s3; s1.AddElem(10); s1.AddElem(20); s1.AddElem(30); s1.AddElem(40); s2.AddElem(30); s2.AddElem(50); s2.AddElem(10); s2.AddElem(60); cout << "s1 = "; cout << "s2 = "; s1.Print(); s2.Print();

if (20 & s1) cout << "20 thuoc s1\n"; cout << "s1 giao s2 = "; cout << "s1 hop s2 = "; (s1 * s2).Print(); (s1 + s2).Print();

if (s1 != s2) cout << "s1 /= s2\n"; return 0;

Khi chy chng trnh s cho kt qu sau:


s1 = {10,20,30,40} s2 = {30,50,10,60} 20 thuoc s1 s1 giao s2 = {10,30} s1 hop s2 = {10,20,30,40,50,60} s1 /= s2

8.3. Chuyn kiu


Cc lut chuyn kiu thng thng c sn ca ngn ng cng p dng ti cc hm v cc ton t ti nh ngha. V d, trong
if ('a' & set) //...

ton hng u ca & (ngha l 'a') c chuyn kiu n t char sang int, bi v ton t & ti nh ngha mong i ton hng u ca n thuc kiu int.
Chng 8: Ti nh ngha
127

Bt k s chuyn kiu no khc thm vo phi c nh ngha bi lp trnh vin. V d, gi s chng ta mun ti nh ngha ton t + cho kiu Point sao cho n c th c s dng cng hai im hoc cng mt s nguyn ti c hai ta ca mt im:
class Point //... friend Point operator + (Point, Point); friend Point operator + (int, Point); friend Point operator + (Point, int); };

lm cho ton t + c tnh giao hon, chng ta phi nh ngha hai hm cng mt s nguyn vi mt im: mt hm i vi trng hp s nguyn l ton hng u tin v mt hm i vi trng hp s nguyn l ton hng th hai. Quan st rng nu chng ta bt u xem xt cc kiu khc thm vo kiu int th tip cn ny dn n mc bin i kh kim sot ca ton t. Mt tip cn tt hn l s dng hm xy dng chuyn i tng ti cng kiu nh chnh lp sao cho mt ton t ti nh ngha c th iu khin cng vic. Trong trng hp ny, chng ta cn mt hm xy dng nhn mt int c t c hai ta ca mt im:
class Point { //... Point (int x) { Point::x = Point::y = x; } friend Point operator + (Point, Point); };

i vi cc hm xy dng ca mt i s th khng cn gi hm xy dng mt cch r rng:


Point p = 10; // tng ng vi: Point p(10);

V th c th vit cc biu thc lin quan n cc bin hoc hng thuc kiu Point v int bng cch s dng ton t +.
Point p(10,20), q = 0; q = p + 5; // tng ng vi: q = p + Point(5);

y, 5 c chuyn tm thi thnh i tng Point v sau c cng vo p. i tng tm sau s c hy i. Tc ng ton b l mt chuyn kiu khng tng minh t int thnh Point. V th gi tr cui ca q l (15,25). Ci g xy ra nu chng ta mun thc hin chuyn kiu ngc li t kiu lp thnh mt kiu khc? Trong trng hp ny cc hm xy dng khng th c s dng bi v chng lun tr v mt i tng ca lp m chng thuc v. thay th, mt lp c th nh ngha mt hm thnh vin m chuyn r rng mt i tng thnh mt kiu mong mun.
Chng 8: Ti nh ngha
128

V d, vi lp Rectangle cho chng ta c th nh ngha mt hm chuyn kiu thc hin chuyn mt hnh ch nht thnh mt im bng cch ti nh ngha ton t kiu Point trong lp Rectangle:
class Rectangle { public: Rectangle (int left, int top, int right, int bottom); Rectangle (Point &p, Point &q); //... operator Point () {return botRight - topLeft;} private: Point topLeft; Point botRight; };

Ton t ny c nh ngha chuyn mt hnh ch nht thnh mt im m ta ca n tiu biu cho rng v chiu cao ca hnh ch nht. V th, trong on m
Point p(5,5); Rectangle r(10,10,20,30); r + p;

trc ht hnh ch nht r c chuyn khng tng minh thnh mt i tng Point bi ton t chuyn kiu v sau c cng vo p. Chuyn kiu Point cng c th c p dng tng minh bng cch s dng k hiu p kiu thng thng. V d:
Point(r); (Point)r; // p kiu tng minh thnh Point // p kiu tng minh thnh Point

Thng thng vi kiu ngi dng nh ngha X cho v kiu Y khc (c sn hay ngi dng nh ngha) th: Hm xy dng c nh ngha cho X nhn mt i s n kiu Y s chuyn khng tng minh cc i tng Y thnh cc i tng X khi c cn. Ti nh ngha ton t Y trong X s chuyn khng tng minh cc i tng X thnh cc i tng Y khi c cn.
class X { //... X (Y&); operator Y (); };

// chuyn Y thnh X // chuyn X thnh Y

Mt trong nhng bt li ca cc phng thc chuyn kiu do ngi dng nh ngha l nu chng khng c s dng mt cch hn ch th chng c th lm cho cc hot ng ca chng trnh l kh c th tin on. Cng c s ri ro thm vo ca vic to ra s m h. S m h xy ra khi trnh bin
Chng 8: Ti nh ngha
129

dch c hn mt chn la cho n p dng cc qui lut chuyn kiu ngi dng nh ngha v v th khng th chn c. Tt c nhng trng hp nh th c bo co nh nhng li bi trnh bin dch. minh ha cho cc m h c th xy ra, gi s rng chng ta cng nh ngha mt hm chuyn kiu cho lp Rectangle (nhn mt i s Point) cng nh l ti nh ngha cc ton t + v -:
class Rectangle { public: Rectangle (int left, int top, int right, int bottom); Rectangle (Point &p, Point &q); Rectangle (Point &p); operator Point () {return botRight - topLeft;} friend Rectangle operator + (Rectangle &r, Rectangle &t); friend Rectangle operator - (Rectangle &r, Rectangle &t); private: Point topLeft; Point botRight; };

By gi, trong
Point p(5,5); Rectangle r(10,10,20,30); r + p;

r + p c th c thng dch theo hai cch. Hoc l


r + Rectangle(p) // cho ra mt Rectangle

hoc l:
Point(r) + p // cho ra mt Point

Nu lp trnh vin khng gii quyt s m h bi vic chuyn kiu tng minh th trnh bin dch s t chi.

V d: Lp S Nh Phn
Danh sch 8.2 nh ngha mt lp tiu biu cho cc s nguyn nh phn nh l mt chui cc k t 0 v 1.

Chng 8: Ti nh ngha

130

Danh sch 8.2 1 #include <iostream.h> 2 #include <string.h> 3 int const binSize = 16; // chieu dai so nhi phan la 16

4 class Binary { 5 public: 6 Binary (const char*); 7 Binary (unsigned int); 8 friend Binary operator + (const Binary, const Binary); 9 operator int (); // chuyen kieu 10 void Print (void); 11 private: 12 char bits[binSize]; // cac bit nhi phan 13 }; Ch gii

Hm xy dng ny cung cp mt s nh phn t mu bit ca n. Hm xy dng ny chuyn mt s nguyn dng thnh biu din nh phn tng ng ca n. 8 Ton t + c ti nh ngha cng hai s nh phn. Php cng c lm tng bit mt. n gin th nhng li trn c b qua. 9 Ton t chuyn kiu ny c s dng chuyn mt i tng Binary thnh i tng int . 10 Hm ny n gin ch in mu bit ca s nh phn. 12 Mng ny c s dng gi cc bit 0 v 1 ca s lng 1 bit nh l cc k t. Ci t cc hm ny l nh sau:
Binary::Binary (const char *num) { int iSrc = strlen(num) - 1; int iDest = binSize - 1; while (iSrc >= 0 && iDest >= 0) // sao chep cac bit bits[iDest--] = (num[iSrc--] == '0' ? '0' : '1'); while (iDest >= 0) // dat cac bit trai ve 0 bits[iDest--] = '0';

6 7

Binary::Binary (unsigned int num) { for (register i = binSize - 1; i >= 0; --i) { bits[i] = (num % 2 == 0 ? '0' : '1'); num >>= 1; } } Binary operator + (const Binary n1, const Binary n2) { unsigned carry = 0;

Chng 8: Ti nh ngha

131

unsigned value; Binary res = "0"; for (register i = binSize - 1; i >= 0; --i) { value = (n1.bits[i] == '0' ? 0 : 1) + (n2.bits[i] == '0' ? 0 : 1) + carry; res.bits[i] = (value % 2 == 0 ? '0' : '1'); carry = value >> 1; } return res;

Binary::operator int () { unsigned value = 0; for (register i = 0; i < binSize; ++i) value = (value << 1) + (bits[i] == '0' ? 0 : 1); return value;

void Binary::Print (void) { char str[binSize + 1]; strncpy(str, bits, binSize); str[binSize] = '\0'; cout << str << '\n'; }

Hm main sau to ra hai i tng kiu Binary v kim tra ton t + .


main () { Binary n1 = "01011"; Binary n2 = "11010"; n1.Print(); n2.Print(); (n1 + n2).Print(); cout << n1 + Binary(5) << '\n'; // cong va chuyen thanh int cout << n1 - 5 << '\n'; // chuyen n2 thanh int v tru }

Hai hng cui ca hm main ng x hon ton khc nhau. Hng u ca hai hng ny chuyn 5 thnh Binary, thc hin cng, v sau chuyn kt qu Binary thnh int trc khi gi n n dng xut cout. iu ny tng ng vi:
cout << (int) Binary::operator+(n2,Binary(5)) << '\n';

Hng th hai trong hai hng ny chuyn n1 thnh int (bi v ton t - khng c nh ngha cho Binary), thc hin tr, v sau gi kt qu n dng xut cout. iu ny tng ng vi:
cout << ((int) n2) - 5 << '\n';

Chng 8: Ti nh ngha

132

Trong trng hp ny th ton t chuyn kiu c p dng khng tng minh. Kt qu cho bi chng trnh l bng chng cho cc chuyn kiu c thc hin chnh xc:
0000000000001011 0000000000011010 0000000000100101 16 6

8.4. Ti nh ngha ton t xut <<


Vic xut ng b v n gin cho cc kiu c sn c m rng d dng cho cc kiu ngi dng nh ngha bng cch ti nh ngha thm na ton t <<. i vi bt k kiu ngi dng nh ngha T, chng ta c th nh ngha mt hm operator << xut cc i tng kiu T:
ostream& operator << (ostream&, T&);

Tham s u phi l mt tham chiu ti dng xut ostream sao cho c nhiu s dng ca << c th ni vo nhau. Tham s th hai khng cn l mt tham chiu nhng iu ny li hiu qu cho cc i tng c kch thc ln. V d, thay v hm thnh vin Print ca lp Binary chng ta c th ti nh ngha ton t << cho lp. Bi v ton hng u ca ton t << phi l mt i tng ostream nn n khng th c ti nh ngha nh l mt hm thnh vin. V th n c nh ngha nh l hm ton cc:
class Binary { //... friend };

ostream& operator << (ostream&, Binary&);

ostream& operator << (ostream &os, Binary &n) { char str[binSize + 1]; strncpy(str, n.bits, binSize); str[binSize] = '\0'; cout << str; return os; }

T nh ngha cho, << c th c nh ngha cho xut cc s nh phn theo cch ging nh cc kiu c sn. V d:
Binary n1 = "01011", n2 = "11010"; cout << n1 << " + " << n2 << " = " << n1 + n2 << '\n';

s cho ra kt qu sau:
0000000000001011 + 0000000000011010 = 0000000000100101

Chng 8: Ti nh ngha

133

Vi cch thc n gin, kiu xut ny loi b i gnh nng ca vic nh tn hm xut i vi mi kiu ngi dng nh ngha. Trong trng hp khng s dng ti nh ngha << th v d cui c th c vit nh sau: (gi s rng \n c xa t hm Print):
Binary n1 = "01011", n2 = "11010"; n1.Print(); cout << " + "; n2.Print(); cout << " = "; (n1 + n2).Print(); cout << '\n';

8.5. Ti nh ngha ton t nhp >>


Vic nhp cc kiu ngi dng nh ngha c lm cho d dng bng cch ti nh ngha ton t >> theo cng cch vi << c ti nh ngha. i vi bt k kiu ngi dng nh ngha T chng ta c th nh ngha mt hm operator>> nhp cc i tng kiu T:
istream& operator >> (istream&, T&);

Tham s u tin phi l mt tham chiu ti dng nhp istream sao cho s dng nhiu >> c th c ni vo nhau. Tham s th hai phi l mt tham chiu v n s c sa i bi hm. Tip theo lp Binary chng ta ti nh ngha ton t >> nhp vo mt chui cc bit. Nhc li, bi v ton hng u tin ca ton t >> phi l mt i tng istream nn n khng th c ti nh ngha nh l mt hm thnh vin:
class Binary { //... friend };

istream& operator >> (istream&, Binary&);

istream& operator >> (istream &is, Binary &n) { char str[binSize + 1]; cin >> str; n = Binary(str); // use the constructor for simplicity return is; }

Vi nh ngha cho ny th ton t >> c th c s dng nhp vo cc s nh phn theo cch ca cc kiu d liu c sn. V d,
Binary n; cin >> n;

s c mt s nh phn t bn phm ti n.

Chng 8: Ti nh ngha

134

8.6. Ti nh ngha []
Danh sch 8.3 nh ngha mt lp vect kt hp n gin. Mt vect kt hp l mt mng mt chiu m cc phn t c th c tm kim bng ni dung ca chng hn l v tr ca chng trong mng. Trong AssocVec th mi phn t c mt tn dng chui (thng qua n c th c tm kim) v mt gi tr s nguyn kt hp.
Danh sch 8.3 1 #include <iostream.h> 2 #include <string.h> 3 class AssocVec { 4 public: 5 AssocVec (const int dim); 6 ~AssocVec (void); 7 int& operator [] (const char *idx); 8 private: 9 struct VecElem { 10 char *index; 11 int value; 12 } *elems; // cac phan tu cua vecto 13 int dim; // kich thuoc cua vecto 14 int used; // cac phan tu duoc su dung toi hien tai 15 }; Ch gii

Hm xy dng to ra mt vect kt hp c kch c c ch nh bi tham s ca n. 7 Ton t [] ti nh ngha c s dng truy xut cc phn t ca vect. Hm ti nh ngha [] phi c chnh xc mt tham s. Vi mt chui cho n tm kim phn t tng ng cha trong vect. Nu mt vic so khp ch s c tm thy th sau mt tham chiu ti gi tr kt hp vi n c tr v. Ngc li, mt phn t mi c to ra v mt tham chiu ti gi tr ny c tr v. 12 Cc phn t vect c biu din bi mt mng ng ca cc cu trc VecElem. Mi phn t ca vect gm mt chui (c biu th bi index) v mt gi tr s nguyn (c biu th bi value). Thi cng ca cc hm ny nh sau:
AssocVec::AssocVec (const int dim) { AssocVec::dim = dim; used = 0; elems = new VecElem[dim]; } AssocVec::~AssocVec (void) {

Chng 8: Ti nh ngha

135

for (register i = 0; i < used; ++i) delete elems[i].index; delete [] elems;

int& AssocVec::operator [] (const char *idx) { for (register i = 0; i < used; ++i) // tim phan tu ton tai if (strcmp(idx,elems[i].index) == 0) return elems[i].value; if (used < dim && // tao ra phan tu moi (elems[used].index = new char[strlen(idx)+1]) != 0) { strcpy(elems[used].index,idx); elems[used].value = used + 1; return elems[used++].value; } static int dummy = 0; return dummy;

Ch rng bi v AssocVec::operator[] phi tr v mt tham chiu hp l, mt tham chiu ti mt s nguyn tnh gi c tr v khi vect y hay ton t new tht bi. Mt biu thc tham chiu l mt gi tr tri v v th c th xut hin trn c hai pha ca mt php gn. Nu mt hm tr v mt tham chiu sau mt li gi hm ti hm c th c gn ti. iu ny l ti sao kiu tr v ca AssocVec::operator[] c nh ngha l mt tham chiu. S dng AssocVec chng ta by gi c th to ra cc vect kt hp m x l rt ging cc vect bnh thng:
AssocVec count(5); count["apple"] = 5; count["orange"] = 10; count["fruit"] = count["apple"] + count["orange"];

iu ny s t count["fruit"] ti 15.

8.7. Ti nh ngha ()
Danh sch 8.4 nh ngha mt lp ma trn. Mt ma trn l mt bng cc gi tr (mng hai chiu) m kch thc ca n c biu th bi s hng v s ct trong bng. Mt v d ca ma trn n gin 2 x 3 s l:
M= 10 20 30 21 52 19

Chng 8: Ti nh ngha

136

K hiu ton hc chun tham kho cc phn t ca ma trn l cc du ngoc. V d phn t 20 ca ma trn M (ngha l trong hng u v ct th hai) c tham kho ti nh l M(1,2). i s hc ca ma trn cung cp mt tp cc thao tc ci t ma trn bao gm cng, tr, nhn, v chia.
Danh sch 8.4 1 #include <iostream.h>

2 class Matrix { public: 3 Matrix (const short rows, const short cols); 4 ~Matrix (void) {delete elems;} 5 double& operator () (const short row, const short col); 6 friend ostream& operator << (ostream&, Matrix&); 7 friend Matrix operator + (Matrix&, Matrix&); 8 friend Matrix operator - (Matrix&, Matrix&); 9 friend Matrix operator * (Matrix&, Matrix&); 10 11 12 13 14 15 };
Ch gii

private: const short rows; // s hng ca ma trn const short cols; // s ct ca ma trn double *elems; // cc phn t ca ma trn

Hm xy dng to ra mt ma trn c kch c c ch nh bi cc tham s ca n, tt c cc phn t ca n c khi to l 0. 6 Ton t() ti nh ngha c s dng truy xut cc phn t ca ma trn. Hm ti nh ngha ton t () c th khng c hay c nhiu tham s. N tr v mt tham chiu ti gi tr ca phn t c ch nh. 7 Ton t << ti nh ngha c s dng in mt ma trn theo hnh thc bng. 8-10 Cc ton t ti nh ngha ny cung cp cc thao tc trn ma trn. 14 Cc phn t ca ma trn c biu din bi mt mng ng kiu double. Vic ci t ca ba hm u tin nh sau:
Matrix::Matrix (const short r, const short c) : rows(r), cols(c) { elems = new double[rows * cols]; } double& Matrix::operator () (const short row, const short col) { static double dummy = 0.0; return (row >= 1 && row <= rows && col >= 1 && col <= cols) ? elems[(row - 1)*cols + (col - 1)] : dummy; } ostream& operator << (ostream &os, Matrix &m) {

Chng 8: Ti nh ngha

137

for (register r = 1; r <= m.rows; ++r) { for (int c = 1; c <= m.cols; ++c) os << m(r,c) << " "; os << '\n'; } return os;

Nh trc bi v Matrix::operator() phi tr v mt tham chiu hp l, mt tham chiu ti mt s thc double tnh gi c tr v khi phn t c ch nh khng tn ti. on m sau minh ha rng cc phn t ca ma trn l cc gi tr tri:
Matrix m(2,3); m(1,1) = 10; m(2,1) = 15; cout << m << '\n'; m(1,2) = 20; m(2,2) = 25; m(1,3) = 30; m(2,3) = 35;

iu ny s cho kt qu sau:
10 15 20 30 25 35

8.8. Khi to ngm nh


Hy xem xt nh ngha ca ton t + ti nh ngha cho lp Matrix sau:
Matrix operator + (Matrix &p, Matrix &q) { Matrix m(p.rows, p.cols); if (p.rows == q.rows && p.cols == q.cols) for (register r = 1; r <= p.rows; ++r) for (register c = 1; c <= p.cols; ++c) m(r,c) = p(r,c) + q(r,c); return m; }

Hm sau tr v mt i tng Matrix c khi to ti m. Vic khi to c iu khin bi mt hm xy dng bn trong do trnh bin dch t ng pht ra cho lp Matrix:
Matrix::Matrix (const Matrix &m) : rows(m.rows), cols(m.cols) { elems = m.elems; }

Hnh thc khi to ny c gi l khi to ngm nh bi v hm xy dng c bit khi to tng thnh vin mt ca i tng. Nu chnh cc thnh vin d liu ca i tng ang c khi to li l cc i tng ca lp khc th sau chng cng c khi to ngm nh.

Chng 8: Ti nh ngha

138

Kt qu ca vic khi to ngm nh l cc thnh vin d liu elems ca c hai i tng s tr ti cng khi c cp pht ng. Tuy nhin m c hy nh vo tr v ca hm. Do cc hm hy xa i khi c tr ti bi m.elems b li thnh vin d liu ca i tng tr v ang tr ti mt khi khng hp l! Cui cng iu ny dn n mt tht bi trong khi thc thi chng trnh. Hnh 8.2 minh ha.
Hnh 8.2 Li ca vic khi to ngm nh
sao chp ngm nh ca m c to A memberwise copy of m is made Matrix m sau khi m b hy After m is destroyed

rows cols elems


sao chp ngm Memberwise nh ca m Copy of m

rows cols elems

Dynamic Block

sao chp ngm Memberwise nh of m Copycam

rows cols elems

Invalid Block

Khi to ngm nh xy ra trong cc tnh hung sau: Khi nh ngha v khi to mt i tng trong mt cu lnh khai bo m s dng i tng khc nh l b khi to ca n, v d lnh khi to Matrix n = m trong hm Foo bn di. Khi truyn mt i s l i tng n mt hm (khng c th dng c i s con tr hay tham chiu), v d m trong hm Foo bn di. Khi tr v mt gi tr i tng t mt hm (khng c th dng c i s con tr hay tham chiu), v d return n trong hm Foo bn di.
Matrix Foo (Matrix m) // sao chp ngm nh ti m { Matrix n = m; // sao chp ngm nh ti n //... return n; // sao chp ngm nh n v tr v sao chp }

R rng vic khi to ngm nh l thch hp cho cc lp khng c cc thnh vin d liu con tr (v d, lp Point). Cc vn gy ra bi khi to ngm nh ca cc lp khc c th c trnh bng cch nh ngha cc hm xy dng ph trch cng vic khi to ngm nh mt cch r rng. Hm xy dng ny cn c gi l hm xy dng sao chp. i vi bt k lp X cho th hm xy dng sao chp lun c hnh thc:
X::X (const X&);

V d vi lp Matrix th iu ny c th c nh ngha nh sau:


class Matrix {

Chng 8: Ti nh ngha

139

};

Matrix (const Matrix&); //...

Matrix::Matrix (const Matrix &m) : rows(m.rows), cols(m.cols) { int n = rows * cols; elems = new double[n]; // cng kch thc for (register i = 0; i < n; ++i) // sao chp cc phn t elems[i] = m.elems[i]; }

8.9. Gn ngm nh
Cc i tng thuc cng lp c gn ti mt lp khc bi mt ti nh ngha ton t gn bn trong m c pht ra t ng bi trnh bin dch. V d iu khin php gn trong
Matrix m(2,2), n(2,2); //... m = n;

trnh bin dch t ng pht ra mt hm bn trong nh sau:


Matrix& Matrix::operator = (const Matrix &m) { rows = m.rows; cols = m.cols; elems = m.elems; }

iu ny ging y ht nh trong vic khi to ngm nh v c gi l gn ngm nh. N cng c cng vn nh trong khi to ngm nh v c th khc phc bng cch ti nh ngha ton t = mt cch r rng. V d i vi lp Matrix th vic ti nh ngha ton t = sau y l thch hp:
Matrix& Matrix::operator = (const Matrix &m) { if (rows == m.rows && cols == m.cols) { // phi khp int n = rows * cols; for (register i = 0; i < n; ++i) // sao chp cc phn t elems[i] = m.elems[i]; } return *this; }

Thng thng, i vi bt k lp X cho th ton t = c ti nh ngha bng thnh vin sau ca X:


X& X::operator = (X&)

Chng 8: Ti nh ngha

140

Ton t = ch c th c ti nh ngha nh l thnh vin v khng th c nh ngha ton cc.

8.10.Ti nh ngha new v delete


Cc i tng khc nhau thng c kch thc v tn s s dng khc nhau. Kt qu l chng c nhng yu cu b nh khc nhau. C th cc i tng nh khng c iu khin mt cch hiu qu bi cc phin bn mc nh ca ton t new v delete. Mi khi c cp pht bi ton t new gi mt vi ph c dng cho mc ch qun l. i vi cc i tng ln th iu ny khng ng k nhng i vi cc i tng nh th ph ny c th ln hn chnh cc khi. Hn na, c qu nhiu khi nh c th lm chm chp d di cho cc cp pht v thu hi theo sau. Hiu sut ca chng trnh bng cch to ra nhiu khi nh t ng c th c ci thin ng k bi vic s dng mt chin lc qun l b nh n gin hn cho cc i tng ny. Cc ton t qun l lu tr ng new v delete c th c ti nh ngha cho mt lp bng cch vit chng ln nh ngha ton cc ca cc ton t ny khi c s dng cho cc i tng ca lp . V d gi s chng ta mun ti nh ngha ton t new v delete cho lp Point sao cho cc i tng Point c cp pht t mt mng:
#include <stddef.h> #include <iostream.h> const int maxPoints = 512; class Point { public: //... void* operator new (size_t bytes); void operator delete (void *ptr, size_t bytes); private: int xVal, yVal; static union Block { int xy[2]; Block *next; } *blocks; // tro toi cac luu tru ranh static Block *freeList; // ds ranh cua cac khoi da lien ket static int used; // cac khoi duoc dung

};

Tn kiu size_t c nh ngha trong stddef.h.. Ton t new s lun tr v void*. Tham s ca new l kch thc ca khi c cp pht (tnh theo byte). i s tng ng lun c truyn mt cch t ng ti trnh bin dch. Tham s u ca ton t delete l khi c xa. Tham s hai (ty chn) l

Chng 8: Ti nh ngha

141

kch thc khi cp pht. Cc i s c truyn mt cch t ng ti trnh bin dch. V cc khi, freeList v used l tnh nn chng khng nh hng n kch thc ca i tng Point. Nhng khi ny c khi to nh sau:
Point::Block *Point::blocks = new Block[maxPoints]; Point::Block *Point::freeList = 0; int Point::used = 0;

Ton t new nhn khi c sn k tip t blocks v tr v a ch ca n. Ton t delete gii phng mt khi bng cch chn n trc danh sch lin kt c biu din bi freeList. Khi used t ti maxPoints, new tr v 0 khi danh sch lin kt l rng, ngc li new tr v khi u tin trong danh sch lin kt.
void* Point::operator new (size_t bytes) { Block *res = freeList; return used < maxPoints ? &(blocks[used++]) : (res == 0 ? 0 : (freeList = freeList->next, res)); } void Point::operator delete (void *ptr, size_t bytes) { ((Block*) ptr)->next = freeList; freeList = (Block*) ptr; }

Point::operator new v Point::operator delete c triu gi ch cho cc i tng Point. Li gi new vi bt k i s kiu khc s triu gi nh ngha ton cc ca new, thm ch nu li gi xy ra bn trong mt hm thnh vin ca Point. V d:
Point *pt = new Point(1,1); char *str = new char[10]; delete pt; delete str; // gi Point::operator new // gi ::operator new // gi Point::operator delete // gi ::operator delete

Khi new v delete c ti nh ngha cho mt lp, new v delete ton cc cng c th c s dng khi to v hy mng cc i tng:
Point *points = new Point[5]; //... delete [] points; // gi ::operator new // gi ::operator delete

Ton t new c triu gi trc khi i tng c xy dng trong khi ton t delete c gi sau khi i tng c hy.

Chng 8: Ti nh ngha

142

8.11.Ti nh ngha ++ v -Cc ton t tng v gim mt cng c th c ti nh ngha theo c hai hnh thc tin t v hu t. phn bit gia hai hnh thc ny th phin bn hu t c c t nhn mt i s nguyn ph. V d, cc phin bn tin t v hu t ca ton t ++ c th c ti nh ngha cho lp Binary nh sau:
class Binary { //... friend friend };

Binary Binary

operator ++ operator ++

(Binary&); (Binary&, int);

// tien to // hau to

Mc d chng ta phi chn nh ngha cc phin bn ny nh l cc hm bn ton cc nhng chng cng c th c nh ngha nh l cc hm thnh vin. C hai c nh ngha d dng theo thut ng ca ton t + c nh ngha trc :
Binary operator ++ (Binary &n) { return n = n + Binary(1); } Binary operator ++ (Binary &n, int) { Binary m = n; n = n + Binary(1); return m; } // tien to

// hau to

Ch rng chng ta n gin pht l tham s ph ca phin bn hu t. Khi ton t ny c s dng th trnh bin dch t ng cung cp mt i s mc nh cho n. on m sau thc hin c hai phin bn ca ton t:
Binary n1 = "01011"; Binary n2 = "11010"; cout << ++n1 << '\n'; cout << n2++ << '\n'; cout << n2 << '\n';

N s cho kt qu sau:
0000000000001100 0000000000011010 0000000000011011

Cc phin bn tin t v hu s ca ton t -- c th c ti nh ngha theo cng cch ny.

Chng 8: Ti nh ngha

143

Bi tp cui chng 8
8.1 8.2 Vit cc phin bn ti nh ngha ca hm Max so snh hai s nguyn, hai s thc, hoc hai chui, v tr v thnh phn ln hn. Ti nh ngha hai ton t sau cho lp Set: Ton t - cho hiu ca cc tp hp (v d, s - t cho mt tp hp gm cc phn t thuc s m khng thuc t). Ton t <= kim tra mt tp hp c cha trong mt tp hp khc hay khng (v d, s <= t l true nu tt c cc phn t thuc s cng thuc t). Ti nh ngha hai ton t sau y cho lp Binary: Ton t - cho hiu ca hai gi tr nh phn. n gin, gi s rng ton hng u tin lun ln hn ton hng th hai. Ton t [] ly ch s mt bit thng qua v tr ca n v tr v gi tr ca n nh l mt s nguyn 0 hoc 1. Cc ma trn tha c s dng trong mt s phng thc s (v d, phn tch phn t c hn). Mt ma trn tha l mt ma trn c i a s cc phn t ca n l 0. Trong thc t, cc ma trn tha c kch thc ln n 500 500 l bnh thng. Trn mt my s dng biu din 64 bit cho cc s thc, lu tr mt ma trn nh th nh mt mng s yu cu 2 megabytes lu tr. Mt biu din kinh t hn s ch cn ghi nhn cc phn t khc 0 cng vi cc v tr ca chng trong ma trn. nh ngha mt lp SparseMatrix s dng mt danh sch lin kt ghi nhn ch cc phn t khc 0, v ti nh ngha cc ton t +, -, v * cho n. Cng nh ngha mt hm xy dng khi to ngm nh v mt ton t khi to ngm nh cho lp. Hon tt vic ci t ca lp String. Ch rng hai phin bn ca hm xy dng ngm nh v ton t = ngm nh c i hi, mt cho khi to hoc gn ti mt chui bng cch s dng char*, v mt cho khi to hoc gn ngm nh. Ton t [] nn ch mc mt k t chui bng cch s dng v tr ca n. Ton t + cho php ni hai chui vo nhau.
class String { public: String String String ~String

8.3

8.4

8.5

(const char*); (const String&); (const short); (void);

String& operator =(const char*); String& operator =(const String&); char& operator [](const short); int Length(void) {return(len);} friend String operator +(const String&, const String&); friend ostream& operator << (ostream&, String&);

Chng 8: Ti nh ngha

144

};

private: char *chars; // cac ky tu chuoi short len; // chieu dai cua chuoi

8.6

Mt vct bit l mt vct vi cc phn t nh phn, ngha l mi phn t c gi tr hoc l 0 hoc l 1. Cc vct bit nh c biu din thun tin bng cc s nguyn khng du. V d, mt unsigned char c th bng mt vct bit 8 phn t. Cc vct bit ln hn c th c nh ngha nh mng ca cc vct bit nh hn. Hon tt s thi cng ca lp Bitvec, nh c nh ngha bn di. Nn cho php cc vct bit ca bt k kch thc c to ra v c thao tc bng cch s dng cc ton t kt hp.
enum Bool {false, true}; typedef unsigned char uchar; class BitVec { public:

BitVec (const short dim); BitVec (const char* bits); BitVec (const BitVec&); ~BitVec (void){ delete vec; } BitVec& operator = (const BitVec&); BitVec& operator &= (const BitVec&); BitVec& operator |= (const BitVec&); BitVec& operator ^= (const BitVec&); BitVec& operator <<= (const short); BitVec& operator >>= (const short); int operator [] (const short idx); void Set (const short idx); void Reset (const short idx); BitVec operator ~ (void); BitVec operator & (const BitVec&); BitVec operator | (const BitVec&); BitVec operator ^ (const BitVec&); BitVec operator << (const short n); BitVec operator >> (const short n); Bool operator == (const BitVec&); Bool operator != (const BitVec&);

friend ostream& operator << (ostream&, BitVec&); private: uchar *vec; short bytes; };

Chng 8: Ti nh ngha

145

You might also like