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 vµ 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- lµ 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 22620 Free
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