Chương 4. Hàm
Chương này mô t nhng hàm do người dùng định nghĩa như là mt trong
nhng khi chương trình C++. Hàm cung cp mt phương thc để đóng gói
quá trình tính toán mt cách d dàng để được s dng khi cn. Định nghĩa
hàm gm hai phn: giao din và thân.
Phn giao din hàm (cũng được gi là khai báo hàm) đặc t hàm có th
được s dng như thế nào. Nó gm ba phn:
Tên hàm. Đây ch là mt định danh duy nht.
Các tham s ca hàm. Đây là mt tp ca không hay nhiu định danh
đã định kiu được s dng để truyn các giá tr ti và t hàm.
Kiu tr v ca hàm. Kiu tr v ca hàm đặc t cho kiu ca giá tr
hàm tr v. Hàm không tr v bt k kiu nào thì nên tr v kiu void.
Phn thân hàm cha đựng các bước tính toán (các lnh).
S dng mt hàm liên quan đến vic gi nó. Mt li gi hàm gm có tên
hàm, theo sau là cp du ngoc đơn ‘()’, bên trong cp du ngoc là không,
mt hay nhiu đối s được tách bit nhau bng du phy. S các đối s phi
khp vi s các tham s ca hàm. Mi đối s mt biu thc mà kiu ca nó
phi khp vi kiu ca tham s tương ng trong khai báo hàm.
Khi li gi hàm được thc thi, các đối s đưc ước lượng trước tiên và
các giá tr kết qu ca chúng được gán ti các tham s tương ng. Sau đó
thân hàm được thc hin. Cui cùng giá tr tr v ca hàm được truyn ti
thành phn gi hàm.
mt li gi ti mt hàm mà kiu tr v không là void s mang li mt
giá tr tr v nên li gi là mt biu thc và có th được s dng trong các
biu thc khác. Ngược li mt li gi ti mt hàm mà kiu tr v ca nó là
void thì li gi là mt lnh.
Chương 4: Hàm
45
4.1. Hàm đơn gin
Danh sách 4.1 trình bày định nghĩa ca mt hàm đơn gin để tính lũy tha
ca mt s nguyên.
Danh sách 4.1
1
2
3
4
5
6
7
int Power (int base, unsigned int exponent)
{
int result = 1;
for (int i = 0; i < exponent; ++i)
result *= base;
return result;
}
Chú gii
1 Dòng này định nghĩa giao din hàm. Nó bt đầu vi kiu tr v ca hàm
(là int trong trường hp này). Kế tiếp là tên hàm, theo sau là danh sách
các tham s. Power có hai tham s (baseexponent) thuc kiu int
unsigned int tương ng. Chú ý là cú pháp cho các tham s là tương t như
cú pháp cho định nghĩa biến: định danh kiu được theo sau bi tên tham
s. Tuy nhiên, không th theo sau định danh kiu vi nhiu tham s phân
cách bi du phy:
int Power (int base, exponent) // Sai!
2 Du ngoc này đánh du đim bt đầu ca thân hàm.
3 Dòng này là định nghĩa mt biến cc b.
4-5 Vòng lp for này tăng cơ s base lên lũy tha ca exponent và lưu tr kết
qu vào trong result.
6 Hàng này tr result v như là kết qu ca hàm.
7 Du ngoc này đánh du đim kết thúc ca thân hàm.
Danh sách 4.2 minh ha hàm đưc gi như thế nào. Tác động ca li gi
hàm này là đầu tiên các giá tr 2 và 8 tương ng được gán cho các tham s
base va exponent, và sau đó thân hàm được ước lượng.
Danh sách 4.2
1
2
3
4
5
#include <iostream.h>
main (void)
{
cout << "2 ^ 8 = " << Power(2,8) << '\n';
}
Khi chy chương trình này xut ra kết qu sau:
2 ^ 8 = 256
Chương 4: Hàm
46
Nói chung, mt hàm phi được khai báo trước khi s dng nó. Khai báo
hàm (function declaration) đơn gin gm có mu ban đầu ca hàm gi là
nguyên mu hàm (function prototype) ch định tên hàm, các kiu tham s, và
kiu tr v. Hàng 2 trong Danh sách 4.3 trình bày hàm Power có th được khai
báo như thế nào cho chương trình trên. Nhưng mt hàm cũng có th được
khai báo mà không cn tên các tham s ca nó,
int Power (int, unsigned int);
tuy nhiên chúng ta không nên làm điu đó tr phi vai trò ca các tham s là rõ
ràng.
Danh sách 4.3
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream.h>
int Power (int base, unsigned int exponent); // khai bao ham
main (void)
{
cout << "2 ^ 8 = " << Power(2,8) << '\n';
}
int Power (int base, unsigned int exponent)
{
int result = 1;
for (int i = 0; i < exponent; ++i)
result *= base;
return result;
}
Bi vì mt định nghĩa hàm cha đựng mt nguyên mu (prototype) nên
nó cũng được xem như là mt khai báo. Vì thế nếu định nghĩa ca mt hàm
xut hin trước khi s dng nó thì không cn khai báo thêm vào. Tuy nhiên
vic s dng các nguyên mu hàm là khuyến khích cho mi trường hp. Tp
hp ca nhiu hàm vào mt tp tin header riêng bit cho phép nhng lp trình
viên khác truy xut nhanh chóng ti các hàm mà không cn phi đọc toàn b
các định nghĩa ca chúng.
4.2. Tham sđối s
C++ h tr hai kiu tham s: giá tr và tham chiếu. Tham s giá tr nhn mt
sao chép giá tr ca đối s được truyn ti nó. Kết qu là, nếu hàm có bt k
chuyn đổi nào ti tham s thì vn không tác động đến đối s. Ví d, trong
#include <iostream.h>
void Foo (int num)
{
num = 0;
Chương 4: Hàm
47
cout << "num = " << num << '\n';
}
int main (void)
{
int x = 10;
Foo(x);
cout << "x = " << x << '\n';
return 0;
}
thì tham s duy nht ca hàm Foo là mt tham s giá tr. Đến lúc mà hàm này
được thc thi thì num được s dng như là mt biến cc b bên trong hàm.
Khi hàm được gi và x được truyn ti nó, num nhn mt sao chép giá tr ca
x. Kết qu là mc dù num được đặt v 0 bi hàm nhưng vn không có gì tác
động lên x. Chương trình cho kết qu như sau:
num = 0;
x = 10;
Trái li, tham s tham chiếu nhn các đối s được truyn ti nó và làm
trc tiếp trên đối s đó. Bt k chuyn đổi nào được to ra bi hàm ti tham
s tham chiếu đều tác động trc tiếp lên đối s.
Bên trong ng cnh ca các li gi hàm, hai kiu truyn đối s tương ng
được gi là truyn-bng-giá tr truyn-bng-tham chiếu. Tht là hoàn
toàn hp l cho mt hàm truyn-bng-giá tr đối vi mt vài tham s
truyn-bng-tham chiếu cho mt vài tham s khác. Trong thc tế thì truyn-
bng-giá tr thường được s dng nhiu hơn.
4.3. Phm vi cc b và toàn cc
Mi th được định nghĩa mc phm vi chương trình (nghĩa là bên ngoài các
hàm và các lp) được hiu là có mt phm vi toàn cc (global scope). Các
hàm ví d mà chúng ta đã thy cho đến thi đim này đều có mt phm vi
toàn cc. Các biến cũng có th định nghĩa phm vi toàn cc:
int year = 1994; // biến toàn cc
int Max (int, int); // hàm toàn cc
int main (void) // hàm toàn cc
{
//...
}
Các biến toàn cc không được khi to, s được khi to t động là 0.
các đầu vào toàn cc là có th thy được mc chương trình nên
chúng cũng phi là duy nht mc chương trình. Điu này nghĩa là cùng các
biến hoc hàm toàn cc có th không được định nghĩa nhiu hơn mt ln
Chương 4: Hàm
48
mc toàn cc. (Tuy nhiên chúng ta s thy sau này mt tên hàm có th được
s dng li). Thông thường các biến hay hàm toàn cc có th được truy xut
t mi nơi trong chương trình.
Mi khi trong mt chương trình định nghĩa mt phm vi cc b. Tht
vy, thân ca mt hàm trình bày mt phm vi cc b. Các tham s ca mt
hàm có cùng phm vi như là thân hàm. Các biến được định nghĩa bên trong
mt phm vi cc b có th nhìn thy ti ch phm vi đó. Do đó mt biến ch
cn là duy nht trong phm vi ca chính nó. Các phm vi cc b cí th lng
nhau, trong trường hp này các phm vi bên trong chng lên các phm vi bên
ngoài. Ví d trong
int xyz; // xyz toàn cc
void Foo (int xyz) // xyz là cc b cho thân ca Foo
{
if (xyz > 0) {
double xyz; // xyz là cc b cho khi này
//...
}
}
có ba phm vi riêng bit, mi phm vi cha đựng mt xyz riêng.
Thông thường, thi gian sng ca mt biến b gii hn bi phm vi ca
nó. Vì thế, ví d các biến toàn cc tn ti sut thi gian thc hin chương
trình trong khi các biến cc b được to ra khi phm vi ca chúng bt đầu và
mt đi khi phm vi ca chúng kết thúc. Không gian b nh cho các biến toàn
cc được dành riêng trước khi s thc hin ca chương trình bt đầu nhưng
ngược li không gian b nh cho các biến cc b được cp phát thi đim
thc hin chương trình.
4.4. Toán t phm vi
Bi vì phm vi cc b ghi chng lên phm vi toàn cc nên mt biến cc b
cùng tên vi biến toàn cc làm cho biến toàn cc không th truy xut được ti
phm vi cc b. Ví d, trong
int error;
void Error (int error)
{
//...
}
biến toàn cc error là không th truy xut được bên trong hàm Error bi vì nó
được ghi chng bi tham s error cc b.
Vn đề này được gii quyết nh vào s dng toán t phm vi đơn hng
(::) , toán t này ly đầu vào toàn cc nhưđối s:
Chương 4: Hàm
49