Bài giảng Lập trình hướng đối tượng - Nguyễn Thị Điệu - Chương 9: Hàm trong C++

9.1. Khai báo hàm

9.2. Định nghĩa hàm

9.3. Sử dụng hàm

9.4. Con trỏ trỏ tới hàm

pdf34 trang | Chuyên mục: Lập Trình Hướng Đối Tượng | Chia sẻ: dkS00TYs | Lượt xem: 2239 | Lượt tải: 1download
Tóm tắt nội dung Bài giảng Lập trình hướng đối tượng - Nguyễn Thị Điệu - Chương 9: Hàm trong C++, để xem tài liệu hoàn chỉnh bạn click vào nút "TẢI VỀ" ở trên
khai báo hàm thường để trong các file header có đuôi .h, còn các định 
nghĩa hàm để trong các file thư viện có đuôi obj hoặc lib. 
 Nếu hàm được định nghĩa ở đâu đó trước khi gọi hàm thì có thể không 
cần khai báo hàm. Tuy nhiên vẫn nên có khai báo hàm nhất là trong 
các chương trình có nhiều hàm lớn hay các chương trình nằm trên 
nhiều file. 
9.1.3. Các tham sӕ trong khai báo hàm 
7 
 Nếu hàm không có tham số thì trong dấu ngoặc đơn 
của khai báo hàm để trống. 
 Ví dụ: int xoa(); 
 Tên của các tham số trong khai báo hàm có thể không 
cần xác định. 
 Ví dụ: float inchtomet(float, float); 
9.2. Định nghĩa hàm 
8 
9.2.1. Cú pháp định nghĩa hàm 
9.2.2. Lệnh return 
9.2.3. Hàm không trả về giá trị 
9.2.1. Cú pháp định nghĩa hàm 
9 
Kiểu_trả_về Tên_hàm(Kiểu_1 Tên_tham_số_1, Kiểu_2 Tên_tham_số_2,…) 
{ 
//Các lệnh của hàm để ở đây 
} 
Không có dấu 
 chấm phẩy Thân hàm 
int cong(int a, int b) 
 { 
 int z; 
 z = a + b; 
 return z; 
 } 
Ví dụ: 
9.2.1. Cú pháp định nghĩa hàm (tiếp) 
10 
 Dòng đầu tiên trong định nghĩa hàm giống trong khai 
báo hàm, chỉ khác là không có dấu chấm phẩy (;) và các 
tham số bắt buộc phải có tên. 
 Khi đã có khai báo hàm thì định nghĩa hàm thường để 
sau hàm main hoặc để trong một tệp obj (lib). Để quen 
dần với việc viết các chương trình lớn, khi thực hành 
chúng ta viết các khai báo hàm trong tệp .h, còn các định 
nghĩa hàm để trong tệp .obj (lib). 
9.2.2. Lệnh return 
11 
 Lệnh return được sử dụng trong một hàm. Lệnh return 
thực hiện hai chức nĕng:  Làm cho một hàm trở về chương trình gọi nó.  Được dùng để trả về một giá trị.  Cú pháp dùng lệnh return như sau: 
 return Giá_trị_trả_về; 
 hoặc return;  Lệnh return có thể dùng ở bất kỳ vị trí nào trong hàm 
nhưng thường ở cuối hàm.  Với các hàm có trả về giá trị thì lệnh return bắt buộc 
phải có. 
9.2.3. Hàm không trả về giá trị 
12 
 Với các hàm không trả về giá trị thì khi khai báo và định 
nghĩa hàm ta phải khai báo kiểu trả về là void. 
 Ví dụ: void chao(); 
 Nếu sử dụng lệnh return trong hàm không trả về giá trị 
