Thực hành Thiết kế Hướng đối tượng với thừa kế và đa hình

Experiment 1: GradeCalc

 1 #pragma once
 2 
 3 #include <vector>
 4 #include <array>
 5 #include <string>
 6 
 7 class GradeCalc {
 8 public:
 9     GradeCalc(const std::string &ten_khoa_hoc);      
10     void nhap(int so_luong);                         // Nhập số_luong điểm
11     void xuat() const;                               // Xuất các điểm
12     void sap_xep(bool tang_dan = false);             // Sắp xếp (mặc định giảm dần)
13     int min() const;                                 // Trả về điểm thấp nhất
14     int max() const;                                 // Trả về điểm cao nhất
15     double trung_binh() const;                       // Trả về trung bình
16     void thong_tin();                                // Xuất thông tin về điểm của khóa học
17 
18 private:
19     void tinh_toan();                                 // Tính toán các thống kê điểm
20 
21 private:
22     std::string ten_khoa_hoc;                         // Tên khóa học
23     std::vector<int> diem;                            // Điểm của khóa học
24     std::array<int, 5> so_luong_diem;                // Số người trong từng đoạn điểm
25     std::array<double, 5> phan_tram;                 // Tỷ lệ phần trăm trong từng đoạn
26     bool danh dau;                                   // Danh dấu cho biết thông tin đã được cập nhật
27 };

GradeCalc.cpp:

 1 #include <algorithm>
 2 #include <array>
 3 #include <cstdlib>
 4 #include <iomanip>
 5 #include <iostream>
 6 #include <numeric>
 7 #include <string>
 8 #include <vector>
 9 #include "GradeCalc.hpp"
10 
11 GradeCalc::GradeCalc(const std::string& ten_khoa_hoc) : ten_khoa_hoc{ten_khoa_hoc}, danh_dau{true} {
12     so_luong_diem.fill(0);
13     phan_tram.fill(0.0);
14 }
15 
16 void GradeCalc::nhap(int so_luong) {
17     if (so_luong < 0) {
18         std::cerr << "Nhập không hợp lệ! Số lượng không thể là số âm.\n";
19         return;
20     }
21 
22     diem.reserve(so_luong);
23     int diem_so;
24     for (int i = 0; i < so_luong;) {
25         std::cin >> diem_so;
26         if (diem_so < 0 || diem_so > 100) {
27             std::cerr << "Nhập không hợp lệ! Điểm phải trong khoảng [0, 100].\n";
28             continue;
29         }
30         diem.push_back(diem_so);
31         ++i;
32     }
33     danh_dau = true;
34 }
35 
36 void GradeCalc::xuat() const {
37     for (auto diem : diem) {
38         std::cout << diem << ' ';
39     }
40     std::cout << std::endl;
41 }
42 
43 void GradeCalc::sap_xep(bool tang_dan) {
44     if (tang_dan) {
45         std::sort(diem.begin(), diem.end());
46     } else {
47         std::sort(diem.begin(), diem.end(), std::greater<int>());
48     }
49 }
50 
51 int GradeCalc::min() const {
52     if (diem.empty()) return -1;
53     auto it = std::min_element(diem.begin(), diem.end());
54     return *it;
55 }
56 
57 int GradeCalc::max() const {
58     if (diem.empty()) return -1;
59     auto it = std::max_element(diem.begin(), diem.end());
60     return *it;
61 }
62 
63 double GradeCalc::trung_binh() const {
64     if (diem.empty()) return 0.0;
65     double tb = std::accumulate(diem.begin(), diem.end(), 0.0) / diem.size();
66     return tb;
67 }
68 
69 void GradeCalc::thong_tin() {
70     if (danh_dau) tinh_toan();
71     std::cout << "Tên khóa học:\t" << ten_khoa_hoc << std::endl;
72     std::cout << "Trung bình:\t" << std::fixed << std::setprecision(2) << trung_binh() << std::endl;
73     std::cout << "Điểm cao nhất:\t" << max() << std::endl;
74     std::cout << "Điểm thấp nhất:\t" << min() << std::endl;
75 }
76 
77 void GradeCalc::tinh_toan() {
78     if (diem.empty()) return;
79     so_luong_diem.fill(0);
80     phan_tram.fill(0.0);
81     for (int diem_so : diem) {
82         if (diem_so < 60) ++so_luong_diem[0];
83         else if (diem_so < 70) ++so_luong_diem[1];
84         else if (diem_so < 80) ++so_luong_diem[2];
85         else if (diem_so < 90) ++so_luong_diem[3];
86         else ++so_luong_diem[4];
87     }
88     for (size_t i = 0; i < so_luong_diem.size(); ++i) {
89         phan_tram[i] = so_luong_diem[i] * 1.0 / diem.size();
90     }
91     danh_dau = false;
92 }

