Bộ chứa hình
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 48 trên 61.
Thử thách
DễHãy cùng đưa dự án Shape Drawer đến hồi kết hoành tráng! Bạn sẽ tạo một vùng chứa hình dạng để lưu tập hợp gồm cả hình tròn và hình chữ nhật, sau đó duyệt qua chúng để tính tổng diện tích: đây là minh chứng cho sức mạnh thực sự của tính đa hình (polymorphism).
Dựa trên mọi thứ bạn đã tạo cho đến nay, dự án hoàn chỉnh sẽ bao gồm:
shape.hvàshape.c: Giao diện Shape cơ sở và hàmprocess_shape.circle.hvàcircle.c: Phần triển khai Circle, cùng hàm khởi tạo và phép tính diện tích.rectangle.hvàrectangle.c: Phần triển khai Rectangle, cùng hàm khởi tạo và phép tính diện tích.main.c: Đây là nơi mọi thứ diễn ra. Bạn sẽ tạo một mảng (array) các con trỏShape*có thể lưu bất kỳ kiểu hình dạng nào. Đưa vào mảng cả hình tròn lẫn hình chữ nhật, rồi lặp qua mảng để tính và hiển thị tổng diện tích của tất cả hình dạng.
Chương trình sẽ nhận các đầu vào sau:
- Số lượng hình dạng cần tạo
- Với mỗi hình dạng: một ký tự chỉ loại (
ccho hình tròn,rcho hình chữ nhật), theo sau là các kích thước của hình
Với mỗi hình dạng trong vùng chứa, hãy tự gọi draw và area thông qua con trỏ Shape* (shapes[i]->draw(shapes[i]), shapes[i]->area(shapes[i])), rồi cộng diện tích vào tổng đang tính. Không dùng process_shape trong shape.c ở đây: hàm này in thêm một dòng Area: cho mỗi hình dạng, nhưng dòng đó không có trong đầu ra mong đợi. Sau khi xử lý tất cả hình dạng, hãy in tổng diện tích với 2 chữ số thập phân theo định dạng Total Area: X.XX.
Ví dụ với các đầu vào 3, rồi c 5.0, r 4.0 3.0, c 2.0:
Drawing Circle with radius: 5.00
Drawing Rectangle with width: 4.00 and height: 3.00
Drawing Circle with radius: 2.00
Total Area: 103.11Ví dụ với các đầu vào 2, rồi r 6.0 4.0, r 3.0 2.0:
Drawing Rectangle with width: 6.00 and height: 4.00
Drawing Rectangle with width: 3.00 and height: 2.00
Total Area: 30.00Điểm mấu chốt là mảng của bạn lưu các con trỏ Shape*. Mảng không cần biết mỗi phần tử thực sự là hình tròn hay hình chữ nhật. Khi bạn duyệt qua mảng và gọi draw cùng area thông qua từng con trỏ, phần triển khai phù hợp sẽ tự động chạy dựa trên cách bạn tạo mỗi hình dạng. Đây là tính đa hình đang hoạt động: một vòng lặp, một giao diện, nhiều hành vi.
Hãy nhớ lưu vào mảng các con trỏ trỏ đến những thành viên Shape được nhúng trong các hình dạng cụ thể. Dùng 3.14159 làm giá trị π khi tính diện tích hình tròn.
Quan trọng: đọc ký tự chỉ loại hình dạng: Sau khi đọc số lượng hình dạng bằng scanf("%d", &n), mỗi lần đọc ký tự chỉ loại tiếp theo cần bỏ qua ký tự xuống dòng còn lại trong bộ đệm đầu vào. Thêm một dấu cách ở đầu chuỗi định dạng để làm việc này:
scanf(" %c", &type); // note the space before %cNếu không có dấu cách ở đầu, scanf sẽ đọc ký tự xuống dòng còn sót lại từ đầu vào trước đó thay vì ký tự c hoặc r như mong muốn. Khi đó, bước kiểm tra loại hình dạng sẽ âm thầm thất bại và không tạo ra đầu ra nào.
Tự làm thử
#include <stdio.h>
#include <stdlib.h>
#include "shape.h"
#include "circle.h"
#include "rectangle.h"
int main() {
// TODO: Đọc số lượng hình
// TODO: Cấp phát các mảng (array) cho hình tròn, hình chữ nhật và con trỏ Shape*
// TODO: Duyệt từng hình, đọc kiểu và kích thước của hình,
// tạo hình và lưu con trỏ trỏ đến phần cơ sở của hình vào mảng shapes
// TODO: Duyệt mảng shapes, gọi trực tiếp shapes[i]->draw(...) và
// shapes[i]->area(...) rồi cộng dồn tổng diện tích
// (không gọi process_shape vì hàm này in thêm một dòng Area)
// TODO: In tổng diện tích theo định dạng: Total Area: X.XX
// TODO: Giải phóng bộ nhớ đã cấp phát
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