thì chỉ dùng được dạng: return; 
9.3. Sử dụng hàm 
13 
9.3.1. Lời gọi hàm 
9.3.2. Truyền đối số theo giá trị 
9.3.3. Truyền đối số theo tham chiếu 
9.3.4. Truyền con trỏ tới hàm 
9.3.5. Truyền mảng tới hàm 
9.3.6. Hàm có đối số mặc định 
9.3.1. Lời gọi hàm 
14 
 Một hàm, sau khi được định nghĩa và khai báo, có thể được 
thực hiện bằng một lệnh gọi hàm (lời gọi hàm) ở đâu đó trong 
chương trình. Có thể gọi từ hàm main, có thể gọi từ một hàm 
khác hoặc có thể gọi từ một hàm thành viên của lớp. 
 Cú pháp gọi hàm như sau: 
 Tên_hàm(Danh sách các đối số, nếu có); 
 Nếu hàm được khai báo và định nghĩa là có các tham số thì khi 
gọi hàm ta phải truyền giá trị cho hàm qua các tham số. Các giá 
trị truyền cho hàm gọi là các đối số. Các đối số có thể là hằng, 
biến, mảng, con trỏ,… 
9.3.1. Lời gọi hàm (tiếp) 
15 
 Ví dụ: giả sử ta khai báo một hàm cộng hai giá trị float: 
 float cong(float, float); 
 Ta gọi hàm này như sau: cong(7,8); 
 Lời gọi một hàm có trả về giá trị có thể sử dụng trong 
các biểu thức, còn lời gọi một hàm không trả về giá trị 
không dùng được trong biểu thức. Khi dùng trong biểu 
thức thì không có dấu chấm phẩy sau lời gọi hàm. 
Ví dụ: a = cong(7,8) +2; cout<<a; 
9.3.1. Lời gọi hàm (tiếp) 
16 
 sdfghjkl 
func1(); 
 sdfghjkl 
 sdfghjkl 
func1(); 
 sdfghjkl 
 sdfghjkl 
func1(); 
 sdfghjkl 
Hoạt động của lời gọi hàm: 
 Chương trình 
 gọi hàm 
 sdfghjkl 
Lời gọi hàm 
void func1() 
 { 
 sdfghjkl 
 sdfghjkl 
 sdfghjkl 
 } 
 Cùng một mã được dùng 
cho tất cả các lời gọi hàm 
Ví dụ về hàm 
17 
 Viết chương trình tính số các chỉnh hợp chập k từ n phần 
tử. Chương trình phải sử dụng hàm để tính giai thừa. 
A = k n n! (n - k)! 
9.3.2. Truyền đӕi sӕ theo giá trị 
18 
 Khi khai báo và định nghĩa hàm ta có hai cách khai báo 
các tham số của hàm: 
 Khai báo để khi gọi hàm truyền đối số cho hàm theo giá trị. 
 Khai báo để khi gọi hàm truyền đối số cho hàm theo tham chiếu. 
 Khai báo để truyền đối số theo giá trị giống như khai báo 
biến thông thường: Kiểu Tên_tham_sӕ 
Ví dụ: void hoandoi(int a, int b); 
9.3.2. Truyền đӕi sӕ theo giá trị (tiếp) 
19 
 Khi truyền đối số cho hàm theo giá trị thì hàm sẽ 
tạo ra các biến mới (tên các biến này là tên của các tham 
số), copy giá trị của các đối số vào các biến mới và thao 
tác trên các biến mới này. Bởi vậy sau khi gọi hàm các 
đối số không bị thay đổi giá trị mặc dù bên trong hàm 
giá trị của đối số bị thay đổi. 
 Ví dụ: Để đổi chỗ giá trị trong hai biến ta viết hàm như 
sau: (Xem trang sau) 
9.3.2. Truyền đӕi sӕ theo giá trị (tiếp) 
20 
#include 
#include 
void DoiCho(int,int); //hàm đổi giá trị của 2 số nguyên 
void main() 
 { 
 int x=12,y=15; 
 clrscr(); 
 cout<<"Truoc khi doi cho: x= "<<x<<", y= "<<y; 
 DoiCho(x,y); 
 cout<<"\nSau khi doi cho: x= "<<x<<", y= "<<y; 
 getch(); 
 } 
