-233-
Ch
Ch
Ch
Ch
ơ
ơ
ơ
ơ
ng
ng
ng
ng
6
6
6
6
khu
khu
khu
khu
ô
ô
ô
ô
n
n
n
n
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
(Template)
(Template)
(Template)
(Template)
Mụcđíchchơngnày:
1.
Hiểuđợclợiíchcủaviệcsửdụngkhuônhìnhhàmvàkhuônhìnhlớpđể
viếtchơngtrình.
2.Biếtcáchtạovàsửdụngmộtkhuônhìnhhàmvàkhuônhìnhlớp.
3.Kháiniệmcácthamsốkiểuvàcácthamsốbiểuthứctrongkhuônhình
hàm,khuônhìnhlớp.
4.
Địnhnghĩachồngkhuônhìnhhàm.
5.Cụthểhoámộtkhuônhìnhhàm,mộthàmthànhphầncủakhuônhìnhlớp.
6.Thuậttoánsảnsinhmộtthểhiệnhàm(hàmthểhiện)củamộtkhuônhình
hàm
7.
Cácvấnđềkháccủalậptrìnhhớngđốitợngliênquanđếnkhuônhình
lớp.
Khu
Khu
Khu
Khu
ô
ô
ô
ô
n
n
n
n
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
h
h
h
h
à
à
à
à
m
m
m
m
Khu
Khu
Khu
Khu
ô
ô
ô
ô
n
n
n
n
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
h
h
h
h
à
à
à
à
m
m
m
m
l
l
l
l
à
à
à
à
g
g
g
g
ì
ì
ì
ì
?
?
?
?
Tađãbiếtđịnhnghĩachồnghàmchophépdùngmộttênduynhấtchonhiều
hàmthựchiệncáccôngviệckhácnhau.Kháiniệmkhuônhìnhhàmcũngchophép
sửdụngcùngmộttênduynhấtđểthựchiệncáccôngviệckhácnhau,tuynhiênso
vớiđịnhnghĩachồnghàm,nócóphầnmạnhhơnvàchặtchẽhơn;mạnhhơnvìchỉ
cầnviếtđịnhnghĩakhuônhìnhhàmmộtlần,rồisauđóchơngtrìnhbiêndịchlàm
chonóthíchứngvớicáckiểudữliệukhácnhau;chặtchẽhơnbởivìdựatheo
khuônhìnhhàm,tấtcảcáchàmthểhiệnđợcsinhrabởitrìnhbiêndịchsẽtơng
ứngvớicùngmộtđịnhnghĩavànhvậysẽcócùngmộtgiảithuật.
T
T
T
T
ạ
ạ
ạ
ạ
o
o
o
o
m
m
m
m
ộ
ộ
ộ
ộ
t
t
t
t
khu
khu
khu
khu
ô
ô
ô
ô
n
n
n
n
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
h
h
h
h
à
à
à
à
m
m
m
m
Giảthiếtrằngchúngtacầnviếtmộthàm
m in
đaragiátrịnhỏnhấttronghai
giátrịcócùngkiểu.Tacóthểviếtmộtđịnhnghĩanhthếđốivớikiểu
int
nhsau:
intmin(int
a,
int
b)
{
if(a
<
b)
return
a;
Khuônh
ì
nh
-234-
elsereturn
b;
}
Giảsử,talạiphảiviếtđịnhnghĩahàm
min()
chokiểu
double
double
double
double
,
float
float
float
float
,
char,char
char,char
char,char
char,char
*
float
min(float
a,
float
b){
if(a<b)
return
a;
else
b;}
Nếutiếptụcnhvậy,sẽcókhuynhhớngphảiviếtrấtnhiềuđịnhnghĩahàm
hoàntoàntơngtựnhau;chỉcókiểudữliệucácthamsốlàthayđổi.Cácchơng
trìnhbiêndịchC++hiệncóchophépgiảiquyếtđơngiảnvấnđềtrênbằngcách
địnhnghĩamộtkhuônhìnhhàmduynhấttheocáchnhsau:
#include
<iostream.h>
//tạomộtkhuônhìnhhàm
template
<class
T>
T
min(T
a,
T
b)
{
if(a
<
b)
return
a;
elsereturn
b;
}
Sosánhvớiđịnhnghĩahàmthôngthờng,tathấychỉcódòngđầutiênbịthay
đổi:
template
<class
T>T
min
(Ta,Tb)
trong
đó
template<class
T>
xácđịnhrằngđólàmộtkhuônhìnhvớimộtthamsốkiểuT;
Phầncònlại
T
min(T
a,Tb)
nóirằng,
m in()
làmộthàmvớihaithamsốhìnhthứckiểu
T
vàcógiátrịtrảvề
cũnglàkiểu
T
.
Khuônh
ì
nh
-235-
S
S
S
S
ử
ử
ử
ử
d
d
d
d
ụ
ụ
ụ
ụ
ng
ng
ng
ng
khu
khu
khu
khu
ô
ô
ô
ô
n
n
n
n
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
h
h
h
h
à
à
à
à
m
m
m
m
Khu
Khu
Khu
Khu
ô
ô
ô
ô
n
n
n
n
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
h
h
h
h
à
à
à
à
m
m
m
m
cho
cho
cho
cho
ki
ki
ki
ki
ể
ể
ể
ể
u
u
u
u
d
d
d
d
ữ
ữ
ữ
ữ
li
li
li
li
ệ
ệ
ệ
ệ
u
u
u
u
c
c
c
c
ơ
ơ
ơ
ơ
s
s
s
s
ở
ở
ở
ở
Đểsửdụngkhuônhìnhhàm
min()
vừatạora,chỉcầnsửdụnghàm
min()
trongnhữngđiềukiệnphùhợp(ởđâycónghĩalàhaithamsốcủahàmcócùng
kiểudữliệu).Nhvậy,nếutrongmộtchơngtrìnhcóhaithamsốnguyên
n
và
p
,
vớilờigọi
min(n,p)
chơngtrìnhbiêndịchsẽtựđộngsảnsinhrahàm
min()
(ta
gọilàmộthàmthểhiện)tơngứngvớihaithamsốkiểunguyên
int
int
int
int
.Nếuchúngta
gọi
min()
vớihaithamsốkiểu
float
float
float
float
,chơngtrìnhbiêndịchcũngsẽtựđộngsản
sinhmộthàmthểhiện
min
kháctơngứngvớicácthamsốkiểu
float
float
float
float
vàcứthế.
Sauđâylàmộtvídụhoànchỉnh:
V
V
V
V
í
í
í
í
d
d
d
d
ụ
ụ
ụ
ụ
6.1
6.1
6.1
6.1
/*template1.cpp*/
/*template1.cpp*/
/*template1.cpp*/
/*template1.cpp*/
#include
<iostream.h>
#include<conio.h>
//tạomộtkhuônhìnhhàm
template
<class
T>
T
min(T
a,
T
b)
{
if
(a<
b)
return
a;
elsereturn
b;
}
//vídụsửdụngkhuônh
ì
nhhàmmin
voidmain()
{
clrscr();
int
n=
4,
p=
12;
float
x=
2.5,
y=
3.25;
cout<<"min
(n,
p)
=
"<<min(n,
p)<<"\n";
//intmin(int,int)
cout<<"min
(x,
y)
=
"<<min(x,
y)<<"\n";
//floatmin(float,float)
getch();
}
min(n,p)=4
min(x,y)=2.5
Khuônh
ì
nh
-236-
Khu
Khu
Khu
Khu
ô
ô
ô
ô
n
n
n
n
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
h
h
h
h
à
à
à
à
m
m
m
m
min
min
min
min
cho
cho
cho
cho
ki
ki
ki
ki
ể
ể
ể
ể
u
u
u
u
char
char
char
char
*
*
*
*
/*template2.cpp*/
/*template2.cpp*/
/*template2.cpp*/
/*template2.cpp*/
#include
<iostream.h>
#include<conio.h>
template
<class
T>
T
min
(Ta,
T
b)
{
if(a
<
b)
return
a;
elsereturn
b;
}
voidmain()
{
clrscr();
char
*
adr1
=
"DHBK";
char
*
adr2
=
"CDSD";
cout
<<
"min(adr1,adr2)="<<min(adr1,adr2);
getch();
}
min(adr1,adr2)=DHBK
Kếtquảkháthúvịvìtahyvọnghàm
m in()
trảvềxâu"CDSD".Thựctế,với
biểuthức
min(adr1,
adr2)
,chơngtrìnhbiêndịchđãsinhrahàmthểhiệnsau
đây:
char
*
min(char
*
a,
char
*
b)
{
if(a
<
b)
return
a;
elsereturn
b;
}
Việcsosánh
a<b
thựchiệntrêncácgiátrịbiếntrỏ(ởđâytrongcáckhuôn
hìnhmáyPCtaluônluôncó
a<b
).Ngợclạiviệchiểnthịthựchiệnbởitoántử
<<sẽđaraxâukýtựtrỏbởicontrỏkýtự.
K
K
K
K
hu
hu
hu
hu
ô
ô
ô
ô
n
n
n
n
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
h
h
h
h
à
à
à
à
m
m
m
m
min
min
min
min
v
v
v
v
ớ
ớ
ớ
ớ
i
i
i
i
ki
ki
ki
ki
ể
ể
ể
ể
u
u
u
u
d
d
d
d
ữ
ữ
ữ
ữ
li
li
li
li
ệ
ệ
ệ
ệ
u
u
u
u
l
l
l
l
ớ
ớ
ớ
ớ
p
p
p
p
Đểápdụngkhuônhìnhhàm
min()
ởtrênvớikiểulớp,cầnphảiđịnhnghĩalớp
saochocóthểápdụngphéptoánsosánh
<
vớicácđốitợngcủalớpnày,nghĩa
làtaphảiđịnhnghĩamộthàmtoántử
operator
<
cholớp.Sauđâylàmộtvídụ
minhhoạ:
Khuônh
ì
nh
-237-
V
V
V
V
í
í
í
í
d
d
d
d
ụ
ụ
ụ
ụ
6.2
6.2
6.2
6.2
/*template3.cpp*/
/*template3.cpp*/
/*template3.cpp*/
/*template3.cpp*/
#include
<iostream.h>
#include<conio.h>
//khuônhìnhhàmmin
template
<class
T>
T
min(
T
a,
T
b)
{
if(a
<
b)
return
a;
elsereturn
b;
}
//lớpvect
classvect
{
int
x,y;
public:
vect(int
abs=0,intord
=
0)
{
x=
abs,
y=
ord;}
void
display()
{
cout<<x<<"
"<<y<<"\n";
}
friendint
operator
<
(vect
,
vect);
};
int
operator
<
(vect
a,
vect
b)
{
returna.x*a.x
+
a.y*a.y
<
b.x*b.x
+
b.y*b.y;
}
voidmain()
{
clrscr();
vect
u(3,2),v(4,1);
cout<<"min
(u,
v)
=
";
min(u,v).display();
getch();
}
min(u,v)=32
Nếutaápdụngkhuônhìnhhàm
min()
đốivớimộtlớpmàchađịnhnghĩa
toántử<,chơngtrìnhbiêndịchsẽđaramộtthôngbáolỗitơngtựnhviệc
địnhnghĩamộthàm
min()
chokiểulớpđó.
Khuônh
ì
nh
-238-
C
C
C
C
á
á
á
á
c
c
c
c
tham
tham
tham
tham
s
s
s
s
ố
ố
ố
ố
ki
ki
ki
ki
ể
ể
ể
ể
u
u
u
u
c
c
c
c
ủ
ủ
ủ
ủ
a
a
a
a
khu
khu
khu
khu
ô
ô
ô
ô
n
n
n
n
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
h
h
h
h
à
à
à
à
m
m
m
m
Phầnnàytrìnhbàycáchđavàocácthamsốkiểutrongmộtkhuônhìnhhàm,
đểchơngtrìnhbiêndịchsảnsinhmộthàmthểhiện.
C
C
C
C
á
á
á
á
c
c
c
c
tham
tham
tham
tham
s
s
s
s
ố
ố
ố
ố
ki
ki
ki
ki
ể
ể
ể
ể
u
u
u
u
trong
trong
trong
trong
đị
đị
đị
đị
nh
nh
nh
nh
ngh
ngh
ngh
ngh
ĩ
ĩ
ĩ
ĩ
a
a
a
a
khu
khu
khu
khu
ô
ô
ô
ô
n
n
n
n
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
h
h
h
h
à
à
à
à
m
m
m
m
Mộtcáchtổngquát,khuônhìnhhàmcóthểcómộthaynhiềuthamsốkiểu,
vớimỗithamsốnàycótừkhoáclass
class
class
class
điliềntrớc,chẳnghạnnh:
template
<class
T,
class
U>
intfct
(Ta,T
*b,
Uc)
{
}
Cácthamsốnàycóthểđểởbấtkỳđâutrongđịnhnghĩacủakhuônhìnhhàm,
nghĩalà:
Trongdòngtiêuđề(nhđãchỉratrongvídụtrên).
Trongcáckhaibáocácbiếncụcbộ.
(i)
Trongcácchỉthịthựchiện.
Chẳnghạn:
template
<class
T,
class
U>
intfct
(Ta,
T
*b,
U
c)
{
T
x;
//biếncụcbộxkiểuT
U
*adr;
//biếncụcbộadrkiểuU*
adr
=
new
T
[10];
//cấpphá
t
mộtmảng10thànhphầnkiểuT n=sizeof(T);
}
Taxemchơngtrìnhsau:
V
V
V
V
í
í
í
í
d
d
d
d
ụ
ụ
ụ
ụ
6.3
6.3
6.3
6.3
/*templat4.cpp*/
/*templat4.cpp*/
/*templat4.cpp*/
/*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;
}
voidmain()
{
clrscr();
int
n=1,
p=
2,
q=
3;
Khuônh
ì
nh
-239-
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();
}
Trongmọitrờnghợp,mỗithamsốkiểuphảixuấthiệnítnhấtmộtlầntrong
khaibáodanhsáchcácthamsốhìnhthứccủakhuônhìnhhàm.Điềuđóhoàntoàn
logicbờivìnhờcácthamsốnày,chơngtrìnhdịchmớicóthểsảnsinhrahàmthể
hiệncầnthiết.Điềugìsẽxảyranếutrongdanhsáchcácthamsốcủakhuônhình
hàmkhôngcóđủcácthamsốkiểu?Hiểnnhiênkhiđóchơngtrìnhdịchkhôngthể
xácđịnhcácthamsốkiểudữliệuthựcứngvớicácthamsốkiểuhìnhthứctrong
template< >
.
Khuônhìnhhàmsauđâythựchiệntraođổinộidungcủahaibiến.
V
V
V
V
í
í
í
í
d
d
d
d
ụ
ụ
ụ
ụ
6.4
6.4
6.4
6.4
/*templat5.cpp*/
/*templat5.cpp*/
/*templat5.cpp*/
/*templat5.cpp*/
#include
<iostream.h>
#include<conio.h>
//địnhnghĩakhuônh
ì
nhhàmđổichỗnộidunghaibiếnvớikiểubấtkỳ
template
<class
X>
voidswap(X&a,
X
&b)
{
X
temp;
temp=a;
a=b;
b=temp;
}
voidmain()
{
clrscr();
inti=10,j=20;
floatx=10.1,y=23.1;
cout<<"I
J
bandau:"<<i<<"
"<<j<<endl;
cout<<"X
Y
bandau:"<<x<<"
"<<y<<endl;
swap(i,j);
//đổ
i
chỗhaisốnguyên
Khuônh
ì
nh
-240-
swap(x,y);
//đổ
i
chỗhaisốnguyên
cout<<"I
J
saukhidoicho:"<<i<<"
"<<j<<endl;
cout<<"X
Y
saukhidoicho:"<<x<<"
"<<y<<endl;
getch();
}
IJbandau:1020
XYbandau:10.123.1
IJsaukhidoicho:2010
XYsaukhidoicho:23.110.1
Gi
Gi
Gi
Gi
ả
ả
ả
ả
i
i
i
i
thu
thu
thu
thu
ậ
ậ
ậ
ậ
t
t
t
t
s
s
s
s
ả
ả
ả
ả
n
n
n
n
sinh
sinh
sinh
sinh
m
m
m
m
ộ
ộ
ộ
ộ
t
t
t
t
h
h
h
h
à
à
à
à
m
m
m
m
th
th
th
th
ể
ể
ể
ể
hi
hi
hi
hi
ệ
ệ
ệ
ệ
n
n
n
n
Trởlạikhuônhìnhhàm
m in()
:
template
<class
T>
T
min(T
a,
T
b)
{
if(a
<
b)
return
a;
elsereturn
b;
}
Vớicáckhaibáo:
int
n;
char
c;
câuhỏiđặtralà:chơngtrìnhdịchsẽlàmgìkhigặplờigọikiểunhlà
min(n,c)
?Câutrảlờidựatrênhainguyêntắcsauđây:
(ii)
C++quyđịnhphảicómộtsựtơngứngchínhxácgiữakiểucủathamsố
hìnhthứcvàkiểuthamsốthựcsựđợctruyềnchohàm,tắclàtachỉcóthểsử
dụngkhuônhìnhhàm
min()
trongcáclờigọivớihaithamsốcócùngkiểu.
Lờigọi
min(n,
c)
khôngđợcchấpnhậnvàsẽgâyralỗibiêndịch.
(iii)
C++thậmchícònkhôngchophépcácchuyểnkiểuthôngthờngnhlà:
T
thànhconst
T
hay
T[]
thành
T*
,nhữngtrờnghợphoàntoànđợcphéptrong
địnhnghĩachồnghàm.
Tathamkhảođoạnchơngtrìnhsauđây:
int
n;
char
c;
unsigned
int
q;
Khuônh
ì
nh
-241-
constint
r=
10;
intt[10];
int*adi;
min(n,
c)
//lỗi
min(n,
q)
//lỗi
min(n,
r)
//lỗi
min(t,adi)
//lỗi
Kh
Kh
Kh
Kh
ở
ở
ở
ở
i
i
i
i
t
t
t
t
ạ
ạ
ạ
ạ
o
o
o
o
c
c
c
c
á
á
á
á
c
c
c
c
bi
bi
bi
bi
ế
ế
ế
ế
n
n
n
n
c
c
c
c
ó
ó
ó
ó
ki
ki
ki
ki
ể
ể
ể
ể
u
u
u
u
d
d
d
d
ữ
ữ
ữ
ữ
li
li
li
li
ệ
ệ
ệ
ệ
u
u
u
u
chu
chu
chu
chu
ẩ
ẩ
ẩ
ẩ
n
n
n
n
Trongkhuônhìnhhàm,thamsốkiểucóthểtơngứngkhithìmộtkiểudữliệu
chuẩn,khithìmộtkiểudữliệulớp.Sẽlàmgìkhitacầnphảikhaibáobêntrong
khuônhìnhhàmmộtđốitợngvàtruyềnmộthaynhiềuthamsốchohàmthiếtlập
củalớp.Xemvídụsauđây:
template
<class
T>
fct(T
a)
{
T
x(3);
//x
l
àmộtđối
t
ợngcụcbộkiểuTmàchúngtaxâydựngbằngcách
//truyềngiátr
ị
3chohàmthiếtlập
}
Khisửdụnghàm
fct()
chomộtkiểudữliệulớp,mọiviệcđềutốtđẹp.Ngợc
lại,nếuchúngtacốgắngápdụngchomộtkiểudữliệuchuẩn,chẳnghạnnhint
int
int
int
,
khiđóchơngtrìnhdịchsảnsinhrahàmsauđây:
fct(int
a)
{
intx(3);
}
Đểchochỉthị
intx(3)
;
khônggâyralỗi,C++đãngầmhiểucâulệnhđónhlàphépkhởitạobiếnx
vớigiátrị3,nghĩalà:
int
x=3;
Mộtcáchtơngtự:
doublex(3.5);
//thayvìdoublex=3.5;
charc('e');
//thayvìcharc='e';
Khuônh
ì
nh
-242-
C
C
C
C
á
á
á
á
c
c
c
c
h
h
h
h
ạ
ạ
ạ
ạ
n
n
n
n
ch
ch
ch
ch
ế
ế
ế
ế
c
c
c
c
ủ
ủ
ủ
ủ
a
a
a
a
khu
khu
khu
khu
ô
ô
ô
ô
n
n
n
n
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
h
h
h
h
à
à
à
à
m
m
m
m
Vềnguyêntắc,khiđịnhnghĩamộtkhuônhìnhhàm,mộtthamsốkiểucóthể
tơngứngvớibấtkỳkiểudữliệunào,chodùđólàmộtkiểuchuẩnhaymộtkiểu
lớpdongờidùngđịnhnghĩa.Dovậykhôngthểhạnchếviệcthểhiệnđốivớimột
sốkiểudữliệucụthểnàođó.Chẳnghạn,nếumộtkhuônhìnhhàmcódòngđầu
tiên:
template
<class
T>
voidfct(T)
chúngtacóthểgọi
fct()
vớimộtthamsốvớikiểubấtkỳ:int
int
int
int
,
float
float
float
float
,
int
int
int
int
* ,
int
int
int
int
**,
t
*
(
t
làmộtkiểudữliệunàođấy)
Tuynhiên,chínhđịnhnghĩabêntrongkhuônhìnhhàmlạichứamộtsốyếutố
cóthểlàmchoviệcsảnsinhhàmthểhiệnkhôngđúngnhmongmuốn.Tagọiđó
làcáchạnchếcủacáckhuônhìnhhàm.
Đầutiên,chúngtacóthểchorằngmộtthamsốkiểucóthểtơngứngvớimột
contrỏ.Dođó,vớidòngtiêuđề:
template
<class
T>
voidfct(T
*)
tachỉcóthểgọi
fct()
vớimộtcontrỏđếnmộtkiểunàođó:int
int
int
int
*,
int
int
int
int
**,
t
*,t**
.
Trongcáctrờnghợpkhác,sẽgâyracáclỗibiêndịch.Ngoàira,trongđịnh
nghĩacủamộtkhuônhìnhhàm,cóthểcócácchỉthịkhôngthíchhợpđốivớimột
sốkiểudữliệunhấtđịnh.Chẳnghạn,khuônhìnhhàm:
template
<class
T>
T
min(T
a,
T
b)
{
if(a
<
b)
return
a;
elsereturn
b;
}
khôngthểdùngđợcnếu
T
tơngứngvớimộtkiểulớptrongđóphéptoán<
khôngđợcđịnhnghĩachồng.Mộtcáchtơngtựvớimộtkhuônhìnhhàmkiểu:
template
<class
T>
voidfct(T)
{
T
x(2,5);
/*đốitợngcụcbộđợckhở
i
tạobằngmộthàmthiếtlậpvới
haithamsố*/
}
khôngthểápdụngchocáckiểudữliệulớpkhôngcóhàmthiếtlậpvớihai
thamsố.
Tómlại,mặcdùkhôngtồntạimộtcơchếhìnhthứcđểhạnchếkhảnăngáp
dụngcủacáckhuônhìnhhàm,nhngbêntrongmỗimộtkhuônhìnhhàmđềucó
Khuônh
ì
nh
-243-
chứanhữngnhântốđểngờitacóthểbiếtđợckhuônhìnhhàmđócóthểđợcáp
dụngđếnmứcnào.
C
C
C
C
á
á
á
á
c
c
c
c
tham
tham
tham
tham
s
s
s
s
ố
ố
ố
ố
bi
bi
bi
bi
ể
ể
ể
ể
u
u
u
u
th
th
th
th
ứ
ứ
ứ
ứ
c
c
c
c
c
c
c
c
ủ
ủ
ủ
ủ
a
a
a
a
m
m
m
m
ộ
ộ
ộ
ộ
t
t
t
t
khu
khu
khu
khu
ô
ô
ô
ô
n
n
n
n
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
h
h
h
h
à
à
à
à
m
m
m
m
Trongđịnhnghĩacủamộtkhuônhìnhhàmcóthểkhaibáocácthamsốhình
thứcvớikiểuxácđịnh.Tagọichúnglàcácthamsốbiểuthức.Chơngtrình
templat6.cpp
sauđâyđịnhnghĩamộtkhuônhìnhhàmchophépđếmsốlợng
cácphầntửnul(0đốivớicácgiátrịsốhoặcNULLnếulàcontrỏ)trongmộtbảng
vớikiểubấtkỳvàkíchthớcnàođó:
V
V
V
V
í
í
í
í
d
d
d
d
ụ
ụ
ụ
ụ
6.5
6.5
6.5
6.5
/*templat6.cpp*/
/*templat6.cpp*/
/*templat6.cpp*/
/*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++;
returnnz;
}
voidmain()
{
clrscr();
intt[5]
=
{5,
2,0,2,
0};
charc[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
Tacóthểnóirằngkhuônhìnhhàm
compte
địnhnghĩamộthọcáchàm
compte
trongđókiểucủathamsốđầutiênlàtuỳý(đợcxácđịnhbởilờigọi),còn
kiểucủathamsốthứhaiđãxácđịnh(kiểu
int
int
int
int
).
Khuônh
ì
nh
-244-
Đị
Đị
Đị
Đị
nh
nh
nh
nh
ngh
ngh
ngh
ngh
ĩ
ĩ
ĩ
ĩ
a
a
a
a
ch
ch
ch
ch
ồ
ồ
ồ
ồ
ng
ng
ng
ng
c
c
c
c
á
á
á
á
c
c
c
c
khu
khu
khu
khu
ô
ô
ô
ô
n
n
n
n
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
h
h
h
h
à
à
à
à
m
m
m
m
Giốngnhviệcđịnhnghĩachồngcáchàmthôngthờng,C++chophépđịnh
nghĩachồngcáckhuônhìnhhàm,tứclàcóthểđịnhnghĩamộthaynhiềukhuôn
hìnhhàmcócùngtênnhngvớicácthamsốkhácnhau.Điềuđósẽtạoranhiềuhọ
cáchàm(mỗikhuônhìnhhàmtơngứngvớimộthọcáchàm).Vídụcóbahọhàm
m in
:
(iv)
Họthứnhấtbaogồmcáchàmtìmgiátrịnhỏnhấttronghaigiátrị,
(v)Họthứhaitìmsốnhỏnhấttrongbasố,
(vi)
Họthứbatìmsốnhỏnhấttrongmộtmảng.
V
V
V
V
í
í
í
í
d
d
d
d
ụ
ụ
ụ
ụ
6.6
6.6
6.6
6.6
/*templat7.cpp*/
/*templat7.cpp*/
/*templat7.cpp*/
/*templat7.cpp*/
#include
<iostream.h>
#include<conio.h>
//khuônhình1
template
<class
T>
T
min(T
a,
T
b)
{
if(a
<
b)
return
a;
elsereturn
b;
}
//khuônhình2
template
<class
T>
T
min(T
a,
T
b,
T
c)
{
returnmin(min(a,b),c);
}
//khuônhình3
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];
returnres;
}
voidmain()
{
clrscr();
int
n=
12,
p=
15,
q=
2;
Khuônh
ì
nh
-245-
float
x=
3.5,
y=
4.25,
z=
0.25;
intt[6]
=
{2,
3,
4,-1,21};
charc[4]
=
{'w','q','a','Q'};
cout<<
min(n,p)
=
<<min(n,p)<<"\n";
//
khu
ônh
ì
nh
1
int
min(int,
int)
cout<<
min(n,p,q)
=
<<min(n,p,q)<<"\n";
//khuônhình2intmin(int,int,int)
cout<<
min(x,y)
=
<<min(x,y)<<"\n";
//
khu
ônh
ì
nh
1
float
min(float,
float)
cout<<
min(x,y,z)
=
<<min(x,y,z)<<"\n";
//
khu
ônh
ì
nh
2
floatm in(float,float,float)
cout<<
min(t,6)
=
<<min(t,6)<<"\n";
//khuônhình3intmin(int*,int)
cout<<
min(c,4)
=
<<min(c,4)<<"\n";
//
khu
ônh
ì
nh
3
charmin(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
Nh
Nh
Nh
ậ
ậ
ậ
ậ
n
n
n
n
x
x
x
x
é
é
é
é
t
t
t
t
Cũnggiốngnhđịnhnghĩachồngcáchàm,việcđịnhnghĩachồngcáckhuôn
hìnhhàmcóthểgâyrasựnhậpnhằngtrongviệcsảnsinhcáchàmthểhiện.Chẳng
hạnvớibốnhọhàmsauđâ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étcáccâulệnhsauđây:
int
x;
int
y;
Khuônh
ì
nh
-246-
Lờigọi
fct(&x,&y)
cóthểtơngứngvớikhuônhìnhhàm1haykhuônhìnhhàm4.
C
C
C
C
ụ
ụ
ụ
ụ
th
th
th
th
ể
ể
ể
ể
ho
ho
ho
ho
á
á
á
á
c
c
c
c
á
á
á
á
c
c
c
c
h
h
h
h
à
à
à
à
m
m
m
m
th
th
th
th
ể
ể
ể
ể
hi
hi
hi
hi
ệ
ệ
ệ
ệ
n
n
n
n
Mộtkhuônhìnhhàmđịnhnghĩamộthọcáchàmdựatrênmộtđịnhnghĩa
chung,nóicáchkhácchúngthựchiệntheocùngmộtgiảithuật.Trongmộtsố
trờnghợp,sựtổngquátnàycóthểchịurủiro,chẳnghạnnhtrongtrờnghợp
ápdụngkhuônhìnhhàm
min
chokiểu
char
char
char
char
*nhđãnóiởtrên.Kháiniệmcụthể
hoá,đaramộtgiảiphápkhắcphụccácrủirokiểunhtrên.C++chophépta
cungcấp,ngoàiđịnhnghĩacủamộtkhuônhìnhhàm,địnhnghĩacủamộtsốcác
hàmchomộtsốkiểudữliệucủathamsố.Taxétchơngtrìnhvídụsauđây:
V
V
V
V
í
í
í
í
d
d
d
d
ụ
ụ
ụ
ụ
6.7
6.7
6.7
6.7
/*templat8.cpp*/
/*templat8.cpp*/
/*templat8.cpp*/
/*templat8.cpp*/
#include
<iostream.h>
#include<string.h>
#include<conio.h>
//khuônhìnhhàmmin
template
<class
T>
T
min
(Ta,
T
b)
{
if(a
<
b)
return
a;
elsereturn
b;
}
//hàmminchokiểuxâukýtự
char
*
min(char*cha,char*chb)
{
if
(strcmp(cha,chb)<0)returncha;
elsereturnchb;
}
voidmain()
{
clrscr();
int
n=
12,
p=
15;
char*adr1="DHBK",*adr2
="CD2D";
cout<<"min(n,
p)
=
"<<min(n,p)<<"\n";
//khuônhìnhhàm
cout<<"min(adr1,adr2)
=
"<<min(adr1,adr2)<<endl;
//hàmchar*min(char*,
Khuônh
ì
nh
-247-
//char*)
getch();
}
min(n,p)=12
min(adr1,adr2)=CD2D
Nhvậy,bảnchấtcủacụthểhoákhuônhìnhhàmlàđịnhnghĩacáchàmthông
thờngcócùngtênvớikhuônhìnhhàmđểgiảiquyếtmộtsốtrờnghợprủirokhi
taápdụngkhuônhìnhhàmchomộtsốkiểudữliệuđặcbiệtnàođó.
T
T
T
T
ổ
ổ
ổ
ổ
ng
ng
ng
ng
k
k
k
k
ế
ế
ế
ế
t
t
t
t
v
v
v
v
ề
ề
ề
ề
c
c
c
c
á
á
á
á
c
c
c
c
khu
khu
khu
khu
ô
ô
ô
ô
n
n
n
n
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
h
h
h
h
à
à
à
à
m
m
m
m
Mộtcáchtổngquát,tacóthểđịnhnghĩamộthaynhiềukhuônhìnhcùngtên,
mỗikhuônhìnhcócácthamsốkiểucũngnhlàcácthamsốbiểuthứcriêng.Hơn
nữa,cóthểcungcấpcáchàmthôngthờngvớicùngtênvớimộtkhuônhìnhhàm;
trongtrờnghợpnàytanóiđólàsựcụthểhoámộthàmthểhiện.
Trongtrờnghợptổngquátkhicóđồngthờicảhàmđịnhnghĩachồngvà
khuônhìnhhàm,chơngtrìnhdịchlựachọnhàmtơngứngvớimộtlờigọihàm
dựatrêncácnguyêntắcsauđây:
(vii)
Đầutiên,kiểmtratấtcảcáchàmthôngthờngcùngtênvàchúýđếnsự
tơngứngchínhxác;nếuchỉcómộthàmphùhợp,hàmđóđợcchọn;cònnếu
cónhiềuhàmcùngthoảmãn(cósựnhậpnhằng)sẽtạoramộtlỗibiêndịchvà
quátrìnhtìmkiếmbịgiánđoạn.
(viii)
Nếukhôngcóhàmthôngthờngnàotơngứngchínhxácvớilờigọi,khi
đótakiểmtratấtcảcáckhuônhìnhhàmcócùngtênvớilờigọi;nếuchỉcó
mộttơngứngchínhxácđợctìmthấy,hàmthểhiệntơngứngđợcsảnsinh
vàvấnđềđợcgiảiquyết;cònnếucónhiềuhơnmộtkhuônhìnhhàm(cósự
nhậpnhằng)điềuđósẽgâyralỗibiêndịchvàquátrìnhtìmkiếmbịngắt.
(ix)
Cuốicùng,nếukhôngcókhuônhìnhhàmphùhợp,takiểmtramộtlầnnữa
tấtcảcáchàmthôngthờngcùngtênvớilờigoi.Trongtrờnghợpnàychúng
taphảitìmkiếmsựtơngứngdựavàocảcácchuyểnkiểuchophéptrong
C/C++.
KHU
KHU
KHU
KHU
ô
ô
ô
ô
N
N
N
N
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
l
l
l
l
ớ
ớ
ớ
ớ
p
p
p
p
Khu
Khu
Khu
Khu
ô
ô
ô
ô
n
n
n
n
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
l
l
l
l
ớ
ớ
ớ
ớ
p
p
p
p
l
l
l
l
à
à
à
à
g
g
g
g
ì
ì
ì
ì
?
?
?
?
Bêncạnhkháiniệmkhuônhìnhhàm,C++cònchophépđịnhnghĩakhuôn
hìnhlớp.Cũnggiốngnhkhuônhìnhhàm,ởđâytachỉcầnviếtđịnhnghĩacác
khuônhìnhlớpmộtlầnrồisauđócóthểápdụngchúngvớicáckiểudữliệukhác
nhauđểđợccáclớpthểhiệnkhácnhau.
Khuônh
ì
nh
-248-
T
T
T
T
ạ
ạ
ạ
ạ
o
o
o
o
m
m
m
m
ộ
ộ
ộ
ộ
t
t
t
t
khu
khu
khu
khu
ô
ô
ô
ô
n
n
n
n
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
l
l
l
l
ớ
ớ
ớ
ớ
p
p
p
p
Tathờngtạoralớppointtheokiểu(ởđâytabỏquađịnhnghĩacủacác
hàmthànhphần):
classpoint
{
int
x,y;
public:
point(intabs=0,intord=0);
void
display();
//
};
Trongvídụnày,tađịnhnghĩamộtlớpcácđiểmcótoạđộnguyên.Nếumuốn
toạđộđiểmcókiểudữliệukhác(float,
float,
float,
float,
double,
double,
double,
double,
long,
long,
long,
long,
unsigned
unsigned
unsigned
unsigned
int
int
int
int
)taphải
địnhnghĩamộtlớpkhácbằngcáchthaythế,trongđịnhnghĩalớp
point
,từkhoá
int
int
int
int
bằngtừkhoátơngứngvớikiểudữliệumongmuốn.
Đểtránhsựtrùnglặptrongcáctìnhhuốngnhtrên,chơngtrìnhdịchC++
chophépđịnhnghĩamộtkhuônhìnhlớpvàsauđó,ápdụngkhuônhìnhlớpnàyvới
cáckiểudữliệukhácnhauđểthuđợccáclớpthểhiệnnhmongmuốn:
template
<class
T>
classpoint
{
T
x;
T
y;
public:
point
(T
abs=0,
T
ord=0);
void
display();
};
Cũnggiốngnhcáckhuônhìnhhàm,tậphợp
template<class
T>
xácđịnh
rằngđólàmộtkhuônhìnhtrongđócómộtthamsốkiểu
T
;Cũngcầnphảinhắclại
rằng,C++sửdụngtừkhoáclass
class
class
class
chỉđểnóirằng
T
đạidiệnchomộtkiểudữliệu
nàođó.Tiếptheođâytabànđếnviệcđịnhnghĩacáchàmthànhphầncủakhuôn
hìnhlớp.Ngờitaphânbiệthaitrờnghợp:(i)Khihàmthànhphầnđợcđịnh
nghĩabêntrongđịnhnghĩalớptrờnghợpnàykhôngcógìthayđổi.Xétđịnhnghĩa
hàmthiếtlậpsauđây:
template
<class
T>
classpoint
{
T
x;
T
y;
public:
point(Tabs=0,
T
ord=0)
{
Khuônh
ì
nh
-249-
x=
abs;
y=
ord;
}
};
(ii)Ngợclại,khiđịnhnghĩacủahàmthànhphầnnằmngoàiđịnhnghĩalớp,
khiđócầnphảinhắclạichochơngtrìnhdịchbiết:cácthamsốkiểucủakhuôn
hìnhlớp,cónghĩalàphảinhắclại:
template
<class
T>
trớcđịnhnghĩahàm,
còntêncủakhuônhìnhlớpđợcviếtnhlà
point<T>
Tómlại,dòngtiêuđềđầyđủchohàmthànhphần
display()
củakhuônhình
hàmpointnhsau:
template
<class
T>
void
point<T>::display()
Sauđâylàđịnhnghĩađầyđủcủakhuônhìnhlớppoint:
#include
<iostream.h>
//tạokhuônhìnhhàm
template
<class
T>
classpoint
{T
x,y;
public:
//địnhnghĩahàmthànhphầnởbêntrongkhuônhình
l
ớp
point(Tabs
=
0,
T
ord
=
0)
{
x=
abs;
y=
ord;
}
void
display();
};
//địnhnghĩahàmthànhphầnởbênngoà
i
khuônhình
l
ớp
template
<class
T>
void
point<T>::display()
{
cout<<"Toa
do:"<<x<<"
"<<y<<"\n";
}
S
S
S
S
ử
ử
ử
ử
d
d
d
d
ụ
ụ
ụ
ụ
ng
ng
ng
ng
khu
khu
khu
khu
ô
ô
ô
ô
n
n
n
n
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
l
l
l
l
ớ
ớ
ớ
ớ
p
p
p
p
Mộtkhikhuônhìnhlớppointđãđợcđịnhnghĩa,mộtkhaibáonh:
point<int>
ai;
Khuônh
ì
nh
-250-
khaibáomộtđốitợng
ai
cóhaithànhphầntoạđộlàkiểunguyên(
int
int
int
int
)
.Điều
đócónghĩalà
point<int>
cóvaitrònhmộtkiểudữliệulớp;ngờitagọinólà
mộtlớpthểhiệncủakhuônhìnhlớp
point
.Mộtcáchtổngquát,khiápdụngmột
kiểudữliệunàođóvớikhuônhìnhlớppointtasẽcóđợcmộtlớpthểhiệntơng
ứngvớikiểudữliệu.Nhvậy:
point<double>
ad;
địnhnghĩamộtđốitợng
ad
cócáctoạđộlàsốthực;cònvới
point<double>
đóngvaitròmộtlớpvàđợcgọilàmộtlớpthểhiệncủakhuônhìnhlớppoint.
Trongtrờnghợpcầnphảitruyềncácthamsốchocáchàmthiếtlập,talàm
bìnhthờng.Vídụ:
point<int>ai(3,5);
point<double>
ad(2.5,4.4);
V
V
V
V
í
í
í
í
d
d
d
d
ụ
ụ
ụ
ụ
s
s
s
s
ử
ử
ử
ử
d
d
d
d
ụ
ụ
ụ
ụ
ng
ng
ng
ng
khu
khu
khu
khu
ô
ô
ô
ô
n
n
n
n
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
l
l
l
l
ớ
ớ
ớ
ớ
p
p
p
p
Taxétvídụsau:
V
V
V
V
í
í
í
í
d
d
d
d
ụ
ụ
ụ
ụ
6.8
6.8
6.8
6.8
/*templat9.cpp*/
/*templat9.cpp*/
/*templat9.cpp*/
/*templat9.cpp*/
#include
<iostream.h>
#include<conio.h>
//tạomộtkhuônhình
l
ớp
template
<class
T>
classpoint
{
T
x,y;
public:
point(Tabs
=
0,
T
ord
=
0)
{
x=
abs;
y=
ord;
}
void
display()
{
cout<<"Toa
do:"<<x<<"
"<<y<<"\n";
}
};
voidmain()
{
clrscr();
Khuônh
ì
nh
-251-
point<int>ai(3,5);ai.display();
point<char>
ac('d','y');
ac.display();
point<double>
ad(3.5,2.3);
ad.display();
getch();
}
Toado:35
Toado:dy
Toado:3.52.3
C
C
C
C
á
á
á
á
c
c
c
c
tham
tham
tham
tham
s
s
s
s
ố
ố
ố
ố
trong
trong
trong
trong
khu
khu
khu
khu
ô
ô
ô
ô
n
n
n
n
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
l
l
l
l
ớ
ớ
ớ
ớ
p
p
p
p
Hoàntoàngiốngnhkhuônhìnhhàm,cáckhuônhìnhlớpcóthểcócáctham
sốkiểuvàthamsốbiểuthức.Trongphầnnàytabànvềcácthamsốkiểu;còncác
thamsốbiểuthứcsẽđợcnóitrongphầnsau.Tuycónhiềuđiểmgiốngnhaugiữa
khuônhìnhhàmvàkhuônhìnhlớp,nhngcácràngbuộcđốivớicáckiểuthamsố
lạikhôngnhnhau.
S
S
S
S
ố
ố
ố
ố
l
l
l
l
ợ
ợ
ợ
ợ
ng
ng
ng
ng
c
c
c
c
á
á
á
á
c
c
c
c
tham
tham
tham
tham
s
s
s
s
ố
ố
ố
ố
ki
ki
ki
ki
ể
ể
ể
ể
u
u
u
u
trong
trong
trong
trong
m
m
m
m
ộ
ộ
ộ
ộ
t
t
t
t
khu
khu
khu
khu
ô
ô
ô
ô
n
n
n
n
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
l
l
l
l
ớ
ớ
ớ
ớ
p
p
p
p
Xétvídụkhaibáosau:
template
<class
T,
class
U,
class
V>
//danhsáchbathamsốkiểu
classtry
{
T
x;
U
t[5];
V
fm1(int,U);
};
S
S
S
S
ả
ả
ả
ả
n
n
n
n
sinh
sinh
sinh
sinh
m
m
m
m
ộ
ộ
ộ
ộ
t
t
t
t
l
l
l
l
ớ
ớ
ớ
ớ
p
p
p
p
th
th
th
th
ể
ể
ể
ể
hi
hi
hi
hi
ệ
ệ
ệ
ệ
n
n
n
n
Mộtlớpthểhiệnđợckhaibáobằngcáchliệtkêđằngsautênkhuônhìnhlớp
cácthamsốthực(làtêncáckiểudữliệu)vớisốlợngbằngvớisốcácthamsố
trongdanhsách(
template< >
)củakhuônhìnhlớp.Sauđâyđaramộtsốvídụ
vềlớpthểhiệncủakhuônhìnhlớp
try
:
try<int,float,int>
//lớpthểhiệnvớibathamsốint,float,int
try
<int,int
*,
double>
//lớpthểhiệnvớibathamsốint,int
*
,double
Khuônh
ì
nh
-252-
try<char
*,
int,obj>
//lớpthểhiệnvớibathamsốchar*,int,obj
Trongdòngcuốitacuốigiảđịnh
obj
làmộtkiểudữliệuđãđợcđịnhnghĩa
trớcđó.Thậmchícóthểsửdụngcáclớpthểhiệnđểlàmthamsốthựcchocáclớp
thểhiệnkhác,chẳnghạn:
try<float,
point<int>,
double>
try
<point<int>,point<float>,
char
*>
Cầnchúýrằng,vấnđềtơngứngchínhxácđợcnóitớitrongcáckhuônhình
hàmkhôngcònhiệulựcvớicáckhuônhìnhlớp.Vớicáckhuônhìnhhàm,việcsản
sinhmộtthểhiệnkhôngchỉdựavàodanhsáchcácthamsốcótrong
template< >
màcòndựavàodanhsáchcácthamsốhìnhthứctrongtiêuđềcủa
hàm.
Mộtthamsốhìnhthứccủamộtkhuônhìnhhàmcóthểcókiểu,làmộtlớp
thểhiệnnàođó,chẳnghạn:
template
<class
T>
void
fct(point<T>)
{
}
Việckhởitạomớicáckiểudữliệumớivẫnápdụngđợctrongcáckhuônhình
lớp.Mộtkhuônhìnhlớpcóthểcócácthànhphần(dữliệuhoặchàm)static
static
static
static
.Trong
trờnghợpnày,cầnphảibiếtrằng,mỗithểhiệncủalớpcómộttậphợpcácthành
phầnstatic
static
static
static
củariêngmình:
C
C
C
C
á
á
á
á
c
c
c
c
tham
tham
tham
tham
s
s
s
s
ố
ố
ố
ố
bi
bi
bi
bi
ể
ể
ể
ể
u
u
u
u
th
th
th
th
ứ
ứ
ứ
ứ
c
c
c
c
trong
trong
trong
trong
khu
khu
khu
khu
ô
ô
ô
ô
n
n
n
n
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
l
l
l
l
ớ
ớ
ớ
ớ
p
p
p
p
Mộtkhuônhìnhlớpcóthểchứacácthamsốbiểuthức.Sovớikhuônhìnhhàm,
kháiniệmthamsốbiểuthứctrongkhuônhìnhlớpcómộtsốđiểmkhácbiệt:tham
sốthựctếtơngứngvớithamsốbiểuthứcphảilàmộthằngsố.
Giảsửrằngtamuốnđịnhnghĩamộtlớp
table
đểthaotáctrêncácbảngchứa
cácđốitợngcókiểubấtkỳ.Mộtcáchtựnhiêntanghĩngayđếnviệctạomột
khuônhìnhlớpvớimộtthamsốkiểu.Đồngthờicòncóthểdùngmộtthamsốthứ
haiđểxácđịnhsốthànhphầncủamảng.Trongtrờnghợpnày,địnhnghĩacủa
khuônhìnhlớpcódạngnhsau:
template
<class
T,
int
n>
classtable
{
T
tab[n];
public:
};
Danhsáchcácthamsố(
template< >
)chứahaithamsốvớiđặcđiểmkhác
nhauhoàntoàn:mộtthamsốkiểuđợcxácđinhbởitừkhoáclass
class
class
class
,mộtthamsố
Khuônh
ì
nh
-253-
biểuthứckiểu
int
>.Chúngtasẽphảichỉrõgiátrịcủachúngtrongkhaibáocáclớp
thểhiện.Chẳnghạn,lớpthểhiện:
table<int,4>
tơngứngvớikhaibáonhsau:
classtable<int,4>
{
inttab[4];
public:
};
Sauđâylàmộtvídụhoànchỉnh:
V
V
V
V
í
í
í
í
d
d
d
d
ụ
ụ
ụ
ụ
6.9
6.9
6.9
6.9
/*templat10.cpp*/
/*templat10.cpp*/
/*templat10.cpp*/
/*templat10.cpp*/
#include
<iostream.h>
#include<conio.h>
template
<class
T,
int
n>
classtable
{
T
tab[n];
public:
table()
{
cout<<"Taobang\n";}
T&
operator[](int
i)
{
returntab[i];
}
};
classpoint
{
int
x,y;
public:
point(intabs
=
1,
intord
=
1)
{
x=
abs;
y=
ord;
cout<<"Tao
diem"<<x<<"
"<<y<<"\n";
}
void
display()
{
cout<<"Toa
do:"<<x<<"
"<<y<<"\n";
Khuônh
ì
nh
-254-
}
};
voidmain()
{
clrscr();
table<int,
4>
ti;
for(int
i=
0;
i<
4;
i++)
ti[i]
=
i;
cout<<"ti:
";
for(i
=
0;
i<
4;
i++)
cout
<<ti[i]<<"
";
cout<<"\n";
table<point,
3>
tp;
for(i
=
0;
i<
3;
i++)
tp[i].display();
getch();
}
Taobang
ti:0123
Taodiem11
Taodiem11
Taodiem11
Taobang
Toado:11
Toado:11
Toado:11
T
T
T
T
ổ
ổ
ổ
ổ
ng
ng
ng
ng
qu
qu
qu
qu
á
á
á
á
t
t
t
t
v
v
v
v
ề
ề
ề
ề
khu
khu
khu
khu
ô
ô
ô
ô
n
n
n
n
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
l
l
l
l
ớ
ớ
ớ
ớ
p
p
p
p
Tacóthểkhaibáomộtsốtuỳýcácthamsốbiểuthứctrongdanhsáchcác
thamsốcủakhuônhìnhhàm.Cácthamsốnàycóthểxuấthiệnởbấtkỳnơinào
trongđịnhnghĩacủakhuônhìnhlớp.Khisảnsinhmộtlớpcócácthamsốbiểuthức,
cácthamsốthựctếtơngứngphảilàcácbiểuthứchằngphùhợpvớikiểudữliệu
đãkhaibáotrongdanhsáchcácthamsốhìnhthứccủakhuônhìnhlớp.
Khuônh
ì
nh
-255-
C
C
C
C
ụ
ụ
ụ
ụ
th
th
th
th
ể
ể
ể
ể
ho
ho
ho
ho
á
á
á
á
khu
khu
khu
khu
ô
ô
ô
ô
n
n
n
n
h
h
h
h
ì
ì
ì
ì
nh
nh
nh
nh
l
l
l
l
ớ
ớ
ớ
ớ
p
p
p
p
Khảnăngcụthểhoákhuônhìnhlớpcóđôichútkhácbiệtsovớikhuônhình
hàm.
Khuônhìnhlớpđịnhnghĩahọcáclớptrongđómỗilớpchứađồngthờiđịnh
nghĩacủachínhnóvàcáchàmthànhphần.Nhvậy,tấtcảcáchàmthànhphần
cùngtênsẽđợcthựchiệntheocùngmộtgiảithuật.Nếutamuốnchomộthàm
thànhphầnthíchứngvớimộttìnhhuốngcụthểcụthểnàođó,cóthểviếtmộtđịnh
nghĩakhácchonó.Sauđâylàmộtvídụcảitiếnkhuônhìnhlớppoint.ởđây
chúngtađãcụthểhoáhàmhiểnthị
display()
chotrờnghợpkiểudữliệu
char
char
char
char
:
V
V
V
V
í
í
í
í
d
d
d
d
ụ
ụ
ụ
ụ
6.10
6.10
6.10
6.10
/*templat11.cpp*/
/*templat11.cpp*/
/*templat11.cpp*/
/*templat11.cpp*/
#include
<iostream.h>
#include<conio.h>
//tạomộtkhuônhình
l
ớp
template
<class
T>
classpoint
{
T
x,y;
public:
point(Tabs
=
0,
T
ord
=
0)
{
x=
abs;
y=
ord;
}
void
display();
};
template
<class
T>
void
point<T>::display()
{
cout<<"Toa
do:"<<x<<"
"<<y<<"\n";
}
//Thêmmộthàmdisplaycụthểhoátrongtrờnghợpcácký
t
ự
void
point<char>::display()
{
cout<<"Toa
do:"<<(int)x<<"
"<<(int)y<<"\n";
}
voidmain()
{
clrscr();
point<int>
ai(3,5);
ai.display();
Khuônh
ì
nh
-256-
point<char>ac('d','y');
ac.display();
point
<double>
ad(3.5,2.3);
ad.display();
getch();
}
Toado:35
Toado:100121
Toado:3.52.3
Tachúýdòngtiêuđềtrongkhaibáomộtthànhphầnđợccụthểhoá:
void
point<char>::display()
Khaibáonàynhắcchơngtrìnhdịchsửdùnghàmnàythaythếhàm
display(
)
củakhuônhìnhlớppoint(trongtrờnghợpgiátrịthựctếchothamsốkiểulà
char
char
char
char
).
Nh
Nh
Nh
Nh
ậ
ậ
ậ
ậ
n
n
n
n
x
x
x
x
é
é
é
é
t
t
t
t
(x)
Cóthểcụthểhoágiátrịcủatấtcảcácthamsố.Xétkhuônhìnhlớpsauđây:
template
<class
T,
int
n>
classtable
{
T
tab[n];
public:
table()
{cout<<"
Tao
bang\n";
}
};
Khiđó,chúngtacóthểviếtmộtđịnhnghĩacụthểhoáchohàmthiếtlậpcho
cácbảng10phầntửkiểupointnhsau:
table<point,10>::table( )
{ }
(xi)Cóthểcụthểhoámộthàmthànhphầnhaymộtlớp.Trongvídụ6.10
chơngtrình
template11.cpp
đãcụthểhoámộthàmthànhphầncủakhuôn
hìnhlớp.Nóichungcóthể:cụthểhoámộthaynhiềuhàmthànhphần,hoặc
khôngcầnthayđổiđịnhnghĩacủabảnthânlớp(thựctếcầnphảilàmnhvậy)
màcụthểhoábảnthânlớpbằngcáchđathêmđịnhnghĩa.Khảnăngthứhai
nàycódẫntớiviệcphảicụthểhoámộtsốhàmthànhphần.Chẳnghạn,saukhi
địnhnghĩakhuônhình
template<class
T>
classpoint
,tacóthểđịnh
Khuônh
ì
nh
-257-
nghĩamộtphiênbảncụthểchokiểudữliệu
point
thíchhợpvớithểhiện
point<char>
.Talàmnhsau:
class
point<char>
{
//địnhnghĩamới
};
S
S
S
S
ự
ự
ự
ự
gi
gi
gi
gi
ố
ố
ố
ố
ng
ng
ng
ng
nhau
nhau
nhau
nhau
c
c
c
c
ủ
ủ
ủ
ủ
a
a
a
a
c
c
c
c
á
á
á
á
c
c
c
c
l
l
l
l
ớ
ớ
ớ
ớ
p
p
p
p
th
th
th
th
ể
ể
ể
ể
hi
hi
hi
hi
ệ
ệ
ệ
ệ
n
n
n
n
Xétcâulệnhgángiữahaiđốitợng.Nhchúngtađãbiết,chỉcóthểthựchiện
đợcphépgánkhihaiđốitợngcócùngkiểu(vớitrờnghợpthừakếvấnđềđặc
biệthơnmộtchútnhngthựcchấtchỉlàchuyểnkiểungầmđịnhđốivớibiểuthức
vếphảicủalệnhgán).Trớcđây,tabiếtrằnghaiđốitợngcócùngkiểunếuchúng
đợckhaibáovớicùngmộttênlớp.Trongtrờnghợpkhuônhìnhlớp,nênhiểusự
cùngkiểuởđâynhthếnào?Thựctế,hailớpthểhiệntơngứngvớicùngmộtkiểu
nếucácthamsốkiểutơngứngnhaumộtcáchchínhxácvàcácthamsốbiểuthức
cócùnggiátrị.Nhvậy(giảthiếtrằngchúngtađãđịnhnghĩakhuônhìnhlớp
table
trongmục2.6)vớicáckhaibáo:
table<int,12>t1;
table
<float,12>
t2;
takhôngcóquyềnviết:
t2=
t1;
//không
t
ơngthíchgiữahaithamsốđầu
Cũngvậy,vớicáckhaibáo:
table<int,12>ta;
table<int,20>tb;
cũngkhôngđợcquyềnviết
ta
=
tb;
//giátr
ị
thựccủahaithamsốsaukhácnhau.
Nhữngquitắcchặtchẽtrênnhằmlàmchophépgánngầmđịnhđợcthựchiện
chínhxác.Trờnghợpcócácđịnhnghĩachồngtoántửgán,cóthểkhôngnhấtthiết
phảituântheoquitắcđãnêutrên.Chẳnghạnhoàntoàncóthểthựchiệnđợcphép
gán
t2=
t1;
nếutacóđịnhnghĩahailớpthểhiện
table<int,
m>
và
table<float,n>
và
tronglớpthứhaicóđịnhnghĩachồngphépgánbằng.
C
C
C
C
á
á
á
á
c
c
c
c
l
l
l
l
ớ
ớ
ớ
ớ
p
p
p
p
th
th
th
th
ể
ể
ể
ể
hi
hi
hi
hi
ệ
ệ
ệ
ệ
n
n
n
n
v
v
v
v
à
à
à
à
c
c
c
c
á
á
á
á
c
c
c
c
khai
khai
khai
khai
b
b
b
b
á
á
á
á
o
o
o
o
b
b
b
b
ạ
ạ
ạ
ạ
n
n
n
n
b
b
b
b
è
è
è
è
Cáckhuônhìnhlớpcũngchophépkhaibáobạnbè.Bêntrongmộtkhuônhình
lớp,tacóthểthựchiệnbakiểukhaibáobạnbènhsau.