[Học lập trình C++] Chương 1: 1.4 Làm quen với hàm và giá trị trả về
1.4 Làm quen với hàm và giá trị trả về
Một hàm là một chuỗi
các câu lệnh có thể sử dụng lại được thiết kế để thực hiện một công việc cụ thể.
Bạn đã biết rằng mọi chương trình phải có một hàm tên là main() (hàm này là nơi
mà chương trình bắt đầu thực thi). Tuy nhiên, hầu hết chương trình sử dụng nhiều
hàm.
Thông thường, chương
trình của bạn cần ngắt những gì đang làm để tạm thời làm việc khác. Bạn luôn thực
hiện điều này trong đời thực. Ví dụ, bạn có thể đang đọc sách khi bạn nhớ bạn cần
thực hiện một cuộc gọi. Bạn để một đánh dấu vào quyển sách của bạn, thực hiện
cuộc gọi, và khi bạn gọi xong, bạn quay trở về quyển sách và đọc tiếp những gì
bạn bỏ dở.
Chương trình C++ hoạt
động theo cách tương tự. Một chương trình sẽ thực thi câu lệnh tuần tự bên
trong một hàm khi nó gặp lệnh gọi hàm. Một lời gọi hàm là một phát biểu nói cho
CPU ngắt hàm hiện tại để thực hiện một hàm khác. CPU đánh dấu tại điểm đang thực
thi, và sau đó gọi (thực thi) tên hàm trong lời gọi hàm. Khi hàm gọi kết thúc,
CPU quay trở về điểm đã được đánh dấu và phục hồi lại sự thực thi ban đầu.
Đây là một chương
trình mẫu mà cho thấy hàm mới được định nghĩa và được gọi như thế nào.
//#include <stdafx.h> // Visual Studio users
need to uncomment this line
#include <iostream> // for std::cout and std::endl
// Definition of function doPrint()
void doPrint()
{
std::cout << "In
doPrint()" << std::endl;
}
// Definition of function main()
int main()
{
std::cout << "Starting
main()" << std::endl;
doPrint(); // Interrupt main() by making a function
call to doPrint()
std::cout << "Ending
main()" << std::endl;
return 0;
}
Chương trình sẽ tạo ra kết
quả sau:
Starting main()
In doPrint()
Ending main()
Chương trình này bắt
đầu thực thi tại phần đầu của hàm main(), và dòng đầu tiên được thực thi in ra
starting main(). Dòng thứ 2 trong main là một lời gọi hàm gọi tới hàm
doPrint(). Tại điểm này, việc thực thi câu lệnh trong main() là được hoãn lại
và CPU nhảy vào doPrint(). Dòng duy nhất trong hàm doPrint in ra “In doPrint()”.
Khi doPrint() kết thúc, trình gọi (main()) hồi phục lại quá trình thực thi tại
nơi cũ. Do vậy, câu lệnh tiếp theo thực thi trong main là in ra Endling main().
Chú ý rằng lời gọi
hàm được thực hiện bởi sử dụng tên hàm, cộng thêm tham số nằm trong dấu ngoặc
đơn. Trong trường hợp này, không có tham số nào được truyền vào. Chúng ta sẽ thảo
luận về tham số hàm trong bài học kế tiếp. Nếu bạn quyên tham số, hàm sẽ không
được gọi.
Giá trị trả về
Nếu bạn nhớ, khi hàm
main() kết thúc thực thi, nó trả về một giá trị integer cho hệ thống (trình gọi)
bằng một câu lệnh return.
Hàm bạn viết có thể
trả về một giá trị đơn cho trình gọi chúng. Chúng ta thực hiện điều này bằng
cách thiết lập kiểu trả về của hàm trong định nghĩa hàm. Kiểu giá trị trả về là
kiểu được khai báo trước tên hàm.
Kiểu trả về là void
có nghĩa là hàm không trả về một giá trị. Kiểu trả về là int nghĩa là hàm trả về
một giá trị integer cho trình gọi.
1
2
3
4
5
6
7
8
9
10
11
|
// void means the function does not return a value to the caller
void returnNothing()
{
// This function does not
return a value so no return statement is needed
}
// int means the function returns an integer value to the caller
int return5()
{
return 5; // this function
returns an integer, so a return statement is needed
}
|
Sử dụng những hàm này
trong chương trình:
#include <iostream>
// void means the function does not return a value
to the caller
void returnNothing()
{
// This function does not return a value so no
return statement is needed
}
// int means the function returns an integer value
to the caller
int return5()
{
return 5; // this function returns an integer, so a
return statement is needed
}
int main()
{
std::cout << return5() <<
std::endl; // prints 5
std::cout << return5() + 2 << std::endl;
// prints 7
returnNothing(); // okay: function returnNothing()
is called, no value is returned
return5(); // okay: function
return5() is called, return value is discarded
std::cout << returnNothing();
// This line will not compile. You'll need to comment it out to continue.
return 0;
}
Trong lời gọi hàm đầu
tiên, return5() được thực thi. Hàm trả về giá trị 5 cho trình gọi, cái mà đưa
giá trị vào cout.
Trong lời gọi hàm thứ
hai, return5() được thực thi và trả về giá trị 5 cho trình gọi. Biểu thức 5+2
sau đó được tính ra 7. Giá trị 7 được đưa vào cout.
Trong lời gọi hàm thứ
ba, returnNothing() được thực thi. Trong hàm không làm gì cả và không trả về gì
cả vì vậy quyền điều khiển trả về cho hàm main().
Trong lần gọi hàm thứ
tư, return5() được thực thi. Giá trị 5 được trả về hàm main(), nhưng hàm main()
không làm gì với giá trị trả về đó, vì vậy giá trị trả về bị bỏ qua.
Trong lần gọi hàm thứ
năm, returnNothing() trả về kiểu void. Điều này không hợp lệ khi truyền giá trị
void vào cout, và trình biên dịch sẽ đưa cho bạn một lỗi khi bạn cố gằng biên dịch
dòng này. Bạn sẽ cần comment dòng này lại để làm cho code của bạn biên dịch được.
Một câu hỏi phổ biến
là “Hàm của tôi có thể trả về nhiều giá trị sử dụng câu lệnh return hay không?”.
Câu trả lời là không. Hàm chỉ có thể trả về một giá trị đơn sử dụng câu lệnh
return. Tuy nhiên, có nhiều cách để giải quyết vấn đề này, cái mà chúng ta sẽ
thảo luận sâu hơn ở phần hàm.
Trả về cho hàm main
Bây giờ bạn đã có thể
hiểu khái niệm về cách làm việc của hàm main. Khi một chương trình được thực
thi, hệ thống tạo một lời gọi hàm tới hàm main(). Sự thực thi sau đó nhảy đến
phần trên cùng của hàm main. Câu lệnh trong hàm main được thực thi một cách tuần
tự. Cuối cùng main trả về một giá trị integer (thường là 0) ngược lại cho hệ thống.
Điều này giải thích tại sao main được định nghĩa như sau int main().
int main()
{
// your code here
return 0;
}
Bạn luôn định nghĩa
hàm main trả về giá trị zero.
Từ bây giờ bạn nên chỉ
định nghĩa main ở cuối file mã nguồn.
Sử dụng lại hàm
Cùng một hàm có thể
được gọi nhiều lần, cái mà hữu ích nếu bạn cần làm một thứ gì đó nhiều hơn một
lần.
//#include <stdafx.h> // Visual Studio users
need to uncomment this line
#include <iostream>
// getValueFromUser will read a value in from the user, and return
it to the caller
int getValueFromUser()
{
std::cout << "Enter
an integer: ";
int a;
std::cin >> a;
return a;
}
int main()
{
int x = getValueFromUser(); //
first call to getValueFromUser
int y = getValueFromUser(); // second call to
getValueFromUser
std::cout << x << " + " <<
y << " = " << x + y << std::endl;
return 0;
}
Chương trình này sẽ tạo
ra kết quả sau:
Enter an integer: 5
Enter an integer: 7
5 + 7 = 12
Trong trường hợp này,
main() được ngắt 2 lần, mỗi một lần cho mỗi lần gọi hàm getValueFromUser(). Chú ý rằng không chỉ hàm main gọi
hàm khác mà tất cả cả hàm khác có thể gọi lẫn nhau.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
//#include <stdafx.h> // Visual Studio users need to
uncomment this line
#include <iostream>
void printA()
{
std::cout << "A"
<< std::endl;
}
void printB()
{
std::cout << "B"
<< std::endl;
}
// function printAB() calls both printA() and printB()
void printAB()
{
printA();
printB();
}
// Definition of main()
int main()
{
std::cout << "Starting
main()" << std::endl;
printAB();
std::cout << "Ending
main()" << std::endl;
return 0;
}
|
Chương trình này tạo
ra kết quả sau:
Starting main()
A
B
Ending main()
Hàm lồng nhau
Hàm không thể được định
nghĩa bên trong hàm khác trong C++. Chương trình sau là không hợp lệ:
#include <iostream>
int main()
{
int foo() // this function is
nested inside main(), which is illegal.
{
std::cout << "foo!";
return 0;
}
foo();
return 0;
}
Cách thích hợp để viết
chương trình trên là:
2
3
4
5
6
7
8
9
10
11
12
13
|
#include <iostream>
int foo() // no longer inside of main()
{
std::cout << "foo!";
return 0;
}
int main()
{
foo();
return 0;
}
|
Nguồn: learncpp.com
Nhận xét
Đăng nhận xét