Gọi con trỏ hàm
Thuộc phần Lập trình hướng đối tượng trong hành trình C của Coddy. Bài học 34 trên 61.
Bây giờ bạn đã biết cách khai báo con trỏ hàm và gán một hàm cho nó, bước tiếp theo là thực sự gọi hàm thông qua con trỏ đó.
Cú pháp khá đơn giản. Bạn dùng con trỏ hàm (function pointer) giống như khi gọi một hàm thông thường:
int add(int a, int b) {
return a + b;
}
int main() {
int (*operation)(int, int) = add;
int result = operation(5, 3); // Gọi add(5, 3)
printf("%d\n", result); // Đầu ra: 8
return 0;
}Chỉ cần viết tên con trỏ, theo sau là dấu ngoặc đơn chứa các đối số. C tự động giải tham chiếu con trỏ và thực thi hàm mà nó trỏ đến.
Bạn cũng có thể dùng cú pháp giải tham chiếu tường minh với (*operation)(5, 3), nhưng đây là cách không bắt buộc và ít phổ biến hơn. Cả hai cách đều cho kết quả giống hệt nhau.
Sức mạnh thực sự thể hiện khi bạn gán lại con trỏ cho các hàm khác nhau:
int subtract(int a, int b) {
return a - b;
}
operation = subtract;
result = operation(5, 3); // Bây giờ gọi subtract(5, 3)
printf("%d\n", result); // Đầu ra: 2Biến operation giờ thực thi logic hoàn toàn khác. Khả năng thay đổi hành vi khi chương trình đang chạy này là nền tảng của tính đa hình trong C.
Thử thách
DễHãy luyện tập cách gọi hàm thông qua con trỏ và thay đổi hàm sẽ được thực thi. Bạn sẽ xây dựng một máy tính đơn giản có thể chuyển đổi giữa phép cộng và phép trừ khi chương trình đang chạy.
Viết một chương trình:
- Định nghĩa hai hàm:
add: nhận hai tham sốintvà trả về tổng của chúngsubtract: nhận hai tham sốintvà trả về hiệu của số thứ nhất trừ số thứ hai
- Trong
main, khai báo một con trỏ hàm có têncalc, có thể trỏ đến các hàm nhận hai tham sốintvà trả về mộtint - Đọc bốn đầu vào: hai số nguyên và hai mã phép toán
- Với mỗi mã phép toán:
- Gán hàm phù hợp cho
calc(1 cho phép cộng, 2 cho phép trừ) - Gọi hàm thông qua con trỏ với hai số
- In ra kết quả
- Gán hàm phù hợp cho
Bạn sẽ nhận bốn đầu vào: số thứ nhất, số thứ hai, mã phép toán thứ nhất (1 hoặc 2) và mã phép toán thứ hai (1 hoặc 2).
Đầu ra cần hiển thị hai kết quả trên hai dòng riêng: mỗi kết quả ứng với một phép toán được thực hiện bằng cùng hai số:
15
5Trong ví dụ này, với các đầu vào 10, 5, 1, 2: phép toán thứ nhất (mã 1) cộng 10 + 5 = 15, sau đó con trỏ được gán lại và phép toán thứ hai (mã 2) trừ 10 - 5 = 5.
Điều này cho thấy cùng một biến con trỏ có thể thực thi logic hoàn toàn khác nhau khi bạn gán lại nó giữa các lần gọi.
Tự làm thử
#include <stdio.h>
// TODO: Định nghĩa hàm (function) add tại đây
// TODO: Định nghĩa hàm subtract tại đây
int main() {
// Đọc các giá trị đầu vào
int num1, num2, op1, op2;
scanf("%d", &num1);
scanf("%d", &num2);
scanf("%d", &op1);
scanf("%d", &op2);
// TODO: Khai báo con trỏ hàm tên 'calc' có thể trỏ đến
// các hàm nhận hai tham số kiểu int và trả về một giá trị kiểu int
// TODO: Với mã phép toán đầu tiên (op1):
// - Gán hàm phù hợp cho calc (1 là add, 2 là subtract)
// - Gọi hàm qua con trỏ và in kết quả
// TODO: Với mã phép toán thứ hai (op2):
// - Gán lại hàm phù hợp cho calc
// - Gọi hàm qua con trỏ và in kết quả
return 0;
}Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Kiến thức cơ bản về lập trình mô-đun
Tệp tiêu đềInclude guardTệp mã nguồnHàm staticÔn tập: Máy tính mô-đun4Tính đóng gói
Khái niệm con trỏ mờĐịnh nghĩa struct mờHàm truy xuất và hàm gánKiểm tra tính hợp lệ trong hàm gánÔn tập: Hộp bí mật7Con trỏ hàm
Khai báo con trỏ hàmGọi con trỏ hàmDùng typedef cho con trỏ hàmTruyền hàm làm đối sốÔn tập: điều phối máy tính2Đối tượng và phương thức
Struct dưới dạng đối tượngCon trỏ 'Self'Tính đúng đắn của constCon trỏ và giá trịPhương thức hỗ trợÔn tập: trình quản lý Point5Dự án: Tài khoản ngân hàng đơn giản
Thiết lập dự ánTriển khai tài khoản3Vòng đời đối tượng
Mẫu hàm khởi tạoMẫu hàm hủyKhởi tạo trên ngăn xếpSao chép sâuÔn tập: lớp bao bọc chuỗi6Kế thừa bằng cách kết hợp
Nhúng structQuy tắc thành viên đầu tiênTruy cập thành viên lớp chaUpcastingÔn tập: hệ phân cấp hình dạngTự luyện tập: Trình biên dịch C online