Tải bản đầy đủ (.pdf) (27 trang)

Hàm trong C++

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (234.17 KB, 27 trang )


26



CHƯƠNG 2
HÀM TRONG C
++

Chương này trình bầy những khả năng mới của C
++
trong việc xây dựng và sử
dụng các hàm. ðó là:
- Biến tham chiếu và việc truyền dữ liệu cho hàm bằng tham chiếu
- ðối có giá trị mặc ñịnh
- Hàm trực tuyến
- ðịnh nghĩa chồng các hàm
- ðịnh nghĩa chồng các toán tử
§
1. BIẾN THAM CHIẾU
1.1. Hai loại biến dùng trong C
Trước khi nói ñến biến tham chiếu, chúng ta nhắc lại hai loại biến ñã gặp trong C
là:
+ Biến giá trị dùng ñể chứa dữ liệu (nguyên, thực, ký tự, ... )
+ Biến con trỏ dùng ñể chứa ñịa chỉ
Các biến này ñều ñược cung cấp bộ nhớ và có ñịa chỉ. Ví dụ câu lệnh khai báo:
double x , *px;
sẽ tạo ra biến giá trị kiểu double là x và biến con trỏ kiểu double là px. Biến x có
vùng nhớ 8 byte, biến px có vùng nhớ 4 byte (nếu dùng mô hình bộ nhớ Large). Biến
x dùng ñể chứa giá trị kiểu double, ví dụ lệnh gán:
x = 3.14;


sẽ chứa giá trị 3.14 vào biến x. Biến px dùng ñể chứa ñịa chỉ của một biến thực, ví dụ
câu lệnh:
px = &x ;
sẽ lưu trữ ñịa chỉ của biến x vào con trỏ px.
1.2. Biến tham chiếu
Trong C
++
cho phép sử dụng loại biến thứ ba là biến tham chiếu (reference
variable). So với hai loại biến nói trên thì biến tham chiếu có những ñặc ñiểm sau:
+ Biến tham chiếu không ñược cấp phát bộ nhớ, không có ñịa chỉ riêng.
+ Nó dùng làm bí danh (alias) cho một biến (kiểu giá trị) nào ñó và nó sử dụng
vùng nhớ của biến này. Ví dụ câu lệnh:
float u, v, &r = u ;

27

tạo ra các biến thực u, v và biến tham chiếu thực r. Biến r không ñược cấp phát bộ
nhớ riêng, nó chỉ là một tên khác (bí danh) của u và nó dùng chung vùng nhớ của
biến u.
Khi r là bí danh của u thì ta nói r tham chiếu ñến biến u. Như vậy hai thuật ngữ
trên ñược hiểu như nhau.
Khi r là bí danh của u thì r dùng chung vùng nhớ của u, do ñó :
+ Trong mọi câu lệnh, viết u hay viết r ñều có ý nghĩa như nhau, vì ñều truy nhập
ñến cùng một vùng nhớ.
+ Có thể dùng biến tham chiếu ñể truy nhập ñến một biến kiểu giá trị.
Ví dụ:
int u, v, &r = u;
r = 10 ; // u=10
cout << u ; // in ra số 10
r++ ; // u = 11

++ u ; // r = 12
cout << r ; // in ra số 12
v = r ; // v=12
& r ; // Cho ñịa chỉ của u
Vài chú ý về biến tham chiếu:
+ Biến tham chiếu thường ñược sử dụng làm ñối của hàm ñể cho phép hàm truy
nhập ñến các tham số biến trong lời gọi hàm.
+ Vì biến tham chiếu không có ñịa chỉ riêng, nó chỉ là bí danh của một biến kiểu
giá trị nên trong khai báo phải chỉ rõ nó tham chiếu ñến biến nào. Ví dụ nếu khai báo:
double &x ;
thì Trình biên dịch sẽ báo lỗi:
Reference variable ‘x’ must be initialized
+ Biến tham chiếu có thể tham chiếu ñến một phần tử mảng, ví dụ:
int a[10] , &r = a[5];
r = 25 ; // khi ñó a[5] = 25
+ Không cho phép khai báo mảng tham chiếu
+ Biến tham chiếu có thể tham chiếu ñến một hằng. Khi ñó nó sẽ sử dụng
vùng nhớ của hằng và nó có thể làm thay ñổi giá trị chứa trong vùng nhớ này.
Ví dụ nếu khai báo:
int &s = 23 ;
thì Trình biên dịch ñưa ra cảnh báo:
Temporary used to initialize 's'