Task1.cpp:

 1 #include <iostream>
 2 #include <string>
 3 #include "GradeCalc.hpp"
 4 
 5 void test() {
 6     GradeCalc bc("Toan");
 7     std::cout << "Nhap diem:\n";
 8     bc.nhap(5);
 9     std::cout << "Xuat diem:\n";
10     bc.xuat();
11     std::cout << "Sap xep diem:\n";
12     bc.sap_xep();
13     bc.xuat();
14     std::cout << "*************Thong tin diem*************\n";
15     bc.thong_tin();
16 }
17 
18 int main() {
19     test();
20 }

Experiment 2: Inheritance vs Composition

 1 #pragma once
 2 
 3 #include <array>
 4 #include <string>
 5 #include <vector>
 6 
 7 class GradeCalc : private std::vector<int> {
 8 public:
 9     GradeCalc(const std::string &ten_khoa_hoc);      
10     void nhap(int so_luong);                        // Nhập số_luong điểm
11     void xuat() const;                              // Xuất các điểm
12     void sap_xep(bool tang_dan = false);            // Sắp xếp (mặc định giảm dần)
13     int min() const;                                // Trả về điểm thấp nhất
14     int max() const;                                // Trả về điểm cao nhất
15     double trung_binh() const;                      // Trả về trung bình
16     void thong_tin();                               // Xuất thông tin về điểm của khóa học
17 
18 private:
19     void tinh_toan();                               // Tính toán các thống kê điểm
20 
21 private:
22     std::string ten_khoa_hoc;                       // Tên khóa học
23     std::array<int, 5> so_luong_diem;              // Số người trong từng đoạn điểm
24     std::array<double, 5> phan_tram;               // Tỷ lệ phần trăm trong từng đoạn
25     bool danh_dau;                                 // Danh dấu cho biết thông tin đã được cập nhật
26 };

GradeCalc.cpp:

 1 #include <algorithm>
 2 #include <array>
 3 #include <cstdlib>
 4 #include <iomanip>
 5 #include <iostream>
 6 #include <numeric>
 7 #include <string>
 8 #include <vector>
 9 #include "GradeCalc.hpp"
10 
11 GradeCalc::GradeCalc(const std::string& ten_khoa_hoc) : ten_khoa_hoc(ten_khoa_hoc), danh_dau(true) {
12     so_luong_diem.fill(0);
13     phan_tram.fill(0.0);
14 }
15 
16 void GradeCalc::nhap(int so_luong) {
17     if (so_luong < 0) {
18         std::cerr << "Nhập không hợp lệ! Số lượng không thể là số âm.\n";
19         return;
20     }
21     this->reserve(so_luong);
22     int diem_so;
23     for (int i = 0; i < so_luong;) {
24         std::cin >> diem_so;
25         if (diem_so < 0 || diem_so > 100) {
26             std::cerr << "Nhập không hợp lệ! Điểm phải trong khoảng [0, 100].\n";
27             continue;
28         }
29         this->push_back(diem_so);
30         ++i;
31     }
32     danh_dau = true;
33 }
34 
35 void GradeCalc::xuat() const {
36     for (auto diem : *this) {
37         std::cout << diem << ' ';
38     }
39     std::cout << std::endl;
40 }
41 
42 void GradeCalc::sap_xep(bool tang_dan) {
43     if (tang_dan) {
44         std::sort(this->begin(), this->end());
45     } else {
46         std::sort(this->begin(), this->end(), std::greater<int>());
47     }
48 }
49 
50 int GradeCalc::min() const {
51     if (this->empty()) return -1;
52     return *std::min_element(this->begin(), this->end());
53 }
54 
55 int GradeCalc::max() const {
56     if (this->empty()) return -1;
57     return *std::max_element(this->begin(), this->end());
58 }
59 
60 double GradeCalc::trung_binh() const {
61     if (this->empty()) return 0.0;
62     double tb = std::accumulate(this->begin(), this->end(), 0.0) / this->size();
63     return tb;
64 }
65 
66 void GradeCalc::thong_tin() {
67     if (danh_dau) tinh_toan();
68     std::cout << "Tên khóa học:\t" << ten_khoa_hoc << std::endl;
69     std::cout << "Trung bình:\t" << std::fixed << std::setprecision(2) << trung_binh() << std::endl;
70     std::cout << "Điểm cao nhất:\t" << max() << std::endl;
71     std::cout << "Điểm thấp nhất:\t" << min() << std::endl;
72 }
73 
74 void GradeCalc::tinh_toan() {
75     if (this->empty()) return;
76     so_luong_diem.fill(0);
77     phan_tram.fill(0.0);
78     for (int diem_so : *this) {
79         if (diem_so < 60) ++so_luong_diem[0];
80         else if (diem_so < 70) ++so_luong_diem[1];
81         else if (diem_so < 80) ++so_luong_diem[2];
82         else if (diem_so < 90) ++so_luong_diem[3];
83         else ++so_luong_diem[4];
84     }
85     for (size_t i = 0; i < phan_tram.size(); ++i) {
86         phan_tram[i] = so_luong_diem[i] * 1.0 / this->size();
87     }
88     danh_dau = false;
89 }