void DoiCho(int a,int b) //Khai bao de truyen doi so theo gia tri 
 { 
 int tmp=a; 
 a=b; 
 b=tmp; 
 } 
9.3.3. Truyền đӕi sӕ theo tham chiếu 
21 
 Tham chiếu (reference) là một tên khác của cùng một 
biến.  Khi truyền đối số theo tham chiếu hàm sẽ không tạo 
ra biến mới mà thao tác trực tiếp trên biến đối số. Kết 
quả là những tác động của hàm sẽ làm thay đổi giá trị 
của đối số.  Để truyền đối số cho hàm theo tham chiếu thì khi khai 
báo hàm ta phải thêm dấu & vào bên phải tên kiểu của 
tham số.  Ví dụ: void DoiCho(int& a, int& b);  Các đối số truyền tới hàm theo tham chiếu chỉ có thể 
là biến không được là giá trị. 
9.3.3. Truyền đӕi sӕ theo tham chiếu (tiếp) 
22 
 Ví dụ: Đổi chỗ giá trị của 2 biến 
..... 
void DoiCho(int&,int&); 
..... 
void DoiCho(int& a,int& b) 
 { 
 int tmp=a; 
 a=b; 
 b=tmp; 
 } 
9.3.3. Truyền đӕi sӕ theo tham chiếu (tiếp) 
23 
 Khi đối số là đối tượng thì truyền theo tham chiếu là tốt 
nhất. Bởi vì truyền theo tham chiếu hàm sẽ không phải 
copy đối tượng mà thao tác trực tiếp trên đối tượng đối 
số. Với các đối tượng lớn thì đây là cách tiết kiệm bộ 
nhớ và thời gian thực hiện chương trình. 
9.3.4. Truyền con trӓ tӟi hàm 
24 
 Để truyền con trỏ tới hàm ta phải thực hiện hai bước: 
 Khai báo các tham số (khi khai báo và định nghĩa) là con trỏ. 
 Khi gọi hàm thì đối số truyền cho hàm là địa chỉ. 
 Ví dụ: 
void DoiCho(int* a, int* b); 
int x = 12,y = 15; 
DoiCho(&x,&y); 
9.3.4. Truyền con trӓ tӟi hàm (tiếp) 
25 
 Khi truyền con trỏ tới hàm thì biến do con trỏ trỏ tới 
có thể bị thay đổi bởi hàm. 
 Ví dụ: Đổi chỗ giá trị của hai biến 
void DoiCho(int* a,int* b); 
.... 
DoiCho(&x,&y); 
.... 
void DoiCho(int* a,int* b) 
{ 
 int tmp = *a; 
 *a = *b; 
 *b = tmp; 
} 
9.3.5. Truyền mảng tӟi hàm 
26 
 Khi tên mảng được sử dụng mà không có chỉ số kèm theo thì 
nó là địa chỉ bắt đầu của mảng. Do đó, nếu dùng mảng làm 
đối số truyền tới một hàm thì chỉ có địa chỉ của mảng được 
truyền tới hàm chứ không phải toàn bộ mảng. Điều này có 
nghĩa rằng khi khai báo tham số của hàm thì tham số phải có 
kiểu con trỏ. 
 Bởi vì địa chỉ của mảng được truyền tới hàm nên mọi thay 
đổi của hàm lên mảng sẽ giữ nguyên khi hàm kết thúc. 
9.3.5. Truyền mảng tӟi hàm (tiếp) 
27 
 Ví dụ: Viết một hàm đưa ra các phần tử của mảng 
void print(int* m); 
..... 
int x[7]={2,5,8,1,6,7,10}; 
..... 
print(x); 
..... 
void print(int* m) 
 { 
 for(int i=0;i<7;i++) cout<<m[i]<<" "; 
 } 
