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 đủ
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:
- giao_trinh_lap_trinh_huong_doi_tuong_voi_c_chuong_6_khuon_hi.pdf