Experiment 3: Polymorphism with Shapes

 1 #pragma once
 2 
 3 #include <string>
 4 #include <vector>
 5 
 6 enum class Hinh { tron, tam_giac, hinh_vuong };
 7 
 8 class Hinh {
 9 public:
10     virtual void ve() = 0;
11     virtual ~Hinh() = default;
12 };
13 
14 class Tron : public Hinh {
15 public:
16     void ve() override;
17 };
18 
19 class TamGiac : public Hinh {
20 public:
21     void ve() override;
22 };
23 
24 class HinhVuong : public Hinh {
25 public:
26     void ve() override;
27 };
28 
29 class BanVinh {
30 public:
31     void them(const std::string& loai_hinh);
32     void ve_tat_ca() const;
33     ~BanVinh();
34 
35 private:
36     std::vector<Hinh*> hinh;
37 };
38 
39 Hinh* tao_hinh(const std::string& loai);
40 Hinh::HinhType str_to_HinhType(const std::string& s);

Hinh.cpp:

 1 #include <algorithm>
 2 #include <cctype>
 3 #include <iostream>
 4 #include <string>
 5 
 6 #include "Hinh.hpp"
 7 
 8 void Tron::ve() { std::cout << "Vẽ một hình tròn...\n"; }
 9 void TamGiac::ve() { std::cout << "Vẽ một tam giác...\n"; }
10 void HinhVuong::ve() { std::cout << "Vẽ một hình vuông...\n"; }
11 
12 void BanVinh::them(const std::string& loai_hinh) {
13     Hinh* h = tao_hinh(loai_hinh);
14     if (h) hinh.push_back(h);
15 }
16 
17 void BanVinh::ve_tat_ca() const {
18     for (Hinh* h : hinh) h->ve();
19 }
20 
21 BanVinh::~BanVinh() {
22     for (Hinh* h : hinh) delete h;
23 }
24 
25 Hinh* tao_hinh(const std::string& loai) {
26     switch (str_to_HinhType(loai)) {
27     case Hinh::tron: return new Tron;
28     case Hinh::tam_giac: return new TamGiac;
29     case Hinh::hinh_vuong: return new HinhVuong;
30     default: return nullptr;
31     }
32 }
33 
34 Hinh::HinhType str_to_HinhType(const std::string& s) {
35     std::string t = s;
36     std::transform(s.begin(), s.end(), t.begin(), [](unsigned char c) { return std::tolower(c); });
37     if (t == "tron") return Hinh::tron;
38     if (t == "tam_giac") return Hinh::tam_giac;
39     if (t == "hinh_vuong") return Hinh::hinh_vuong;
40     return Hinh::tron;
41 }

