Giáo trình Lập trình hướng đối tượng với C++ - Chương 6: Khuôn hình

Ch-¬ng 6  
khu«n  
h×nh  
(Template)  
Môc ®Ých ch-¬ng nµy:  
HiÓu ®-îc lîi Ých cña viÖc sö dông khu«n h×nh hµm vµ khu«n h×nh líp ®Ó  
viÕt ch-¬ng tr×nh.  
1.  
2. BiÕt c¸ch t¹o vµ sö dông mét khu«n h×nh hµm vµ khu«n h×nh líp.  
3. Kh¸i niÖm c¸c tham sè kiÓu vµ c¸c tham sè biÓu thøc trong khu«n h×nh  
hµm, khu«n h×nh líp.  
§Þnh nghÜa chång khu«n h×nh hµm.  
4.  
5. Cô thÓ ho¸ mét khu«n h×nh hµm, mét hµm thµnh phÇn cña khu«n h×nh líp.  
6. ThuËt to¸n s¶n sinh mét thÓ hiÖn hµm (hµm thÓ hiÖn) cña mét khu«n h×nh  
hµm  
C¸c vÊn ®Ò kh¸c cña lËp tr×nh h-íng ®èi t-îng liªn quan ®Õn khu«n h×nh  
7.  
líp.  
Khu«n h×nh hµm  
Khu«n h×nh hµm lµ g×?  
Ta ®· biÕt ®Þnh nghÜa chång hµm cho phÐp dïng mét tªn duy nhÊt cho nhiÒu  
hµm thùc hiÖn c¸c c«ng viÖc kh¸c nhau. Kh¸i niÖm khu«n h×nh hµm còng cho phÐp  
sö dông cïng mét tªn duy nhÊt ®Ó thùc hiÖn c¸c c«ng viÖc kh¸c nhau, tuy nhiªn so  
víi ®Þnh nghÜa chång hµm, nã cã phÇn m¹nh h¬n vµ chÆt chÏ h¬n; m¹nh h¬n v× chØ  
cÇn viÕt ®Þnh nghÜa khu«n h×nh hµm mét lÇn, råi sau ®ã ch-¬ng tr×nh biªn dÞch lµm  
cho nã thÝch øng víi c¸c kiÓu d÷ liÖu kh¸c nhau; chÆt chÏ h¬n bëi v× dùa theo  
khu«n h×nh hµm, tÊt c¶ c¸c hµm thÓ hiÖn ®-îc sinh ra bëi tr×nh biªn dÞch sÏ t-¬ng  
øng víi cïng mét ®Þnh nghÜa vµ nh- vËy sÏ cã cïng mét gi¶i thuËt.  
T¹o mét khu«n h×nh hµm  
Gi¶ thiÕt r»ng chóng ta cÇn viÕt mét hµm m in ®-a ra gi¸ trÞ nhá nhÊt trong hai  
gi¸ trÞ cã cïng kiÓu. Ta cã thÓ viÕt mét ®Þnh nghÜa nh- thÕ ®èi víi kiÓu intnh- sau:  
int min (int a, int b) {  
if (a < b) return a;  
-233-  
Khu«n h×nh  
else return b;  
}
Gi¶ sö, ta l¹i ph¶i viÕt ®Þnh nghÜa hµm min() cho kiÓu  
double,float,char,char* ...  
float min(float a, float b) {  
if (a < b) return a;  
else b; }  
NÕu tiÕp tôc nh- vËy, sÏ cã khuynh h-íng ph¶i viÕt rÊt nhiÒu ®Þnh nghÜa hµm  
hoµn toµn t-¬ng tù nhau; chØ cã kiÓu d÷ liÖu c¸c tham sè lµ thay ®æi. C¸c ch-¬ng  
tr×nh biªn dÞch C++ hiÖn cã cho phÐp gi¶i quyÕt ®¬n gi¶n vÊn ®Ò trªn b»ng c¸ch  
®Þnh nghÜa mét khu«n h×nh hµm duy nhÊt theo c¸ch nh- sau:  
#include <iostream.h>  
//t¹o mét khu«n h×nh hµm  
template <class T> T min(T a, T b) {  
if (a < b) return a;  
else return b;  
}
So s¸nh víi ®Þnh nghÜa hµm th«ng th-êng, ta thÊy chØ cã dßng ®Çu tiªn bÞ thay  
®æi:  
template <class T> T min (T a, T b)  
trong ®ã  
template<class T>  
x¸c ®Þnh r»ng ®ã lµ mét khu«n h×nh víi mét tham sè kiÓu T;  
PhÇn cßn l¹i  
T min(T a, T b)  
nãi r»ng, m in()lµ mét hµm víi hai tham sè h×nh thøc kiÓu T vµ cã gi¸ trÞ tr¶ vÒ  
còng lµ kiÓu T.  
-234-  
Khu«n h×nh  
Sö dông khu«n h×nh hµm  
Khu«n h×nh hµm cho kiÓu d÷ liÖu c¬ së  
§Ó sö dông khu«n h×nh hµm min() võa t¹o ra, chØ cÇn sö dông hµm min()  
trong nh÷ng ®iÒu kiÖn phï hîp (ë ®©y cã nghÜa lµ hai tham sè cña hµm cã cïng  
kiÓu d÷ liÖu). Nh- vËy, nÕu trong mét ch-¬ng tr×nh cã hai tham sè nguyªn n p,  
víi lêi gäi min(n,p) ch-¬ng tr×nh biªn dÞch sÏ tù ®éng s¶n sinh ra hµm min() (ta  
gäi lµ mét hµm thÓ hiÖn) t-¬ng øng víi hai tham sè kiÓu nguyªn int. NÕu chóng ta  
gäi min() víi hai tham sè kiÓu float, ch-¬ng tr×nh biªn dÞch còng sÏ tù ®éng s¶n  
sinh mét hµm thÓ hiÖn min kh¸c t-¬ng øng víi c¸c tham sè kiÓu float vµ cø thÕ.  
Sau ®©y lµ mét vÝ dô hoµn chØnh:  
VÝ dô 6.1  
/*template1.cpp*/  
#include <iostream.h>  
#include <conio.h>  
//t¹o mét khu«n h×nh hµm  
template <class T> T min(T a, T b) {  
if ( a < b) return a;  
else return b;  
}
//vÝ dô sö dông khu«n h×nh hµm min  
void main() {  
clrscr();  
int n = 4, p = 12;  
float x = 2.5, y= 3.25;  
cout<<"min (n, p) = "<<min (n, p)<<"\n";//int min(int, int)  
cout<<"min (x, y) = "<<min (x, y)<<"\n";//float min(float, float)  
getch();  
}
min(n, p) = 4  
min(x, y) = 2.5  
-235-  
Khu«n h×nh  
Khu«n h×nh hµm min cho kiÓu char *  
/*template2.cpp*/  
#include <iostream.h>  
#include <conio.h>  
template <class T> T min (T a, T b) {  
if (a < b) return a;  
else return b;  
}
void main() {  
clrscr();  
char * adr1 = "DHBK";  
char * adr2 = "CDSD";  
cout << "min (adr1, adr2) ="<<min (adr1, adr2);  
getch();  
}
min (adr1, adr2) = DHBK  
KÕt qu¶ kh¸ thó vÞ v× ta hy väng hµm m in() tr¶ vÒ x©u "CDSD". Thùc tÕ, víi  
biÓu thøc min(adr1, adr2) , ch-¬ng tr×nh biªn dÞch ®· sinh ra hµm thÓ hiÖn sau  
®©y:  
char * min(char * a, char * b) {  
if (a < b) return a;  
else return b;  
}
ViÖc so s¸nh a < b thùc hiÖn trªn c¸c gi¸ trÞ biÕn trá (ë ®©y trong c¸c khu«n  
h×nh m¸y PC ta lu«n lu«n cã a < b). Ng-îc l¹i viÖc hiÓn thÞ thùc hiÖn bëi to¸n tö  
<< sÏ ®-a ra x©u ký tù trá bëi con trá ký tù.  
Khu«n h×nh hµm min víi kiÓu d÷ liÖu líp  
§Ó ¸p dông khu«n h×nh hµm min() ë trªn víi kiÓu líp, cÇn ph¶i ®Þnh nghÜa líp  
sao cho cã thÓ ¸p dông phÐp to¸n so s¸nh “<” víi c¸c ®èi t-îng cña líp nµy, nghÜa  
lµ ta ph¶i ®Þnh nghÜa mét hµm to¸n tö operator < cho líp. Sau ®©y lµ mét vÝ dô  
minh ho¹:  
-236-  
Khu«n h×nh  
VÝ dô 6.2  
/*template3.cpp*/  
#include <iostream.h>  
#include <conio.h>  
//khu«n h×nh hµm min  
template <class T> T min( T a, T b) {  
if (a < b) return a;  
else return b;  
}
//líp vect  
class vect {  
int x, y;  
public:  
vect(int abs =0, int ord = 0) { x= abs, y= ord;}  
void display() { cout <<x<<" "<<y<<"\n"; }  
friend int operator < (vect , vect);  
};  
int operator < (vect a, vect b) {  
return a.x*a.x + a.y*a.y < b.x*b.x + b.y*b.y;  
}
void main() {  
clrscr();  
vect u(3,2),v(4,1);  
cout<<"min (u, v) = ";  
min(u,v).display();  
getch();  
}
min (u, v) = 3 2  
NÕu ta ¸p dông khu«n h×nh hµm min() ®èi víi mét líp mµ ch-a ®Þnh nghÜa  
to¸n tö “<”, ch-¬ng tr×nh biªn dÞch sÏ ®-a ra mét th«ng b¸o lçi t-¬ng tù nh- viÖc  
®Þnh nghÜa mét hµm min() cho kiÓu líp ®ã.  
-237-  
Khu«n h×nh  
C¸c tham sè kiÓu cña khu«n h×nh hµm  
PhÇn nµy tr×nh bµy c¸ch ®-a vµo c¸c tham sè kiÓu trong mét khu«n h×nh hµm,  
®Ó ch-¬ng tr×nh biªn dÞch s¶n sinh mét hµm thÓ hiÖn.  
C¸c tham sè kiÓu trong ®Þnh nghÜa khu«n h×nh hµm  
Mét c¸ch tæng qu¸t, khu«n h×nh hµm cã thÓ cã mét hay nhiÒu tham sè kiÓu,  
víi mçi tham sè nµy cã tõ kho¸ class ®i liÒn tr-íc, ch¼ng h¹n nh-:  
template <class T, class U> int fct (T a, T *b, U c) {... }  
C¸c tham sè nµy cã thÓ ®Ó ë bÊt kú ®©u trong ®Þnh nghÜa cña khu«n h×nh hµm,  
nghÜa lµ:  
Trong dßng tiªu ®Ò ( nh- ®· chØ ra trong vÝ dô trªn).  
Trong c¸c khai b¸o c¸c biÕn côc bé.  
Trong c¸c chØ thÞ thùc hiÖn.  
(i)  
Ch¼ng h¹n:  
template <class T, class U> int fct (T a, T *b, U c) {  
T x; //biÕn côc bé x kiÓu T  
U *adr; //biÕn côc bé adr kiÓu U *  
...  
adr = new T [10];//cÊp ph¸t mét m¶ng 10 thµnh phÇn kiÓu T ... n = sizeof (T);  
}
Ta xem ch-¬ng tr×nh sau:  
VÝ dô 6.3  
/*templat4.cpp*/  
#include <iostream.h>  
#include <conio.h>  
template <class T, class U> T fct(T x, U y, T z) {  
return x + y + z;  
}
void main() {  
clrscr();  
int n= 1, p = 2, q = 3;  
-238-  
Khu«n h×nh  
float x =2.5, y = 5.0;  
cout <<fct( n, x, p)<<"\n";// (int) 5  
cout <<fct(x, n, y)<<"\n"; // (float)8.5  
cout <<fct(n, p, q)<<"\n"; // (int) 6  
//cout <<fct(n, p, x)<<"\n"; // lçi  
getch();  
}
Trong mäi tr-êng hîp, mçi tham sè kiÓu ph¶i xuÊt hiÖn Ýt nhÊt mét lÇn trong  
khai b¸o danh s¸ch c¸c tham sè h×nh thøc cña khu«n h×nh hµm. §iÒu ®ã hoµn toµn  
logic bêi v× nhê c¸c tham sè nµy, ch-¬ng tr×nh dÞch míi cã thÓ s¶n sinh ra hµm thÓ  
hiÖn cÇn thiÕt. §iÒu g× sÏ x¶y ra nÕu trong danh s¸ch c¸c tham sè cña khu«n h×nh  
hµm kh«ng cã ®ñ c¸c tham sè kiÓu? HiÓn nhiªn khi ®ã ch-¬ng tr×nh dÞch kh«ng thÓ  
x¸c ®Þnh c¸c tham sè kiÓu d÷ liÖu thùc øng víi c¸c tham sè kiÓu h×nh thøc trong  
template<...>.  
Khu«n h×nh hµm sau ®©y thùc hiÖn trao ®æi néi dung cña hai biÕn.  
VÝ dô 6.4  
/*templat5.cpp*/  
#include <iostream.h>  
#include <conio.h>  
//®Þnh nghÜa khu«n h×nh hµm ®æi chç néi dung hai biÕn víi kiÓu bÊt kú  
template <class X> void swap(X &a, X &b) {  
X temp;  
temp=a;  
a=b;  
b=temp;  
}
void main() {  
clrscr();  
int i=10, j=20;  
float x=10.1, y=23.1;  
cout<<"I J ban dau: "<<i<<" "<<j<<endl;  
cout<<"X Y ban dau: "<<x<<" "<<y<<endl;  
swap(i,j);//®æi chç hai sè nguyªn  
-239-  
Khu«n h×nh  
swap(x,y); //®æi chç hai sè nguyªn  
cout<<"I J sau khi doi cho: "<<i<<" "<<j<<endl;  
cout<<"X Y sau khi doi cho: "<<x<<" "<<y<<endl;  
getch();  
}
I J ban dau: 10 20  
X Y ban dau: 10.1 23.1  
I J sau khi doi cho: 20 10  
X Y sau khi doi cho: 23.1 10.1  
Gi¶i thuËt s¶n sinh mét hµm thÓ hiÖn  
Trë l¹i khu«n h×nh hµm m in():  
template <class T> T min(T a, T b) {  
if (a < b) return a;  
else return b;  
}
Víi c¸c khai b¸o:  
int n;  
char c;  
c©u hái ®Æt ra lµ: ch-¬ng tr×nh dÞch sÏ lµm g× khi gÆp lêi gäi kiÓu nh- lµ  
min(n,c)? C©u tr¶ lêi dùa trªn hai nguyªn t¾c sau ®©y:  
C++ quy ®Þnh ph¶i cã mét sù t-¬ng øng chÝnh x¸c gi÷a kiÓu cña tham sè  
h×nh thøc vµ kiÓu tham sè thùc sù ®-îc truyÒn cho hµm, t¾c lµ ta chØ cã thÓ sö  
dông khu«n h×nh hµm min() trong c¸c lêi gäi víi hai tham sè cã cïng kiÓu.  
Lêi gäi min(n, c) kh«ng ®-îc chÊp nhËn vµ sÏ g©y ra lçi biªn dÞch.  
(ii)  
C++ thËm chÝ cßn kh«ng cho phÐp c¸c chuyÓn kiÓu th«ng th-êng nh- lµ: T  
thµnh const T hay T[] thµnh T * , nh÷ng tr-êng hîp hoµn toµn ®-îc phÐp trong  
®Þnh nghÜa chång hµm.  
(iii)  
Ta tham kh¶o ®o¹n ch-¬ng tr×nh sau ®©y:  
int n;  
char c;  
unsigned int q;  
-240-  
Khu«n h×nh  
const int r = 10;  
int t[10];  
int *adi;  
...  
min (n, c) //lçi  
min (n, q) //lçi  
min (n, r) //lçi  
min (t, adi) //lçi  
Khëi t¹o c¸c biÕn cã kiÓu d÷ liÖu chuÈn  
Trong khu«n h×nh hµm, tham sè kiÓu cã thÓ t-¬ng øng khi th× mét kiÓu d÷ liÖu  
chuÈn, khi th× mét kiÓu d÷ liÖu líp. SÏ lµm g× khi ta cÇn ph¶i khai b¸o bªn trong  
khu«n h×nh hµm mét ®èi t-îng vµ truyÒn mét hay nhiÒu tham sè cho hµm thiÕt lËp  
cña líp. Xem vÝ dô sau ®©y:  
template <class T> fct(T a) {  
T x(3);//x lµ mét ®èi t-îng côc bé kiÓu T mµ chóng ta x©y dùng b»ng c¸ch  
//truyÒn gi¸ trÞ 3 cho hµm thiÕt lËp ...  
}
Khi sö dông hµm fct() cho mét kiÓu d÷ liÖu líp, mäi viÖc ®Òu tèt ®Ñp. Ng-îc  
l¹i, nÕu chóng ta cè g¾ng ¸p dông cho mét kiÓu d÷ liÖu chuÈn, ch¼ng h¹n nh- int,  
khi ®ã ch-¬ng tr×nh dÞch s¶n sinh ra hµm sau ®©y:  
fct( int a) { int x(3); ... }  
§Ó cho chØ thÞ  
int x(3) ;  
kh«ng g©y ra lçi, C++ ®· ngÇm hiÓu c©u lÖnh ®ã nh- lµ phÐp khëi t¹o biÕn x  
víi gi¸ trÞ 3, nghÜa lµ:  
int x = 3;  
Mét c¸ch t-¬ng tù:  
double x(3.5); //thay v× double x = 3.5;  
char c('e'); //thay v× char c = 'e';  
-241-  
Khu«n h×nh  
C¸c h¹n chÕ cña khu«n h×nh hµm  
VÒ nguyªn t¾c, khi ®Þnh nghÜa mét khu«n h×nh hµm, mét tham sè kiÓu cã thÓ  
t-¬ng øng víi bÊt kú kiÓu d÷ liÖu nµo, cho dï ®ã lµ mét kiÓu chuÈn hay mét kiÓu  
líp do ng-êi dïng ®Þnh nghÜa. Do vËy kh«ng thÓ h¹n chÕ viÖc thÓ hiÖn ®èi víi mét  
sè kiÓu d÷ liÖu cô thÓ nµo ®ã. Ch¼ng h¹n, nÕu mét khu«n h×nh hµm cã dßng ®Çu  
tiªn:  
template <class T> void fct(T)  
chóng ta cã thÓ gäi fct() víi mét tham sè víi kiÓu bÊt kú: int,float,int *,int **,  
t* (t lµ mét kiÓu d÷ liÖu nµo ®Êy)  
Tuy nhiªn, chÝnh ®Þnh nghÜa bªn trong khu«n h×nh hµm l¹i chøa mét sè yÕu tè  
cã thÓ lµm cho viÖc s¶n sinh hµm thÓ hiÖn kh«ng ®óng nh- mong muèn. Ta gäi ®ã  
lµ c¸c h¹n chÕ cña c¸c khu«n h×nh hµm.  
§Çu tiªn, chóng ta cã thÓ cho r»ng mét tham sè kiÓu cã thÓ t-¬ng øng víi mét  
con trá. Do ®ã, víi dßng tiªu ®Ò:  
template <class T> void fct(T *)  
ta chØ cã thÓ gäi fct() víi mét con trá ®Õn mét kiÓu nµo ®ã: int*, int **, t  
*, t **.  
Trong c¸c tr-êng hîp kh¸c, sÏ g©y ra c¸c lçi biªn dÞch. Ngoµi ra, trong ®Þnh  
nghÜa cña mét khu«n h×nh hµm, cã thÓ cã c¸c chØ thÞ kh«ng thÝch hîp ®èi víi mét  
sè kiÓu d÷ liÖu nhÊt ®Þnh. Ch¼ng h¹n, khu«n h×nh hµm:  
template <class T> T min(T a, T b) {  
if (a < b) return a;  
else return b;  
}
kh«ng thÓ dïng ®-îc nÕu T t-¬ng øng víi mét kiÓu líp trong ®ã phÐp to¸n “<”  
kh«ng ®-îc ®Þnh nghÜa chång. Mét c¸ch t-¬ng tù víi mét khu«n h×nh hµm kiÓu:  
template <class T> void fct(T) {  
... T x(2, 5); /*®èi t-îng côc bé ®-îc khëi t¹o b»ng mét hµm thiÕt lËp víi  
hai tham sè*/  
}
kh«ng thÓ ¸p dông cho c¸c kiÓu d÷ liÖu líp kh«ng cã hµm thiÕt lËp víi hai  
tham sè.  
Tãm l¹i, mÆc dï kh«ng tån t¹i mét c¬ chÕ h×nh thøc ®Ó h¹n chÕ kh¶ n¨ng ¸p  
dông cña c¸c khu«n h×nh hµm, nh-ng bªn trong mçi mét khu«n h×nh hµm ®Òu cã  
-242-  
Khu«n h×nh  
chøa nh÷ng nh©n tè ®Ó ng-êi ta cã thÓ biÕt ®-îc khu«n h×nh hµm ®ã cã thÓ ®-îc ¸p  
dông ®Õn møc nµo.  
C¸c tham sè biÓu thøc cña mét khu«n h×nh hµm  
Trong ®Þnh nghÜa cña mét khu«n h×nh hµm cã thÓ khai b¸o c¸c tham sè h×nh  
thøc víi kiÓu x¸c ®Þnh. Ta gäi chóng lµ c¸c tham sè biÓu thøc. Ch-¬ng tr×nh  
templat6.cpp sau ®©y ®Þnh nghÜa mét khu«n h×nh hµm cho phÐp ®Õm sè l-îng  
c¸c phÇn tö nul (0 ®èi víi c¸c gi¸ trÞ sè hoÆc NULL nÕu lµ con trá) trong mét b¶ng  
víi kiÓu bÊt kú vµ kÝch th-íc nµo ®ã:  
VÝ dô 6.5  
/*templat6.cpp*/  
#include <iostream.h>  
#include <conio.h>  
template <class T> int compte(T * tab, int n) {  
int i, nz = 0;  
for (i=0; i<n; i++)  
if (!tab[i])  
nz++;  
return nz;  
}
void main() {  
clrscr();  
int t[5] = {5, 2, 0, 2, 0};  
char c[6] = { 0, 12, 0, 0, 0};  
cout<<" compte (t) = "<<compte(t, 5)<<"\n";  
cout<<" compte (c) = "<<compte(c,6)<<"\n";  
getch();  
}
compte (t) = 2  
compte (c) = 4  
Ta cã thÓ nãi r»ng khu«n h×nh hµm compte ®Þnh nghÜa mét hä c¸c hµm  
compte trong ®ã kiÓu cña tham sè ®Çu tiªn lµ tuú ý (®-îc x¸c ®Þnh bëi lêi gäi), cßn  
kiÓu cña tham sè thø hai ®· x¸c ®Þnh (kiÓu int).  
-243-  
Khu«n h×nh  
§Þnh nghÜa chång c¸c khu«n h×nh hµm  
Gièng nh- viÖc ®Þnh nghÜa chång c¸c hµm th«ng th-êng, C++ cho phÐp ®Þnh  
nghÜa chång c¸c khu«n h×nh hµm, tøc lµ cã thÓ ®Þnh nghÜa mét hay nhiÒu khu«n  
h×nh hµm cã cïng tªn nh-ng víi c¸c tham sè kh¸c nhau. §iÒu ®ã sÏ t¹o ra nhiÒu hä  
c¸c hµm (mçi khu«n h×nh hµm t-¬ng øng víi mét hä c¸c hµm). VÝ dô cã ba hä hµm  
m in:  
Hä thø nhÊt bao gåm c¸c hµm t×m gi¸ trÞ nhá nhÊt trong hai gi¸ trÞ,  
Hä thø hai t×m sè nhá nhÊt trong ba sè,  
(iv)  
(v)  
Hä thø ba t×m sè nhá nhÊt trong mét m¶ng.  
(vi)  
VÝ dô 6.6  
/*templat7.cpp*/  
#include <iostream.h>  
#include <conio.h>  
//khu«n h×nh 1  
template <class T> T min(T a, T b) {  
if (a < b) return a;  
else return b;  
}
//khu«n h×nh 2  
template <class T> T min(T a, T b, T c) {  
return min (min (a, b), c);  
}
//khu«n h×nh 3  
template <class T> T min (T *t, int n) {  
T res = t[0];  
for(int i = 1; i < n; i++)  
if (res > t[i])  
res = t[i];  
return res;  
}
void main() {  
clrscr();  
int n = 12, p = 15, q = 2;  
-244-  
Khu«n h×nh  
float x = 3.5, y = 4.25, z = 0.25;  
int t[6] = {2, 3, 4,-1, 21};  
char c[4] = {'w', 'q', 'a', 'Q'};  
cout<<“min(n,p) = ”<<min(n,p)<<"\n"; //khu«nh×nh1intmin(int,int)  
cout<<“min(n,p,q) = ”<<min(n,p,q)<<"\n";//khu«n h×nh 2 int min(int,int,int)  
cout<<“min(x,y) = ”<<min(x,y)<<"\n"; //khu«nh×nh1floatmin(float,float)  
cout<<“min(x,y,z) = ”<<min(x,y,z)<<"\n";//khu«nh×nh2floatmin(float,float,float)  
cout<<“min(t,6) = ”<<min(t,6)<<"\n"; // khu«n h×nh 3 int min(int *, int)  
cout<<“min(c,4) = ”<<min(c,4)<<"\n"; //khu«nh×nh3charmin(char*,int)  
getch();  
}
min(n,p) = 12  
min(n,p,q) = 2  
min(x,y) = 3.5  
min(x,y,z) = 0.25  
min(t,6) = -1  
min(c,4) = Q  
NhËn xÐt  
Còng gièng nh- ®Þnh nghÜa chång c¸c hµm, viÖc ®Þnh nghÜa chång c¸c khu«n  
h×nh hµm cã thÓ g©y ra sù nhËp nh»ng trong viÖc s¶n sinh c¸c hµm thÓ hiÖn. Ch¼ng  
h¹n víi bèn hä hµm sau ®©y:  
template <class T> T fct(T, T) {...}  
template <class T> T fct(T *, T) {...}  
template <class T> T fct(T, T*) {...}  
template <claas T> T fct(T *, T*) {...}  
XÐt c¸c c©u lÖnh sau ®©y:  
int x;  
int y;  
-245-  
Khu«n h×nh  
Lêi gäi  
fct(&x, &y)  
cã thÓ t-¬ng øng víi khu«n h×nh hµm 1 hay khu«n h×nh hµm 4.  
Cô thÓ ho¸ c¸c hµm thÓ hiÖn  
Mét khu«n h×nh hµm ®Þnh nghÜa mét hä c¸c hµm dùa trªn mét ®Þnh nghÜa  
chung, nãi c¸ch kh¸c chóng thùc hiÖn theo cïng mét gi¶i thuËt. Trong mét sè  
tr-êng hîp, sù tæng qu¸t nµy cã thÓ chÞu “rñi ro”, ch¼ng h¹n nh- trong tr-êng hîp  
¸p dông khu«n h×nh hµm min cho kiÓu char* nh- ®· nãi ë trªn. Kh¸i niÖm cô thÓ  
ho¸, ®-a ra mét gi¶i ph¸p kh¾c phôc c¸c “rñi ro” kiÓu nh- trªn. C++ cho phÐp ta  
cung cÊp, ngoµi ®Þnh nghÜa cña mét khu«n h×nh hµm, ®Þnh nghÜa cña mét sè c¸c  
hµm cho mét sè kiÓu d÷ liÖu cña tham sè. Ta xÐt ch-¬ng tr×nh vÝ dô sau ®©y:  
VÝ dô 6.7  
/*templat8.cpp*/  
#include <iostream.h>  
#include <string.h>  
#include <conio.h>  
//khu«n h×nh hµm min  
template <class T> T min (T a, T b) {  
if (a < b) return a;  
else return b;  
}
//hµm min cho kiÓu x©u ký tù  
char * min (char *cha, char *chb) {  
if (strcmp(cha, chb) <0) return cha;  
else return chb;  
}
void main() {  
clrscr();  
int n= 12, p = 15;  
char *adr1= "DHBK", *adr2 ="CD2D";  
cout<<"min(n, p) = "<<min(n, p)<<"\n"; //khu«n h×nh hµm  
cout<<"min(adr1,adr2) = "<<min(adr1,adr2)<<endl; //hµm char * min (char *,  
-246-  
Khu«n h×nh  
//char *)  
getch();  
}
min(n, p) = 12  
min(adr1,adr2) = CD2D  
Nh- vËy, b¶n chÊt cña cô thÓ ho¸ khu«n h×nh hµm lµ ®Þnh nghÜa c¸c hµm th«ng  
th-êng cã cïng tªn víi khu«n h×nh hµm ®Ó gi¶i quyÕt mét sè tr-êng hîp rñi ro khi  
ta ¸p dông khu«n h×nh hµm cho mét sè kiÓu d÷ liÖu ®Æc biÖt nµo ®ã.  
Tæng kÕt vÒ c¸c khu«n h×nh hµm  
Mét c¸ch tæng qu¸t, ta cã thÓ ®Þnh nghÜa mét hay nhiÒu khu«n h×nh cïng tªn,  
mçi khu«n h×nh cã c¸c tham sè kiÓu còng nh- lµ c¸c tham sè biÓu thøc riªng. H¬n  
n÷a, cã thÓ cung cÊp c¸c hµm th«ng th-êng víi cïng tªn víi mét khu«n h×nh hµm;  
trong tr-êng hîp nµy ta nãi ®ã lµ sù cô thÓ ho¸ mét hµm thÓ hiÖn.  
Trong tr-êng hîp tæng qu¸t khi cã ®ång thêi c¶ hµm ®Þnh nghÜa chång vµ  
khu«n h×nh hµm, ch-¬ng tr×nh dÞch lùa chän hµm t-¬ng øng víi mét lêi gäi hµm  
dùa trªn c¸c nguyªn t¾c sau ®©y:  
§Çu tiªn, kiÓm tra tÊt c¶ c¸c hµm th«ng th-êng cïng tªn vµ chó ý ®Õn sù  
t-¬ng øng chÝnh x¸c; nÕu chØ cã mét hµm phï hîp, hµm ®ã ®-îc chän; cßn nÕu  
cã nhiÒu hµm cïng tho¶ m·n (cã sù nhËp nh»ng) sÏ t¹o ra mét lçi biªn dÞch vµ  
qu¸ tr×nh t×m kiÕm bÞ gi¸n ®o¹n.  
(vii)  
NÕu kh«ng cã hµm th«ng th-êng nµo t-¬ng øng chÝnh x¸c víi lêi gäi, khi  
(viii)  
®ã ta kiÓm tra tÊt c¶ c¸c khu«n h×nh hµm cã cïng tªn víi lêi gäi; nÕu chØ cã  
mét t-¬ng øng chÝnh x¸c ®-îc t×m thÊy, hµm thÓ hiÖn t-¬ng øng ®-îc s¶n sinh  
vµ vÊn ®Ò ®-îc gi¶i quyÕt; cßn nÕu cã nhiÒu h¬n mét khu«n h×nh hµm( cã sù  
nhËp nh»ng) ®iÒu ®ã sÏ g©y ra lçi biªn dÞch vµ qu¸ tr×nh t×m kiÕm bÞ ng¾t.  
Cuèi cïng, nÕu kh«ng cã khu«n h×nh hµm phï hîp, ta kiÓm tra mét lÇn n÷a  
tÊt c¶ c¸c hµm th«ng th-êng cïng tªn víi lêi goi. Trong tr-êng hîp nµy chóng  
ta ph¶i t×m kiÕm sù t-¬ng øng dùa vµo c¶ c¸c chuyÓn kiÓu cho phÐp trong  
C/C++.  
(ix)  
KHU«N h×nh líp  
Khu«n h×nh líp lµ g×?  
Bªn c¹nh kh¸i niÖm khu«n h×nh hµm, C++ cßn cho phÐp ®Þnh nghÜa khu«n  
h×nh líp. Còng gièng nh- khu«n h×nh hµm, ë ®©y ta chØ cÇn viÕt ®Þnh nghÜa c¸c  
khu«n h×nh líp mét lÇn råi sau ®ã cã thÓ ¸p dông chóng víi c¸c kiÓu d÷ liÖu kh¸c  
nhau ®Ó ®-îc c¸c líp thÓ hiÖn kh¸c nhau.  
-247-  
Khu«n h×nh  
T¹o mét khu«n h×nh líp  
Ta th-êng t¹o ra líp point theo kiÓu (ë ®©y ta bá qua ®Þnh nghÜa cña c¸c  
hµm thµnh phÇn ):  
class point {  
int x, y;  
public:  
point (int abs =0, int ord =0);  
void display();  
//...  
};  
Trong vÝ dô nµy, ta ®Þnh nghÜa mét líp c¸c ®iÓm cã to¹ ®é nguyªn. NÕu muèn  
to¹ ®é ®iÓm cã kiÓu d÷ liÖu kh¸c (float, double, long, unsigned int) ta ph¶i  
®Þnh nghÜa mét líp kh¸c b»ng c¸ch thay thÕ, trong ®Þnh nghÜa líp point, tõ kho¸ int  
b»ng tõ kho¸ t-¬ng øng víi kiÓu d÷ liÖu mong muèn.  
§Ó tr¸nh sù trïng lÆp trong c¸c t×nh huèng nh- trªn, ch-¬ng tr×nh dÞch C++  
cho phÐp ®Þnh nghÜa mét khu«n h×nh líp vµ sau ®ã, ¸p dông khu«n h×nh líp nµy víi  
c¸c kiÓu d÷ liÖu kh¸c nhau ®Ó thu ®-îc c¸c líp thÓ hiÖn nh- mong muèn:  
template <class T> class point {  
T x; T y;  
public:  
point (T abs=0, T ord=0);  
void display();  
};  
Còng gièng nh- c¸c khu«n h×nh hµm, tËp hîp template<class T> x¸c ®Þnh  
r»ng ®ã lµ mét khu«n h×nh trong ®ã cã mét tham sè kiÓu T; Còng cÇn ph¶i nh¾c l¹i  
r»ng, C++ sö dông tõ kho¸ class chØ ®Ó nãi r»ng T ®¹i diÖn cho mét kiÓu d÷ liÖu  
nµo ®ã. TiÕp theo ®©y ta bµn ®Õn viÖc ®Þnh nghÜa c¸c hµm thµnh phÇn cña khu«n  
h×nh líp. Ng-êi ta ph©n biÖt hai tr-êng hîp: (i) Khi hµm thµnh phÇn ®-îc ®Þnh  
nghÜa bªn trong ®Þnh nghÜa líp tr-êng hîp nµy kh«ng cã g× thay ®æi. XÐt ®Þnh nghÜa  
hµm thiÕt lËp sau ®©y:  
template <class T> class point {  
T x; T y;  
public:  
point(T abs=0, T ord=0) {  
-248-  
Khu«n h×nh  
x = abs; y = ord;  
}
...  
};  
(ii) Ng-îc l¹i, khi ®Þnh nghÜa cña hµm thµnh phÇn n»m ngoµi ®Þnh nghÜa líp,  
khi ®ã cÇn ph¶i “nh¾c l¹i” cho ch-¬ng tr×nh dÞch biÕt: c¸c tham sè kiÓu cña khu«n  
h×nh líp, cã nghÜa lµ ph¶i nh¾c l¹i: template <class T> tr-íc ®Þnh nghÜa hµm,  
cßn tªn cña khu«n h×nh líp ®-îc viÕt nh- point<T>  
Tãm l¹i, dßng tiªu ®Ò ®Çy ®ñ cho hµm thµnh phÇn display() cña khu«n h×nh  
hµm point nh- sau:  
template <class T> void point<T>::display()  
Sau ®©y lµ ®Þnh nghÜa ®Çy ®ñ cña khu«n h×nh líp point:  
#include <iostream.h>  
//t¹o khu«n h×nh hµm  
template <class T> class point { T x, y;  
public:  
// ®Þnh nghÜa hµm thµnh phÇn ë bªn trong khu«n h×nh líp  
point(T abs = 0, T ord = 0) {  
x = abs; y = ord;  
}
void display();  
};  
// ®Þnh nghÜa hµm thµnh phÇn ë bªn ngoµi khu«n h×nh líp  
template <class T> void point<T>::display() {  
cout<<"Toa do: "<<x<<" "<<y<<"\n";  
}
Sö dông khu«n h×nh líp  
Mét khi khu«n h×nh líp point ®· ®-îc ®Þnh nghÜa, mét khai b¸o nh- :  
point<int> ai;  
-249-  
Khu«n h×nh  
khai b¸o mét ®èi t-îng ai cã hai thµnh phÇn to¹ ®é lµ kiÓu nguyªn (int). §iÒu  
®ã cã nghÜa lµ point<int> cã vai trß nh- mét kiÓu d÷ liÖu líp; ng-êi ta gäi nã lµ  
mét líp thÓ hiÖn cña khu«n h×nh líp point. Mét c¸ch tæng qu¸t, khi ¸p dông mét  
kiÓu d÷ liÖu nµo ®ã víi khu«n h×nh líp point ta sÏ cã ®-îc mét líp thÓ hiÖn t-¬ng  
øng víi kiÓu d÷ liÖu. Nh- vËy:  
point<double> ad;  
®Þnh nghÜa mét ®èi t-îng ad cã c¸c to¹ ®é lµ sè thùc; cßn víi point<double>  
®ãng vai trß mét líp vµ ®-îc gäi lµ mét líp thÓ hiÖn cña khu«n h×nh líp point.  
Trong tr-êng hîp cÇn ph¶i truyÒn c¸c tham sè cho c¸c hµm thiÕt lËp, ta lµm  
b×nh th-êng. VÝ dô:  
point<int> ai(3,5);  
point<double> ad(2.5,4.4);  
VÝ dô sö dông khu«n h×nh líp  
Ta xÐt vÝ dô sau:  
VÝ dô 6.8  
/*templat9.cpp*/  
#include <iostream.h>  
#include <conio.h>  
//t¹o mét khu«n h×nh líp  
template <class T> class point {  
T x, y;  
public:  
point(T abs = 0, T ord = 0) {  
x = abs; y = ord;  
}
void display() {  
cout<<"Toa do: "<<x<<" "<<y<<"\n";  
}
};  
void main() {  
clrscr();  
-250-  
Khu«n h×nh  
point<int> ai(3,5); ai.display();  
point<char> ac('d','y'); ac.display();  
point<double> ad(3.5, 2.3); ad.display();  
getch();  
}
Toa do: 3 5  
Toa do: d y  
Toa do: 3.5 2.3  
C¸c tham sè trong khu«n h×nh líp  
Hoµn toµn gièng nh- khu«n h×nh hµm, c¸c khu«n h×nh líp cã thÓ cã c¸c tham  
sè kiÓu vµ tham sè biÓu thøc. Trong phÇn nµy ta bµn vÒ c¸c tham sè kiÓu; cßn c¸c  
tham sè biÓu thøc sÏ ®-îc nãi trong phÇn sau. Tuy cã nhiÒu ®iÓm gièng nhau gi÷a  
khu«n h×nh hµm vµ khu«n h×nh líp, nh-ng c¸c rµng buéc ®èi víi c¸c kiÓu tham sè  
l¹i kh«ng nh- nhau.  
Sè l-îng c¸c tham sè kiÓu trong mét khu«n h×nh líp  
XÐt vÝ dô khai b¸o sau:  
template <class T, class U, class V> //danh s¸ch ba tham sè kiÓu  
class try {  
T x;  
U t[5];  
...  
V fm1 (int, U);  
...  
};  
S¶n sinh mét líp thÓ hiÖn  
Mét líp thÓ hiÖn ®-îc khai b¸o b»ng c¸ch liÖt kª ®»ng sau tªn khu«n h×nh líp  
c¸c tham sè thùc (lµ tªn c¸c kiÓu d÷ liÖu) víi sè l-îng b»ng víi sè c¸c tham sè  
trong danh s¸ch (template<...>) cña khu«n h×nh líp. Sau ®©y ®-a ra mét sè vÝ dô  
vÒ líp thÓ hiÖn cña khu«n h×nh líp try:  
try <int, float, int> // líp thÓ hiÖn víi ba tham sè int, float, int  
try <int,int *, double>// líp thÓ hiÖn víi ba tham sè int, int *, double  
-251-  
Khu«n h×nh  
try <char *, int, obj> // líp thÓ hiÖn víi ba tham sè char *, int, obj  
Trong dßng cuèi ta cuèi gi¶ ®Þnh objlµ mét kiÓu d÷ liÖu ®· ®-îc ®Þnh nghÜa  
tr-íc ®ã. ThËm chÝ cã thÓ sö dông c¸c líp thÓ hiÖn ®Ó lµm tham sè thùc cho c¸c líp  
thÓ hiÖn kh¸c, ch¼ng h¹n:  
try <float, point<int>, double>  
try <point<int>,point<float>, char *>  
CÇn chó ý r»ng, vÊn ®Ò t-¬ng øng chÝnh x¸c ®-îc nãi tíi trong c¸c khu«n h×nh  
hµm kh«ng cßn hiÖu lùc víi c¸c khu«n h×nh líp. Víi c¸c khu«n h×nh hµm, viÖc s¶n  
sinh mét thÓ hiÖn kh«ng chØ dùa vµo danh s¸ch c¸c tham sè cã trong  
template<...> mµ cßn dùa vµo danh s¸ch c¸c tham sè h×nh thøc trong tiªu ®Ò cña  
hµm.  
Mét tham sè h×nh thøc cña mét khu«n h×nh hµm cã thÓ cã kiÓu, lµ mét líp  
thÓ hiÖn nµo ®ã, ch¼ng h¹n:  
template <class T> void fct(point<T>) { ... }  
ViÖc khëi t¹o míi c¸c kiÓu d÷ liÖu míi vÉn ¸p dông ®-îc trong c¸c khu«n h×nh  
líp. Mét khu«n h×nh líp cã thÓ cã c¸c thµnh phÇn(d÷ liÖu hoÆc hµm) static. Trong  
tr-êng hîp nµy, cÇn ph¶i biÕt r»ng, mçi thÓ hiÖn cña líp cã mét tËp hîp c¸c thµnh  
phÇn static cña riªng m×nh:  
C¸c tham sè biÓu thøc trong khu«n h×nh líp  
Mét khu«n h×nh líp cã thÓ chøa c¸c tham sè biÓu thøc. So víi khu«n h×nh hµm,  
kh¸i niÖm tham sè biÓu thøc trong khu«n h×nh líp cã mét sè ®iÓm kh¸c biÖt: tham  
sè thùc tÕ t-¬ng øng víi tham sè biÓu thøc ph¶i lµ mét h»ng sè.  
Gi¶ sö r»ng ta muèn ®Þnh nghÜa mét líp table ®Ó thao t¸c trªn c¸c b¶ng chøa  
c¸c ®èi t-îng cã kiÓu bÊt kú. Mét c¸ch tù nhiªn ta nghÜ ngay ®Õn viÖc t¹o mét  
khu«n h×nh líp víi mét tham sè kiÓu. §ång thêi cßn cã thÓ dïng mét tham sè thø  
hai ®Ó x¸c ®Þnh sè thµnh phÇn cña m¶ng. Trong tr-êng hîp nµy, ®Þnh nghÜa cña  
khu«n h×nh líp cã d¹ng nh- sau:  
template <class T, int n> class table {  
T tab[n];  
public:  
...  
};  
Danh s¸ch c¸c tham sè (template<...>) chøa hai tham sè víi ®Æc ®iÓm kh¸c  
nhau hoµn toµn: mét tham sè kiÓu ®-îc x¸c ®inh bëi tõ kho¸ class, mét tham sè  
-252-  
Tải về để xem bản đầy đủ
pdf 33 trang Thùy Anh 26/04/2022 6340
Bạn đang xem 20 trang mẫu của tài liệu "Giáo trình Lập trình hướng đối tượng với C++ - Chương 6: Khuôn hình", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

File đính kèm:

  • pdfgiao_trinh_lap_trinh_huong_doi_tuong_voi_c_chuong_6_khuon_hi.pdf