Bài 13: Hàm Trong Lập Trình C++ - DNMTechs
Có thể bạn quan tâm
Trong lập trình C ++, một hàm là một nhóm các câu lệnh được đặt tên và có thể được gọi từ một số điểm của chương trình. Cú pháp phổ biến nhất để xác định một hàm là:
type name ( parameter1, parameter2, ...) { statements }Giải thích:
- type là kiểu giá trị trả về bởi hàm.
- name là số nhận dạng mà theo đó chức năng có thể được gọi.
- Các tham số (càng nhiều càng tốt): Mỗi tham số bao gồm một kiểu, theo sau là một định danh, với mỗi tham số được tách ra từ tiếp theo bằng dấu phẩy. Mỗi tham số trông rất giống với khai báo biến thường (ví dụ: int x), và trên thực tế hoạt động bên trong hàm như một biến thông thường là cục bộ của hàm. Mục đích của các tham số là để cho phép chuyển các đối số đến hàm từ vị trí mà nó được gọi từ.
- statements là phần nội dung của hàm. Nó là một khối các câu lệnh được bao quanh bởi các dấu ngoặc {} để xác định chức năng thực sự làm việc.
Ví dụ đơn giản về Hàm trong lập trình C++:
#include <iostream> using namespace std; int addition (int a, int b) { int r; r=a+b; return r; } int main () { int z; z = addition (5,3); cout << "Kết quả là " << z; } Kết quả là 8Chương trình này được chia thành hai chức năng: addition và main. Hãy nhớ rằng không có vấn đề về thứ tự mà chúng được định nghĩa, một chương trình C ++ luôn luôn bắt đầu bằng cách gọi hàm main. Trong thực tế, hàm main là chức năng duy nhất được gọi tự động, và mã trong bất kỳ hàm nào khác chỉ được thực hiện nếu hàm của nó được gọi từ main (trực tiếp hoặc gián tiếp).
Trong ví dụ trên, hàm main bắt đầu bằng cách khai báo biến z kiểu int, và ngay sau đó, nó thực hiện gọi hàm addition. Gọi đến hàm theo một cấu trúc rất giống với khai báo của biến z. Trong ví dụ trên, hàm được gọi có thể được so sánh với định nghĩa của biến z chỉ là một vài dòng trước đó:
int addition (int a, int b) int z = addition (5,3);Các tham số trong khai báo hàm có một sự tương ứng rõ ràng với các đối số được truyền vào khi hàm được gọi. Hai giá trị là 5 và 3 được truyền đến hàm; chúng tương ứng với các tham số a và b, được khai báo cho hàm addition.
Tại thời điểm mà hàm addition được gọi từ bên trong hàm main, việc thực thi hàm main bị dừng lại và sẽ chỉ tiếp tục khi hàm addition kết thúc. Tại thời điểm gọi hàm, giá trị của cả hai đối số (5 và 3) được sao chép vào các biến cục bộ int a và int b trong hàm addition.
Sau đó, bên trong hàm addition, một biến địa phương được khai báo (int r), và bằng biểu thức r = a + b, kết quả của phép tính được gán cho r; trong trường hợp này a là 5 và b là 3, có nghĩa là 8 được gán cho r.
Câu lệnh cuối cùng trong hàm:
return r;Kết thúc hàm addition, chương trình sẽ tiếp tục chạy ở hàm main, chính xác tại cùng một điểm mà tại đó nó bị ngắt bởi lệnh gọi hàm addition. Nhưng thêm vào đó, vì bổ sung có kiểu trả về, giá trị này là giá trị được chỉ định trong câu lệnh trả về kết thúc hàm addition: trong trường hợp cụ thể này, giá trị của biến cục bộ r được trả về có giá trị là 8.
Một hàm có thể được gọi nhiều lần trong một chương trình, và đối số của nó có thể được thay đổi không giới hạn:
#include <iostream> using namespace std; int subtraction (int a, int b) { int r; r=a-b; return r; } int main () { int x=5, y=3, z; z = subtraction (7,2); cout << "Giá trị đầu tiên: " << z << '\n'; cout << "Giá trị thứ 2: " << subtraction (7,2) << '\n'; cout << "Giá trị thứ 3: " << subtraction (x,y) << '\n'; z= 4 + subtraction (x,y); cout << "Giá trị thứ 4:" << z << '\n'; } Giá trị thứ nhất: 5 Giá trị thứ 2: 5 Giá trị thứ 3: 2 Giá trị thứ 4: 6Hàm không có giá trị trả về – Kiểu void
Cú pháp hiển thị ở dưới cho tất cả các hàm:
type tên_hàm(đối số 1, đối số 2 ...) {lệnh}Yêu cầu khai báo kiểu đối với mỗi hàm. Đây là kiểu giá trị trả về bởi hàm. Nhưng khi không muốn hàm trả về bất cứ một giá trị nào thì sao? Trong trường hợp này, loại được sử dụng là void, là một loại đặc biệt để thể hiện sự vắng mặt của giá trị. Ví dụ, một hàm chỉ đơn giản in ra một thông điệp có thể không cần trả lại bất kỳ giá trị nào:
#include <iostream> using namespace std; void printmessage () { cout << "I'm a function!"; } int main () { printmessage (); } I'm a function!void cũng có thể được sử dụng trong danh sách tham số của hàm để xác định rõ ràng rằng hàm không lấy các thông số thực tế khi được gọi. Ví dụ, hàm printmessage có thể đã được khai báo là:
void printmessage (void) { cout << "I'm a function!"; }Trong C + +, một danh sách các tham số rỗng có thể được sử dụng thay vì void có cùng ý nghĩa, nhưng việc sử dụng void trong danh sách các đối số đã được phổ biến bởi ngôn ngữ C, nơi đây là một yêu cầu.
Ngay cả khi hàm không có tham số, ít nhất một cặp ngoặc rỗng () sẽ luôn luôn được nối vào tên hàm (bắt buộc). Xem cách printmessage đã được gọi như thế nào trong ví dụ trước đó:
printmessage ();Giá trị trả về của hàm main
Bạn có thể nhận thấy rằng kiểu trả về mainlà int, nhưng hầu hết các ví dụ trong các chương này và trước đây đã không thực sự trả về bất kỳ giá trị nào đó từ hàm main.
Nếu việc thực thi hàm main kết thúc mà không gặp lệnh return, thì chương trình sẽ mặc định trả về giá trị là 0:
return 0;Khi hàm main trả về 0 (ngầm định hoặc rõ ràng), nó được xem như chương trình kết thúc thành công. Các giá trị khác có thể được trả lại bởi hàm main, và một số môi trường cho phép truy cập vào giá trị đó cho người gọi bằng một cách nào đó, mặc dù hành vi này không bắt buộc và không nhất thiết giữa các nền tảng. Các giá trị cho hàm mainđiều đó được đảm bảo sẽ được giải thích theo cùng một cách trên tất cả các nền tảng là:
Giá trị | Sự miêu tả |
---|---|
0 | Chương trình đã thành công |
EXIT_SUCCESS | Chương trình đã thành công (giống như ở trên). Giá trị này được định nghĩa trong tiêu đề <cstdlib>. |
EXIT_FAILURE | Chương trình thất bại. Giá trị này được định nghĩa trong tiêu đề <cstdlib>. |
Đối số được truyền bằng giá trị và bằng tham chiếu
Trong các hàm được thấy trước đó, các đối số luôn luôn được truyền bằng giá trị . Điều này có nghĩa là, khi gọi một hàm, những gì được truyền vào hàm là các giá trị của các đối số này vào thời điểm hàm được gọi, được sao chép vào các biến thể hiện bởi các tham số hàm. Ví dụ, lấy:
int x=5, y=3, z; z = addition ( x, y );Trong trường hợp này,hàm addition được truyền vào đối số là 5 và 3, đó là bản sao của các giá trị của x, và y, tương ứng. Các giá trị này (5 và 3) được sử dụng để khởi tạo các biến đặt dưới dạng các tham số trong định nghĩa của hàm, nhưng bất kỳ sửa đổi nào của các biến này trong hàm không ảnh hưởng đến các giá trị của các biến x và y bên ngoài, bởi vì x và y là bản thân nó không được chuyển đến hàm khi được gọi, chỉ có bản sao của các giá trị của nó tại thời điểm đó.
Trong một số trường hợp nhất định, tuy nhiên, có thể hữu ích để truy cập vào một biến bên ngoài từ bên trong một hàm. Để làm điều đó, đối số có thể được truyền bằng tham chiếu , thay vì theo giá trị . Ví dụ, hàm duplicatetrong đoạn mã này trùng lặp giá trị của ba đối số của nó, làm cho các biến được sử dụng làm đối số thực sự được sửa đổi khi được gọi:
#include <iostream> using namespace std; void duplicate (int& a, int& b, int& c) { a*=2; b*=2; c*=2; } int main () { int x=1, y=3, z=7; duplicate (x, y, z); cout << "x=" << x << ", y=" << y << ", z=" << z; return 0; } x = 2, y = 6, z = 14Để truy cập các đối số của nó, hàm tuyên bố các tham số của nó như các tham chiếu . Trong C + +, tài liệu tham khảo được chỉ định bằng ký hiệu và ( and - &) theo kiểu tham số, như trong các tham số được thực hiện bởi hàm duplicatetrong ví dụ trên.
Khi một biến được truyền bằng tham chiếu , biến được truyền đi không còn là một bản sao nữa, nhưng bản thân biến được xác định bởi tham số hàm, bằng cách nào đó liên kết với đối số được truyền đến hàm và bất kỳ sửa đổi nào trên các biến cục bộ tương ứng được phản ánh trong các biến được truyền như các đối số khi hàm được gọi.
Trong thực tế, a, b, và ctrở thành bí danh (aliases) của đối số được truyền trên đến hàm được gọi ( x, y, vàz) và bất kỳ thay đổi nào của abên trong hàm sẽ làm sửa đổi biến xbên ngoài hàm. Bất kỳ thay đổi nào của b sẽ sửa đổi yvà bất kỳ thay đổi nào đối với c sẽ sửa đổi z. Đó là lý do tại sao khi, trong ví dụ này, hàm duplicatelàm thay đổi các giá trị của các biến a, bvà c, các giá trị của x, yvà zbị ảnh hưởng.
Nếu thay vào đó khai báo hàm duplicate từ:
void duplicate (int& a, int& b, int& c)thành:
void duplicate (int a, int b, int c) Các biến sẽ không được truyền bằng tham chiếu . Trong trường hợp này, đầu ra của chương trình sẽ là các giá trị của x, y và zkhông bị sửa đổi (ví dụ, 1, 3 và 7).Khai báo hàm
Trong C++, định danh chỉ có thể được sử dụng sau khi khai báo. Ví dụ một biến x kiêu int không thể đươc sử dụng trước khi được khai báo, chẳng hạn như:
int x;Tương tự như vậy, các hàm cũng cần được khai báo trước khi sử dụng. Đó là lý do tại sao trong tất cả các ví dụ trước hàm luôn được đặt trước hàm main(), bởi nếu hàm main đã được khai báo trước đó sẽ phá vỡ quy tắc và chương trình sẽ không thể biên dịch được.
Nguyên mẫu của một hàm có thể được khai báo mà không thực sự định nghĩa hoàn toàn chức năng, cho biết chi tiết để có thể gọi được hàm đó. Đương nhiên, hàm sẽ được định nghĩa ở nơi khác, như ở phần sau của mã. Nhưng ít nhất, một khi đã khai báo như thế này, nó đã có thể được gọi.
Khai báo bao gồm tất cả các loại liên quan (kiểu trả về và loại đối số của nó), sử dụng cú pháp giống như được sử dụng trong định nghĩa hàm, nhưng thay thế phần thân của hàm (khối lệnh) bằng dấu chấm phẩy cuối.
Danh sách tham số không cần phải bao gồm tên tham số, nhưng chỉ rõ kiểu dữ liệu của chúng. Tuy nhiên, các tên tham số vẫn có thể được chỉ định, nhưng chúng là tùy chọn, và không nhất thiết phải khớp với tên trong định nghĩa hàm. Ví dụ, một hàm được gọi protofunctionvới hai tham số int có thể được khai báo với một trong hai câu lệnh sau:
int protofunction (int first, int second); int protofunction (int, int);Dù sao, có cả tên cho mỗi tham số, luôn cải thiện tính dễ đọc của khai báo.
Ví dụ: Viết chương trình C++ để cho biết số nhập vào là số chẵn hay số lẽ:
#include <iostream> using namespace std; void odd (int x); void even (int x); int main() { int i; do { cout << "Vui lòng nhập số (0 để thoát): "; cin >> i; odd (i); } while (i!=0); return 0; } void odd (int x) { if ((x%2)!=0) cout << "Nó là số lẻ.\n"; else even (x); } void even (int x) { if ((x%2)==0) cout << "Nó là số chẵn.\n"; else odd (x); }Kết quả:
Vui lòng nhập số (0 để thoát): 9 Nó là số lẻ. Vui lòng nhập số (0 để thoát): 6 Nó là số chẵn. Vui lòng nhập số (0 để thoát): 1030 Nó là số chẵn. Vui lòng nhập số (0 để thoát): 0 Nó là số chẵn.Việc khai báo các hàm trước khi được định nghĩa rất hữu ích để tổ chức lại thứ tự các hàm trong mã.
Hàm đệ quy (Recursivity) trong C++
Sự đệ quy là thuộc tính mà các hàm có thể tự gọi chính bản thân nó. Nó rất hữu ích cho một số nhiệm vụ, chẳng hạn như sắp xếp các phần tử, hoặc tính nhân tố số. Ví dụ, để có được giai thừa của một số (n!) công thức toán học sẽ là:
n! = n * (n-1) * (n-2) * (n-3) ... * 1Cụ thể hơn, 5!(giai thừa của 5) sẽ là:
5! = 5 * 4 * 3 * 2 * 1 = 120Và một hàm đệ quy để tính toán này trong C + + có thể là:
#include <iostream> using namespace std; long factorial (long a) { if (a > 1) return (a * factorial (a-1)); else return 1; } int main () { long number = 9; cout << number << "! = " << factorial (number); return 0; } 9! = 362880Chú ý ở hàm factorial nó có thể gọi chính bản thân nó, nhưng chỉ khi đối số được truyền lớn hơn 1, vì nếu không thì hàm sẽ thực hiện một vòng lặp đệ quy vô hạn. Một khi nó đến 0, nó sẽ tiếp tục nhân lên bởi tất cả số âm (có thể gây tràn stack tại một số điểm trong thời gian chạy).
Từ khóa » Hàm Main Trong C++ Có đặc điểm Như Thế Nào
-
Khai Báo Thư Viện Và Hàm Main Trong C++ - Freetuts
-
Hàm Trong C++ - Học Lập Trình C++ Online - VietTuts
-
Hàm Trong C/C++
-
1.7. Chia Nhỏ Chương Trình Thành Các Hàm - Lập Trình Tân Binh
-
[Lập Trình C++ Cơ Bản] Bài 6: Hàm Trong C++ - Viblo
-
1.1 Cấu Trúc Cơ Bản Của Một Chương Trình C++
-
7.0 Làm Quen Với Khái Niệm Function - Khóa Học C++
-
Cơ Bản Về Class Trong C++ | TopDev
-
Cú Pháp Ngôn Ngữ C++ – Wikipedia Tiếng Việt
-
Hàm Tạo (lập Trình Hướng đối Tượng) – Wikipedia Tiếng Việt
-
[PDF] Bài 2 - NGÔN NGỮ LẬP TRÌNH C/C++ - FIT@MTA
-
Lập Trình C++ - Hàm Trong C++