Giới thiệu
Trong bài viết trước, bạn đã được tìm hiểu về ép kiểu dữ liệu và kỹ thuật ÉP KIỂU TƯỜNG MINH TRONG C++ (Explicit type conversion). Hôm nay, chúng ta sẽ cùng nhau khám phá về Cơ bản về Hàm và Giá trị trả về (Basics of Functions and Return values), một phần không thể thiếu trong hầu hết các ngôn ngữ lập trình.
Nội dung
Để hiểu rõ bài viết này, hãy nắm vững kiến thức cơ bản về các phần sau:
- CẤU TRÚC MỘT CHƯƠNG TRÌNH C++ (Structure of a program)
Trong bài viết này, chúng ta sẽ tìm hiểu về các vấn đề sau:
- Tổng quan về hàm (functions overview)
- Giá trị trả về (return values)
- Giá trị trả về của kiểu void (return values of type void)
Tổng quan về hàm (functions overview)
Giả sử chúng ta có một chương trình yêu cầu tính tuổi của người dùng dựa trên năm sinh được nhập từ bàn phím.
#include
using namespace std;
int main() {
int year;
cout "Nhập năm sinh của bạn: ";
cin >> year;
int age = 2016 - year;
cout "Tuổi của bạn là: " age endl;
return 0;
}
Chương trình trên dùng để tính tuổi của một người. Giả sử bây giờ chúng ta cần tính tuổi của 3 người. Vấn đề phát sinh từ đó là chúng ta phải lặp lại những dòng code tương tự để tính tuổi cho 2 người tiếp theo. Điều này dẫn đến trùng lắp code và mất nhiều thời gian xây dựng chương trình. Để khắc phục vấn đề đó, khái niệm Hàm (Function) trong lập trình được ra đời.
Hàm (function) là một dãy các câu lệnh có thể tái sử dụng, được thiết kế để thực hiện một công việc cụ thể trong chương trình.
Cú pháp của hàm trong C++:
([ ]) { [return ;] } Trong đó:
: kiểu bất kỳ của C++ (bool, char, int, double,...). Nếu không trả về thì là void.
: theo quy tắc đặt tên định danh.
: tham số hình thức đầu vào giống khai báo biến, cách nhau bằng dấu phẩy ",". (Có thể không có)
: trả về cho hàm qua lệnh return. (Có thể không có)
Trong bài CẤU TRÚC MỘT CHƯƠNG TRÌNH C++ (Structure of a program), bạn đã biết mỗi chương trình C++ đều có một hàm tên là main(), hàm này là nơi bắt đầu của chương trình. Trong thực tế, một chương trình thường sẽ có rất nhiều hàm bên trong.
Ví dụ về chương trình đơn giản có 2 hàm: main() và sayHello()
#include
using namespace std;
// Định nghĩa hàm sayHello()
void sayHello() // sayHello() là hàm được gọi trong ví dụ này
{
cout "Xin chào Howkteam.com!" endl;
}
// Định nghĩa hàm main()
int main()
{
cout "Bắt đầu main()" endl;
// Ngắt main() bằng cách gọi hàm sayHello(). main() là người gọi.
sayHello();
cout "Kết thúc main()" endl;
return 0;
}
Chương trình sẽ thực thi các câu lệnh một cách tuần tự bên trong một hàm. Khi gặp một lời gọi hàm, CPU sẽ gián đoạn hàm hiện tại để thực thi các câu lệnh bên trong hàm được gọi. Khi hàm được gọi kết thúc, CPU sẽ lại tiếp tục thực thi hàm hiện tại.
Chú ý: Hàm có thể được gọi nhiều lần trong một chương trình (tính tái sử dụng), và bất kỳ hàm nào cũng đều có thể gọi hàm khác.
Hiện tại, bạn nên đặt hàm main() ở vị trí cuối cùng trong file code của chương trình. Lý do tại sao sẽ được đề cập cụ thể trong bài TIỀN KHAI BÁO & ĐỊNH NGHĨA HÀM (Forward declarations and Definitions of Functions).
Giá trị trả về (return values)
Trong bài CẤU TRÚC MỘT CHƯƠNG TRÌNH C++ (Structure of a program), bạn đã biết hàm main() có kiểu int nên bắt buộc phải có một câu lệnh return giá trị kiểu int. Khi chương trình thực thi kết thúc, hàm main() sẽ return một giá trị cho hệ điều hành, để thông báo là chương trình chạy thành công hay không.
Khi tạo ra một hàm mới, tùy vào mục đích của hàm mà bạn có thể quyết định hàm đó có trả về một giá trị nào đó hay không.
Để tạo ra một hàm có giá trị trả về, bạn cần:
- Thiết lập kiểu trả về trong định nghĩa của hàm
- Sử dụng câu lệnh return để trả về một giá trị.
Chú ý: Khi gặp câu lệnh return, hàm sẽ trả về giá trị ngay tại thời điểm đó. Tất cả câu lệnh trong hàm, sau dòng lệnh return sẽ được bỏ qua.
Ví dụ về chương trình có hàm trả về một số nguyên:
#include
using namespace std;
// int có nghĩa là hàm trả về một giá trị số nguyên cho người gọi
int return69()
{
// hàm này trả về một số nguyên, nên cần câu lệnh return
return 69; // chúng ta trả về giá trị số nguyên 69
}
int main()
{
cout return69() endl; // in ra 69
int sum = return69() + 1;
cout sum endl; // in ra 70
return69(); // hợp lệ: giá trị 69 được trả về, nhưng bị bỏ qua
return 0;
}
Hàm có giá trị trả về có thể đặt riêng biệt hoặc bên trong một biểu thức như ở ví dụ trên.
Một câu hỏi thường được đặt là: "Hàm có thể trả về nhiều giá trị thông qua câu lệnh return?". Câu trả lời là không. Khi sử dụng câu lệnh return, hàm chỉ có thể trả về một giá trị duy nhất.
Tuy nhiên, bạn có thể sử dụng phương pháp truyền tham chiếu hoặc truyền địa chỉ cho hàm để có thể lấy được nhiều giá trị:
- Phương pháp truyền tham chiếu sẽ được hướng dẫn ở bài: TRUYỀN THAM CHIẾU CHO HÀM (Passing Arguments by Reference).
- Phương pháp truyền địa chỉ (con trỏ) sẽ được hướng dẫn trong bài: TRUYỀN ĐỊA CHỈ CHO HÀM (Passing arguments by address).
Giá trị trả về của kiểu void (return values of type void)
Những hàm có mục đích tính toán thường sẽ trả về một giá trị khi kết thúc hàm. Đối với những hàm không có mục đích tính toán (Vd: hàm setter, hàm print, ...), C++ hỗ trợ sử dụng kiểu dữ liệu void cho những hàm không có giá trị trả về.
#include
using namespace std;
// void có nghĩa là hàm không trả về giá trị cho người gọi
void sayHello()
{
cout "Xin chào Howkteam.com!" endl;
cout "Học trực tuyến miễn phí" endl;
// Hàm này không trả về giá trị nên không cần câu lệnh return
}
int main()
{
sayHello(); // hợp lệ: hàm sayHello() được gọi, không trả về giá trị
cout sayHello(); // lỗi: dòng này không thể biên dịch. Bạn cần comment dòng này để tiếp tục.
return 0;
}
Trong chương trình trên, hàm sayHello() có kiểu void nên không trả về giá trị. Từ đó, trình biên dịch sẽ thông báo lỗi không thể in giá trị của hàm sayHello() ra màn hình trong lần gọi hàm thứ hai.
Chú ý:
- Hàm có kiểu void sẽ không có giá trị trả về.
- Có thể sử dụng câu lệnh return trong hàm void để kết thúc hàm ngay lập tức.
Kết luận
Qua bài học này, bạn đã nắm được Cơ bản về Hàm và Giá trị trả về (Basics of Function and Return values) trong C++. Mình tóm tắt lại một số nội dung quan trọng mà bạn cần nắm:
- Hàm có thể được gọi nhiều lần trong một chương trình (tính tái sử dụng).
- Khi gặp câu lệnh return, hàm sẽ trả về giá trị ngay tại thời điểm đó. Tất cả câu lệnh trong hàm, sau dòng lệnh return sẽ được bỏ qua.
- Hàm có kiểu void sẽ không có giá trị trả về.