Khai báo 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 33 trên 61.
Đến nay, chúng ta đã học cách mô phỏng tính kế thừa bằng cách nhúng struct. Nhưng đa hình thực sự, khi các đối tượng khác nhau phản hồi khác nhau với cùng một lời gọi, cần thêm một yếu tố: con trỏ hàm.
Con trỏ hàm là một biến lưu địa chỉ của một hàm. Giống như con trỏ thông thường lưu địa chỉ của dữ liệu, con trỏ hàm lưu địa chỉ của mã có thể thực thi.
Cú pháp này có thể trông khó hiểu lúc đầu. Để khai báo một con trỏ hàm (function pointer), bạn chỉ định kiểu giá trị trả về, sau đó là tên con trỏ trong ngoặc đơn cùng với dấu hoa thị, rồi đến các kiểu tham số:
int (*operation)(int, int);Câu lệnh này khai báo một biến có tên operation, biến này có thể trỏ đến bất kỳ hàm (function) nào nhận hai tham số int và trả về một int. Dấu ngoặc đơn quanh *operation rất quan trọng, nếu không có chúng, bạn sẽ khai báo một hàm trả về một con trỏ.
Để gán một hàm (function) cho con trỏ này, chỉ cần dùng tên hàm (không có dấu ngoặc đơn):
int add(int a, int b) {
return a + b;
}
int (*operation)(int, int);
operation = add; // Bây giờ operation trỏ đến addTên hàm đóng vai trò như địa chỉ của hàm. Bạn cũng có thể dùng &add một cách tường minh, nhưng không bắt buộc: cả hai cách đều tương đương trong C.
Thử thách
DễHãy luyện tập khai báo con trỏ hàm và gán hàm cho chúng. Bạn sẽ tạo một hệ thống phép toán đơn giản, trong đó một con trỏ hàm có thể trỏ đến các hàm số học khác nhau.
Viết một chương trình:
- Định nghĩa hai hàm:
multiply: nhận hai tham sốintvà trả về tích 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 biến con trỏ hàm tên làoperation, có thể trỏ đến các hàm nhận hai tham sốintvà trả về một giá trịint - Đọc ba đầu vào: hai số nguyên và một mã phép toán (1 để nhân, 2 để trừ)
- Dựa trên mã phép toán, gán hàm phù hợp cho con trỏ
operation - In tên phép toán đã gán, sau đó in kết quả gọi hàm thông qua con trỏ
Bạn sẽ nhận ba đầu vào: số thứ nhất, số thứ hai và mã phép toán (1 hoặc 2).
Đầu ra của bạn sẽ trông như sau:
Operation: multiply
Result: 35Trong đó, multiply là tên phép toán (hoặc subtract nếu mã là 2), còn 35 là kết quả gọi hàm thông qua con trỏ (trong trường hợp này, 5 × 7).
Hãy nhớ: để khai báo con trỏ hàm, bạn cần có kiểu trả về, tên con trỏ đặt trong ngoặc đơn cùng dấu hoa thị và các kiểu tham số. Để gán một hàm, chỉ dùng tên hàm, không có dấu ngoặc đơn.
Tự làm thử
#include <stdio.h>
// TODO: Định nghĩa hàm (function) multiply ở đây
// TODO: Định nghĩa hàm subtract ở đây
int main() {
int num1, num2, code;
// Đọc đầu vào
scanf("%d", &num1);
scanf("%d", &num2);
scanf("%d", &code);
// TODO: Khai báo con trỏ hàm tên 'operation' có thể trỏ đến
// các hàm nhận hai tham số int và trả về một giá trị int
// TODO: Dựa vào mã phép toán (1 là multiply, 2 là subtract),
// gán hàm phù hợp cho con trỏ operation
// TODO: In ra tên phép toán và kết quả
// Định dạng:
// Operation: <name>
// Result: <result>
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