[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

Bài đăng phổ biến