Mô phỏng phương thức
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 39 trên 61.
Bạn đã thấy cách đặt con trỏ hàm bên trong một struct. Sức mạnh thực sự xuất hiện khi bạn gán các hàm khác nhau cho những instance khác nhau của cùng một kiểu struct. Đây là cách mô phỏng các phương thức có hành vi khác nhau.
Hãy xem một struct biểu diễn một hành động với logic có thể tùy chỉnh:
typedef void (*ActionFunc)(void);
typedef struct {
const char* name;
ActionFunc execute;
} Action;Khi tạo các đối tượng, bạn kết nối từng hàm với một đối tượng:
void say_hello(void) {
printf("Hello!\n");
}
void say_goodbye(void) {
printf("Goodbye!\n");
}
int main() {
Action greet = { "Greet", say_hello };
Action farewell = { "Farewell", say_goodbye };
greet.execute(); // Đầu ra: Hello!
farewell.execute(); // Đầu ra: Goodbye!
return 0;
}Cả greet và farewell đều cùng kiểu (Action), nhưng gọi execute trên mỗi giá trị lại cho kết quả hoàn toàn khác nhau. Struct không chỉ chứa dữ liệu. Nó còn chứa hành vi thay đổi theo từng instance.
Mẫu này tương tự cách các đối tượng hoạt động trong những ngôn ngữ khác: mỗi đối tượng có thể có cách triển khai phương thức riêng, dù chúng dùng chung một giao diện.
Thử thách
DễHãy xây dựng một hệ thống Speaker để minh họa cách các instance khác nhau của cùng một kiểu struct có thể thể hiện những hành vi hoàn toàn khác nhau, tùy thuộc vào hàm được gán cho chúng.
Bạn sẽ tạo hai tệp để sắp xếp code:
speaker.h: Định nghĩa một kiểu con trỏ hàm có tênSpeakFunc, không nhận tham số và không trả về giá trị nào. Sau đó, định nghĩa một structSpeakerchứaname(kiểuconst char*) và một con trỏ hàmspeakkiểuSpeakFunc.main.c: Thêm header của bạn và triển khai ba hàm phát ra âm thanh khác nhau:bark: in raWoof!meow: in raMeow!chirp: in raChirp!
Speaker, mỗi instance được gán một hàm khác nhau dựa trên đầu vào, rồi gọi phương thứcspeakcủa chúng để xem tính đa hình hoạt động.
Chương trình của bạn sẽ nhận hai đầu vào: kiểu loa thứ nhất (1 là bark, 2 là meow, 3 là chirp) và kiểu loa thứ hai (cũng là 1, 2 hoặc 3).
Tạo hai instance Speaker. Bạn có thể đặt tên tùy ý cho chúng (chẳng hạn như "Dog", "Cat", "Bird", hoặc đơn giản là "Speaker1", "Speaker2"). Gán cho mỗi instance hàm phù hợp dựa trên mã đầu vào, rồi lần lượt gọi speak trên từng instance.
Ví dụ đầu ra khi kiểu thứ nhất là 1 và kiểu thứ hai là 2:
Woof!
Meow!Ví dụ đầu ra khi kiểu thứ nhất là 3 và kiểu thứ hai là 3:
Chirp!
Chirp!Điểm mấu chốt ở đây là cả hai loa đều có cùng kiểu Speaker, nhưng tạo ra đầu ra khác nhau vì mỗi loa có một hàm khác nhau được gán cho thành viên speak. Hãy nhớ dùng các include guard trong tệp header.
Tự làm thử
#include <stdio.h>
#include "speaker.h"
// TODO: Viết hàm (function) bark để in ra "Woof!"
// TODO: Viết hàm meow để in ra "Meow!"
// TODO: Viết hàm chirp để in ra "Chirp!"
int main() {
int type1, type2;
scanf("%d", &type1);
scanf("%d", &type2);
// TODO: Tạo hai instance của Speaker
// TODO: Gán hàm speak cho speaker thứ nhất dựa trên type1
// (1 = bark, 2 = meow, 3 = chirp)
// TODO: Gán hàm speak cho speaker thứ hai dựa trên type2
// (1 = bark, 2 = meow, 3 = chirp)
// TODO: Gọi speak trên từng speaker theo thứ tự
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ật2Đố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ản8Đa hình
Con trỏ hàm trong structMô phỏng phương thứcKhái niệm interfaceTriển khai interfaceLặp đa hìnhÔn tập: Greeter3Vò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