Truyền hàm làm đối số
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 36 trên 61.
Một trong những cách sử dụng con trỏ hàm (function pointer) hiệu quả nhất là truyền chúng làm đối số cho các hàm khác. Cách này cho phép bạn thêm hành vi tùy chỉnh vào một hàm mà không cần sửa code của hàm đó, đây là kỹ thuật đôi khi được gọi là callback.
Hãy xem xét một hàm thực hiện phép tính trên hai số. Thay vì viết cứng phép toán, bạn có thể nhận một con trỏ hàm xác định phép toán cần thực hiện:
typedef int (*Operation)(int, int);
int compute(int a, int b, Operation op) {
return op(a, b);
}Hàm compute không biết mình đang cộng, trừ hay làm việc gì khác. Hàm chỉ gọi hàm được truyền vào:
int add(int a, int b) { return a + b; }
int multiply(int a, int b) { return a * b; }
int main() {
printf("%d\n", compute(5, 3, add)); // Đầu ra: 8
printf("%d\n", compute(5, 3, multiply)); // Đầu ra: 15
return 0;
}Hãy chú ý rằng cùng một hàm compute tạo ra các kết quả khác nhau tùy vào hàm mà ta truyền vào. Mẫu này là nền tảng để viết code linh hoạt và có thể tái sử dụng. Bạn viết cấu trúc một lần, rồi người dùng hàm của bạn cung cấp logic cụ thể mà họ cần.
Thử thách
DễViết hàm apply_twice nhận hai số nguyên và một mã thao tác, áp dụng thao tác đó lần lượt lên các số hai lần rồi trả về kết quả cuối cùng.
Hàm của bạn sẽ nhận một mã thao tác để xác định thao tác cần dùng. Bạn cần định nghĩa các hàm thao tác bên trong lời giải, rồi truyền chúng vào hàm hỗ trợ compute, hàm này nhận một con trỏ hàm.
Lưu ý: bạn chỉ cần viết các hàm. Các bài kiểm tra gọi trực tiếp apply_twice và kiểm tra giá trị trả về, vì vậy đừng đọc đầu vào hay in ra bất cứ thứ gì.
Cấu trúc bắt buộc:
- Định nghĩa một
typedefcó tênOperationcho con trỏ hàm nhận hai tham sốintvà trả về mộtint - Định nghĩa hai hàm thao tác:
add(trả về a + b) vàmultiply(trả về a * b) - Định nghĩa hàm
computenhận hai số nguyên và một con trỏ hàmOperation, sau đó trả về kết quả gọi thao tác đó - Trong
apply_twice, chọn thao tác phù hợp dựa trên mã, rồi dùngcomputehai lần: lần đầu với các số ban đầu, lần sau với kết quả và số thứ hai
Logic:
- Chọn hàm thao tác dựa trên
op_code(1 = add, 2 = multiply) - Gọi
compute(a, b, operation)để lấy kết quả trung gian - Gọi
compute(intermediate, b, operation)để lấy kết quả cuối cùng - Trả về kết quả cuối cùng
Tham số:
a(int): Số thứ nhấtb(int): Số thứ haiop_code(int): Mã thao tác (1 để cộng, 2 để nhân)
Giá trị trả về: Kết quả sau khi áp dụng thao tác đó lần lượt hai lần (int)
Ví dụ: Với a = 5, b = 3, op_code = 1 (cộng):
- Lần tính đầu tiên: 5 + 3 = 8
- Lần tính thứ hai: 8 + 3 = 11
- Trả về: 11
Với a = 2, b = 4, op_code = 2 (nhân):
- Lần tính đầu tiên: 2 × 4 = 8
- Lần tính thứ hai: 8 × 4 = 32
- Trả về: 32
Tự làm thử
int apply_twice(int a, int b, int op_code) {
// Viết code vào đây
}
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