9.3.6. Hàm có đӕi sӕ mặc định 
28 
 Một đặc điểm mới được đưa vào C++ liên quan tới hàm 
là đối số mặc định. Đó là khi khai báo và định nghĩa hàm 
ta có thể gán giá trị mặc định cho một tham số. Giá trị 
mặc định này sẽ được sử dụng khi không có đối số tương 
ứng với tham số đó trong lời gọi hàm. 
 Như vậy, nếu sử dụng đối số mặc định thì khi gọi hàm có 
thể truyền đủ hoặc không đủ số lượng đối số. 
9.3.6. Hàm có đӕi sӕ mặc định (tiếp) 
29 
 Ví dụ: Khai báo và sử dụng hàm có đối số mặc định. 
 void f(int a=0, int b=0); 
 Với khai báo này ta có ba cách gọi hàm khác nhau: 
 Cách 1: có thể gọi hàm với cả hai đối số: 
f(5,6); 
 Cách 2: có thể gọi hàm với một đối số đầu tiên, khi đó đối số thứ hai sẽ có giá trị mặc định bằng 0: 
f(5); 
 Cách 3: có thể gọi hàm mà không có đối số nào: 
f(); 
9.3.6. Hàm có đӕi sӕ mặc định (tiếp) 
30 
 Một số chú ý khi tạo hàm có đối số mặc định: 
 Các giá trị mặc định chỉ được xác định duy nhất một lần 
ngay khi khai báo hàm (prototype), không xác định lại trong 
định nghĩa hàm. Ví dụ: 
 void f(int a=0, int b=0); //Khai báo hàm 
 void f(int a=0, int b=0) //Định nghĩa hàmSai 
 { } 
 Các tham số có giá trị mặc định phải nằm bên phải các tham 
số không có giá trị mặc định. 
 Ví dụ: void f(int a=1, int b); //Sai 
9.4. Con trӓ trӓ tӟi hàm 
31 
 Một đặc điểm rất mạnh của C++ là con trỏ hàm. Mặc 
dù hàm không phải là biến nhưng nó vẫn có địa chỉ trong 
bộ nhớ. Địa chỉ này có thể chứa trong một con trỏ. Vì địa 
chỉ của hàm chứa trong con trỏ nên ta có thể sử dụng con 
trỏ thay cho tên hàm. 
 Để có địa chỉ của hàm ta dùng tên hàm không có đối số 
(giống như tên biến mảng là địa chỉ của mảng). 
9.4. Con trӓ trӓ tӟi hàm (tiếp) 
32 
 Để có con trỏ có thể chứa địa chỉ của hàm ta khai báo con trỏ 
trỏ tới kiểu giống kiểu trả về của hàm, theo sau là các tham 
số của hàm đặt trong ngoặc đơn. 
 Ví dụ: giả sử hàm Tong có hai tham số kiểu int, kiểu trả về 
cũng là int. Khi đó ta khai báo con trỏ trỏ tới hàm này như 
sau: 
int Tong(int a, int b); //Khai báo hàm 
int (*p) (int a, int b); //Khai báo con trỏ hàm 
p = Tong; //Gán địa chỉ của hàm Tong cho p 
(*p)(10,15); //Gọi hàm Tong qua con trỏ 
9.4. Con trӓ trӓ tӟi hàm (tiếp) 
33 
 Ví dụ: Viết chương trình tính tổng, hiệu, tích và thương 
của hai số nguyên nhập vào từ bàn phím. Chương trình 
yêu cầu người sử dụng lựa chọn một trong các cách 
tính. 
BÀI TẬP VÀ THỰC HÀNH 
34 
Q & A? 

File đính kèm:

  • pdfBài giảng Lập trình hướng đối tượng - Nguyễn Thị Điệu - Chương 9 Hàm trong C++.pdf