28

Tuy nhiên chương trình vẫn làm việc. Các câu lệnh dưới ñây vẫn thực hiện và cho
kết quả như sau:
s++;
cout << "\ns= " << s; // In ra s=24
§

2. TRUYỀN GIÁ TRỊ CHO HÀM THEO THAM CHIẾU
2.1. Hàm trong C
Trong C chỉ có một cách truyền dữ liệu cho hàm theo giá trị, ñược thực hiện như
sau:
+ Cấp phát vùng nhớ cho các ñối.
+ Gán giá trị các tham số trong lời gọi hàm cho các ñối sau ñó hàm làm
việc trên vùng nhớ của các ñối chứ không liên quan gì ñến các tham số.
Như vây chương trình sẽ tạo ra các bản sao (các ñối) của các tham số và hàm sẽ
thao tác trên các bản sao này, chứ không làm việc trực tiếp với các tham số. Phương
pháp này có những nhược ñiểm chính: Tốn kém về thời gian và bộ nhớ vì phải tạo ra
các bản sao, và không thao tác trực tiếp trên các tham số, vì vậy không làm thay ñổi
ñược giá trị các tham số.
2.2. Truyền giá trị cho hàm theo tham chiếu
C
++
cung cấp thêm cách truyền dữ liệu cho hàm theo tham chiếu bằng cách dùng
ñối là biến tham chiếu hoặc ñối là hằng tham chiếu. Cách này có ưu ñiểm: Không cần
tạo ra các bản sao của các tham số, do ñó tiết kiệm bộ nhớ và thời gian chạy máy, và
hàm sẽ thao tác trực tiếp trên vùng nhớ của các tham số, do ñó có thể dễ dàng thay
ñổi giá trị các tham số khi cần.
2.3. Mối quan hệ giữa ñối và tham số trong lời gọi hàm
Nếu ñối là biến hoặc hằng tham chiếu kiểu gì thì tham số (trong lời gọi hàm) phải
là biến hoặc phần tử mảng kiểu ñó. Ví dụ:
+ ðối là biến (hoặc hằng) tham chiếu kiểu double, thì tham số là biến hoặc phần tử
mảng kiểu double
+ ðối là biến (hoặc hằng) tham chiếu kiểu cấu trúc, thì tham số là biến hoặc phần
tử mảng kiểu cấu trúc
2.4. Các chương trình minh hoạ
/* Chương trình 1:
Gồm các hàm:

+ Nhập dẫy số kiểu double
+ Hoán vị 2 biến kiểu double
+ Sắp xếp dẫy số kiểu double theo thứ tự tăng dần
Chương trình sẽ nhập một dẫy số và in dẫy sau khi sắp xếp
*/

29

#include <iostream.h>
#include <conio.h>
#include <stdio.h>
void nhapds(double *a, int n)
{
for (int i=1; i<= n ; ++i)
{
cout << "\nPhan tu thu " << i << " : " ;
cin >> a[i] ;
}
}
// Hàm hoán vị, dùng ñối tham chiếu
void hv(double &x, double &y)
{
double tg=x;
x=y;
y= tg;
}
void sapxep(double * a, int n)
{
for (int i=1; i <= n-1 ;++i)
for (int j=i+1 ; j<=n ;++j)

if (a[i] > a[j])
hv(a[i],a[j]);
}
void main()
{
double x[100];
int i, n;
cout <<"\n N= ";
cin >> n;
nhapds(x,n);
sapxep(x,n);
for (i=1;i<=n;++i)
printf("\n%0.1lf",x[i]);
getch();

30

}
/* Chương trình 2:
Gồm các hàm:
+ Nhập dẫy cấu trúc (mỗi cấu trúc chứa dữ liệu một thí sinh)
+ Hoán vị 2 biến cấu trúc
+ Sắp xếp dẫy thí sinh theo thứ tự giảm của tổng ñiểm
+ In một cấu trúc (in họ tên và tổng ñiểm)
Chương trình sẽ nhập dữ liệu một danh sách thí sinh, nhập ñiểm chuẩn và in
danh sách thí sinh trúng tuyển
*/
#include <iostream.h>
#include <iomanip.h>
#include <conio.h>

