Tổng quan về dự án
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 44 trên 61.
Thử thách
DễHãy đặt nền móng cho dự án Shape Drawer bằng cách tạo cấu trúc Shape cơ sở: một giao diện xác định những gì mọi hình dạng có thể làm thông qua các con trỏ hàm (function pointer).
Bạn sẽ tạo hai tệp để thiết lập hệ thống đa hình này:
shape.h: Định nghĩa giao diện cốt lõi tại đây. Trước tiên, tạo khai báo trước cho cấu trúcShape. Sau đó, định nghĩa hai kiểu con trỏ hàm:DrawFunc: nhận tham sốconst Shape*và không trả về giá trị nàoAreaFunc: nhận tham sốconst Shape*và trả về một giá trịdouble
Shape, trong đó có hai con trỏ hàm:draw(kiểuDrawFunc) vàarea(kiểuAreaFunc). Cấu trúc này chỉ đóng vai trò là giao diện. Nó không chứa dữ liệu riêng của hình dạng, chỉ chứa hành vi.main.c: Chứng minh giao diện hoạt động bằng cách tạo một hình dạng kiểm thử đơn giản. Triển khai hai hàm:test_draw: in raDrawing test shapetest_area: trả về42.0
Shape, kết nối nó với các hàm kiểm thử này, rồi gọi cả hai thông qua giao diện. In kết quả diện tích với một chữ số thập phân.
Kết quả đầu ra của bạn cần chứng minh rằng các con trỏ hàm hoạt động chính xác:
Drawing test shape
Area: 42.0Tại sao cần khai báo trước? Bạn có thể thắc mắc tại sao typedef struct Shape Shape; lại xuất hiện trước khi cấu trúc được định nghĩa đầy đủ. Điều này cần thiết vì DrawFunc và AreaFunc tham chiếu đến const Shape* trong kiểu tham số, nhưng tại thời điểm đó trong tệp, trình biên dịch chưa thấy định nghĩa đầy đủ của cấu trúc. Khai báo trước cho trình biên dịch biết: "có một cấu trúc tên là Shape", như vậy là đủ để dùng con trỏ trỏ đến cấu trúc đó. Định nghĩa đầy đủ sẽ xuất hiện sau. Đây là cách làm phổ biến trong C khi một cấu trúc cần tham chiếu đến chính nó, trực tiếp hoặc thông qua con trỏ hàm.
Điểm mấu chốt ở đây là Shape không biết gì về hình tròn hay hình chữ nhật. Nó chỉ biết rằng mọi hình dạng đều phải có khả năng tự draw và tính area của mình. Trong các bài học tiếp theo, bạn sẽ tạo những hình dạng cụ thể nhúng cấu trúc cơ sở này và cung cấp phần triển khai riêng. Nhớ dùng include guard trong tệp tiêu đề.
Tự làm thử
#include <stdio.h>
#include "shape.h"
// TODO: Triển khai hàm test_draw
// - Nhận một tham số const Shape*
// - In ra "Drawing test shape"
void test_draw(const Shape* shape) {
// TODO: In ra thông báo theo yêu cầu
}
// TODO: Triển khai hàm test_area
// - Nhận một tham số const Shape*
// - Trả về 42.0
double test_area(const Shape* shape) {
// TODO: Trả về giá trị diện tích dùng để kiểm thử
}
int main() {
// TODO: Tạo một instance của Shape
// TODO: Liên kết shape với các hàm test_draw và test_area
// TODO: Gọi draw thông qua giao diện
// TODO: Gọi area thông qua giao diện và in ra kết quả với một chữ số thập phân
// Định dạng: "Area: %.1f\n"
return 0;
}
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ả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ạng9Dự án: Trình vẽ hình
Tổng quan về dự ánTriển khai hình trònTriển khai hình chữ nhậtCách sử dụng đa hìnhBộ chứa hìnhTự luyện tập: Trình biên dịch C online