Experiment 4: Toy Factory

 1 #ifndef CAYXUCXICH_HPP
 2 #define CAYXUCXICH_HPP
 3 
 4 #include <string>
 5 
 6 class CayXucXich {
 7 protected:
 8     std::string ten;
 9     std::string material;
10     std::string loai;
11     std::string am_thanh;
12 
13 public:
14     CayXucXich(const std::string& n, const std::string& m, const std::string& t, const std::string& s);
15     virtual ~CayXucXich() = default;
16 
17     virtual void hoat_dong() const = 0;
18     void phat_am_thanh() const;
19     void hien_thi_thong_tin() const;
20     std::string getTen() const;
21     std::string getMaterial() const;
22     std::string getLoai() const;
23     std::string getAmThanh() const;
24 };
25 
26 #endif

CayXucXich.cpp:

 1 #include "CayXucXich.hpp"
 2 #include <iostream>
 3 
 4 CayXucXich::CayXucXich(const std::string& n, const std::string& m, const std::string& t, const std::string& s)
 5     : ten(n), material(m), loai(t), am_thanh(s) {}
 6 
 7 void CayXucXich::phat_am_thanh() const {
 8     std::cout << "Phát tiếng: " << am_thanh << std::endl;
 9 }
10 
11 void CayXucXich::hien_thi_thong_tin() const {
12     std::cout << ten << "\t" << material << "\t" << loai << "\t" << am_thanh << std::endl;
13 }
14 
15 std::string CayXucXich::getTen() const { return ten; }
16 std::string CayXucXich::getMaterial() const { return material; }
17 std::string CayXucXich::getLoai() const { return loai; }
18 std::string CayXucXich::getAmThanh() const { return am_thanh; }

Factory Implementation

 1 #ifndef TOYFACTORY_HPP
 2 #define TOYFACTORY_HPP
 3 
 4 #include <vector>
 5 #include <string>
 6 #include "CayXucXich.hpp"
 7 
 8 class CayXucXichFactory {
 9 private:
10     std::vector<CayXucXich*> cay;
11 
12 public:
13     ~CayXucXichFactory();
14     
15     bool them_cay(CayXucXich* c);
16     bool xoa_cay(const std::string& ten);
17     
18     void hien_thi_tat_ca() const;
19     void phat_tat_ca_am_thanh() const;
20     void thuc_hien_tat_ca_hoat_dong() const;
21     
22     int getSoLuongCay() const;
23 };
24 
25 #endif

CayXucXichFactory.cpp:

 1 #include "CayXucXichFactory.hpp"
 2 #include <iostream>
 3 #include <algorithm>
 4 
 5 CayXucXichFactory::~CayXucXichFactory() {
 6     for (CayXucXich* c : cay) {
 7         delete c;
 8     }
 9 }
10 
11 bool CayXucXichFactory::them_cay(CayXucXich* c) {
12     cay.push_back(c);
13     std::cout << "Thành công thêm cay: " << c->getTen() << std::endl;
14     return true;
15 }
16 
17 bool CayXucXichFactory::xoa_cay(const std::string& ten) {
18     for (auto it = cay.begin(); it != cay.end(); ++it) {
19         if ((*it)->getTen() == ten) {
20             delete *it;
21             cay.erase(it);
22             std::cout << "Xóa thành công.\n";
23             return true;
24         }
25     }
26     return false;
27 }
28 
29 void CayXucXichFactory::hien_thi_tat_ca() const {
30     std::cout << "Thông tin về các cay:" << std::endl;
31     for (const CayXucXich* c : cay) {
32         c->hien_thi_thong_tin();
33     }
34 }
35 
36 void CayXucXichFactory::phat_tat_ca_am_thanh() const {
37     for (const CayXucXich* c : cay) {
38         c->phat_am_thanh();
39     }
40 }
41 
42 void CayXucXichFactory::thuc_hien_tat_ca_hoat_dong() const {
43     for (const CayXucXich* c : cay) {
44         c->hoat_dong();
45     }
46 }
47 
48 int CayXucXichFactory::getSoLuongCay() const {
49     return cay.size();
50 }

Thẻ: C++ Thừa Kế Đa hình Mẫu Factory Thiết Kế Hướng Đối Tượng

Đăng vào ngày 23 tháng 6 lúc 07:32