struct TS
{
char ht[20];
float t,l,h,td;
} ;
void ints(const TS &ts)
{
cout << setiosflags(ios::showpoint) << setprecision(1) ;
cout << "\nHo ten: " << setw(20) << ts.ht << setw(6) << ts.td ;
}
void nhapsl(TS *ts, int n)
{
for (int i=1;i<=n;++i)
{
cout << "\n Thi sinh " << i ;
cout << "\n Ho ten: " ;
cin.ignore(1);
cin.get(ts[i].ht,25) ;
cout << "Cac diem toan, ly, hoa: ";
cin >> ts[i].t >> ts[i].l >> ts[i].h ;
ts[i].td = ts[i].t + ts[i].l + ts[i].h ;
}

31

}
// Hoỏn v hai bin cu trỳc, dựng ủi tham chiu
void hvts(TS &ts1, TS &ts2)
{
TS tg=ts1;

ts1=ts2;
ts2=tg;
}
void sapxep(TS *ts,int n)
{
for (int i=1;i<=n-1;++i)
for (int j=i+1;j<=n;++j)
if (ts[i].td < ts[j].td)
hvts(ts[i],ts[j]);
}
void main()
{
TS ts[100];
int n,i;
cout << " So thi sinh: " ; cin >> n ;
nhapsl(ts,n);
sapxep(ts,n) ;
float dc;
cout << " Diem chuan: " ; cin >> dc;
cout << "\n\nDanh sach trung tuyen\n" ;
for (i=1;i<=n;++i)
if (ts[i].td >= dc) ints(ts[i]);
else break;
getch();
}
Đ
3. Hàm trả về các tham chiếu
Hàm có thể có kiểu tham chiếu và trả về giá trị tham chiếu. Khi đó có thể dùng
hàm để truy nhập đến một biến hoặc một phần tử mảng nào đó. Dới đây là một số ví
dụ.

Ví dụ 1 trình bầy một hàm trả về một tham chiếu đến một biến toàn bộ. Do đó có
thể dùng hàm để truy nhập đến biến này.

32

#include <iostream.h>
int z ; // Biến toàn bộ
int &f() // Hàm trả về một bí danh của biến toàn bộ z
{
return z;
}
void main(void)
{
f()=50;
cout <<"\nz= " << z; // z = 50
}
Ví dụ 2 trình bầy một hàm trả về bí danh của một biến cấu trúc toàn bộ. Khác với
ví dụ trên, ở đây không dùng hàm một cách trực tiếp mà gán hàm cho một biến tham
chiếu, sau đó dùng biến tham chiếu này để truy nhập đến biến cấu trúc toàn bộ.
#include <iostream.h>
#include <conio.h>
struct TS
{
char ht[25];
float t,l,h,td;
};
TS ts;
TS &f()
{
return ts;

}
void main()
{
TS &h=f(); // h tham chiếu đến biến ts
cout << "\n Ho ten: " ;
cin.get(h.ht,25) ;
cout << "Cac diem toan, ly, hoa: ";
cin >> h.t >> h.l >> h.h ;
h.td = h.t + h.l + h.h ;
cout << "\n Ho ten: " << ts.ht;
cout << "\n Tong diem: " << ts.td;
getch();

33

§
3. HÀM TRẢ VỀ CÁC THAM CHIẾU
Hàm có thể có kiểu tham chiếu và trả về giá trị tham chiếu. Khi ñó có thể dùng
hàm ñể truy nhập ñến một biến hoặc một phần tử mảng nào ñó. Dưới ñây là một số ví
dụ.
Ví dụ 1 trình bầy một hàm trả về một tham chiếu ñến một biến toàn bộ. Do ñó có
thể dùng hàm ñể truy nhập ñến biến này.
#include <iostream.h>
int z ; // Biến toàn bộ
int &f() // Hàm trả về một bí danh của biến toàn bộ z
{
return z;
}
void main(void)
{

f()=50;
cout <<"\nz= " << z; // z = 50
}
Ví dụ 2 trình bầy một hàm trả về bí danh của một biến cấu trúc toàn bộ. Khác với
ví dụ trên, ở ñây không dùng hàm một cách trực tiếp mà gán hàm cho một biến tham
chiếu, sau ñó dùng biến tham chiếu này ñể truy nhập ñến biến cấu trúc toàn bộ.
#include <iostream.h>
#include <conio.h>
struct TS
{
char ht[25];
float t,l,h,td;
};
TS ts;
TS &f()
{
return ts;
}
void main()
{
TS &h=f(); // h tham chiếu ñến biến ts
cout << "\n Ho ten: " ;

34

cin.get(h.ht,25) ;
cout << "Cac diem toan, ly, hoa: ";
cin >> h.t >> h.l >> h.h ;
h.td = h.t + h.l + h.h ;
cout << "\n Ho ten: " << ts.ht;

cout << "\n Tong diem: " << ts.td;
getch();
}
Ví dụ 3 trình bầy một hàm trả về bí danh của một phần tử mảng cấu toàn bộ.
Hàm sẽ kiểm tra xem chỉ số mảng có vượt ra ngoài miền quy ñịnh hay không. Sau ñó
dùng hàm này ñể truy nhập ñến các phần tử mảng cấu trúc.
#include <iostream.h>
#include <conio.h>
#include <stdlib.h>
struct TS
{
char ht[25];
float t,l,h,td;
};
TS *ts;
void cap_phat_bo_nho_nhapsl(int n)
{
ts = new TS[n+1] ;
if (ts==NULL)
{
cout << "Loi cap phat bo nho " ;
exit(1);
}
for (int i=1;i<=n;++i)
{
TS &h=ts[i];
cout << "\nThi sinh thu " << i ;
cout << "\n Ho ten: " ;
cin.ignore(1);
cin.get(h.ht,25) ;

cout << "Cac diem toan, ly, hoa: ";

35

cin >> h.t >> h.l >> h.h ;
h.td = h.t + h.l + h.h ;
}
}
TS &f(int i, int n) // Cho bi danh ts[i]
{
if (i<1 || i>n)
{
cout << "Chi so mang khong hop le " ;
exit(1);
}
return ts[i];
}
void main()
{
int n, i ;
cout << "\n So thi sinh : " ;
cin >> n;
cap_phat_bo_nho_nhapsl(n);
while (1)
{
cout << "\nCan xem thi sinh thu may: " ;
cin >> i;
TS &h=f(i,n);
cout << "\n Ho ten: " << h.ht;
cout << "\n Tong diem: " << h.td;

}
}
§
4. ðỐI CÓ GIÁ TRỊ MẶC ðỊNH
4.1. Thế nào là ñối có giá trị mặc ñịnh
Thông thường số tham số trong lời gọi hàm phải bằng số ñối của hàm. Mỗi
ñối sẽ ñược khởi gán giá trị theo tham số tương ứng của nó. Trong C
++
cho
phép tạo giá trị mặc ñịnh cho các ñối. Các ñối này có thể có hoặc không có
tham số tương ứng trong lời gọi hàm. Khi không có tham số tương ứng, ñối
ñược khởi gán bởi giá trị mặc ñịnh.
Ví dụ hàm delay với ñối số mặc ñịnh ñược viết theo một trong 2 cách sau:
Cách 1 (Không khai báo nguyên mẫu):
void delay(int n=1000)

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×