30/09/2018, 16:38

Làm thế nào để xác định chính xác thuộc tính của các đối tượng?

Chào mọi người. Mình đang học hướng đối tượng, gặp bài toán sau mà không biết minh xây dựng các lớp có đúng không nữa. Nhờ mọi người kiểm tra giúp mình với. Đề bài:

Mùa hè lại đến, công viên văn hóa Đầm Sen hân hoan đón chào các em thiếu nhi , các bạn học sinh, sinh viên và toàn thể quí khách đến tham quan và tham dự các trò chơi kì thú và hấp dẫn. Giả sử trên mỗi chiếc vé mà công viên phát hành, đều có ghi lại mã vé(chuỗi), họ tên người chủ vé(chuỗi), năm sinh của người đó (số nguyên) và số trò chơi mà người đó tham dự(số nguyên). Để phục vụ tối đa cho lợi ích khách hàng, công viên phát hành 2 loại vé là vé trọn gói và vé từng phần. Giá vé trọn gói có thể chơi tất cả 30 trò chơi có trong công viên. Đối với gói từng phần, giá vé là 70.000VNĐ (giá vé vào cổng), khi người chơi tham dự một trò chơi nào thì cần trả thêm 20.000 VNĐ cho một trò chơi.

Mình thiết lập các lớp như sau:

//Dinh nghia lop ve
class Ve
{
protected:
    string MaVe;
    string HoTenChuVe;
    string NamSinhChuVe;
    unsigned long GiaTien;
    int SoTroChoi;
public:
    virtual void Nhap();
    virtual void Xuat();
    virtual unsigned long TinhTien();
};
//Dinh nghia lop Ve Tron Goi
class VeTronGoi: public Ve
{
public:
    void Nhap();
    void Xuat();
    virtual unsigned long TinhTien();
};
// Dinh nghia lop Ve Tung Phan
class VeTungPhan: public Ve
{
public:
    void Nhap();
    void Xuat();
    unsigned long TinhTien();
};
... viết 18:39 ngày 30/09/2018
năm sinh của người đó (số nguyên)

Năm sinh thì để cho nó kiểu unsigned int cũng được rồi.

Chú ý khi tạo một lớp nên có constructor và destructor (mặc dù không có thành phần nào cần giải phóng một cách thủ công) cho nó phong thủy. Giả sử khi bạn dùng constructor cho lớp Vé trọn gói, thì ngay khi khai báo đối tượng nó sẽ mang giá trị số trò chơi là 30, và giá tiền quy định trước luôn, đỡ phải mất công setup cho nó. Còn vé từng phần thì constructor khởi tạo theo kiểu mà bạn quy định thế nào đó.

BaoLe viết 18:49 ngày 30/09/2018

Khi mình khai báo lớp Ve có thuộc tính GiaTien, nhưng trong phương thức Nhap của lớp Ve mình không nhập thông tin của giá tiền mà để phương thức Nhap của lớp VeTronGoi và lớp VeTungPhan thực hiện việc này thì có được không vậy @nguyenchiemminhvu

... viết 18:47 ngày 30/09/2018

Nhập trước hay nhập sau thì cũng như nhau thôi. Nếu bạn không có ý định sử dụng lớp Ve sau này thì làm thế cũng được. Không thì cho nó cái giá trị là 70000 VNĐ từ ban đầu coi như vé vào cửa. Còn lớp kế thừa của nó thì chỉnh lại sau.

BaoLe viết 18:41 ngày 30/09/2018

Để mình làm rồi post bạn kiểm tra zùm nha?

BaoLe viết 18:44 ngày 30/09/2018

Mới làm xong, nhờ mọi người cho nhận xét.

#include<iostream>
#include<string>
#include<vector>

using namespace std;
//Dinh nghia lop ve
class Ve {
protected:
    string MaVe;
    string HoTenChuVe;
    string NamSinhChuVe;
    unsigned long GiaTien;
    int SoTroChoi;
public:
    virtual void Nhap();
    virtual void Xuat();
    virtual unsigned long TinhTien() = 0;
    virtual int SoTroChoi1() = 0;
};

void Ve::Nhap() {
    cout << "Nhap ma ve: ";
    cin.ignore();
    getline(cin, MaVe);
    cout << "Nha ho va ten cua chu ve: ";
    cin.ignore();
    getline(cin, HoTenChuVe);
    cout << "Nhap nam sinh cua chu ve: ";
    cin.ignore();
    getline(cin, NamSinhChuVe);
}

void Ve::Xuat() {
    cout << "Ma ve: " << MaVe << endl;
    cout << "Ho ten chu ve: " << HoTenChuVe << endl;
    cout << "Nam sinh cua chu ve: " << NamSinhChuVe << endl;
}

//Dinh nghia lop Ve Tron Goi
class VeTronGoi: public Ve {
public:
    void Nhap();
    void Xuat();
    unsigned long TinhTien();
    int SoTroChoi1();
};

void VeTronGoi::Nhap() {
    Ve::Nhap();
    SoTroChoi = 30;
    GiaTien = 200000;
}

void VeTronGoi::Xuat() {
    Ve::Xuat();
    cout << "Gia tien: " << GiaTien << "VND" << endl;
    cout << "So tro choi: " << SoTroChoi << endl;
}

unsigned long VeTronGoi::TinhTien() {
    return GiaTien;
}

int VeTronGoi::SoTroChoi1() {
    return SoTroChoi;
}
// Dinh nghia lop Ve Tung Phan
class VeTungPhan: public Ve {
public:
    void Nhap();
    void Xuat();
    unsigned long TinhTien();
    int SoTroChoi1();
};

void VeTungPhan::Nhap() {
    Ve::Nhap();
    GiaTien = 70000;
    cout << "Nhap so tro choi: ";
    cin >> SoTroChoi;
}

void VeTungPhan::Xuat() {
    Ve::Xuat();
    cout << "Gia tien: " << GiaTien << "VND" << endl;
    cout << "So tro choi: " << SoTroChoi << endl;
}

unsigned long VeTungPhan::TinhTien() {
    return GiaTien;
}

int VeTungPhan::SoTroChoi1() {
    return SoTroChoi;
}
class CongVien {
private:
    vector<Ve*> DanhSachVe;
public:
    void Nhap();
    void Xuat();
    unsigned int SoVeTungPhan();
    unsigned long TongTien();
};

void CongVien::Nhap() {
    cout << "         NHAP THONG TIN:         " << endl;
    int LuaChon = 0;
    do {
        do {
            cout << "1.Nhap du lieu cho ve tron goi." << endl;
            cout << "2.Nhap du lieu cho ve tung phan." << endl;
            cout << "3.Ket thuc." << endl;
            cout << "Nhap lua chon cua ban: ";
            cin >> LuaChon;
            if(LuaChon != 1 && LuaChon != 2 && LuaChon != 3)
                cout << "Lua chon ban da nhap khong hop le.Xin moi nhap lai." << endl;
        } while(LuaChon != 1 && LuaChon !=2 && LuaChon != 3);
        Ve* x = NULL;
        if(LuaChon == 1) {
            x = new VeTronGoi;
            x->Nhap();
            DanhSachVe.push_back(x);
        } else if(LuaChon == 2) {
            x = new VeTungPhan;
            x -> Nhap();
            DanhSachVe.push_back(x);
        }
    } while(LuaChon != 3);
}

void CongVien::Xuat() {
    cout << "          DANH SACH VE:          " << endl;
    for(int i = 0; i < DanhSachVe.size(); i++) {
        cout << "Thong tin ve " << i + 1 << ":" << endl;
        DanhSachVe[i] -> Xuat();
    }
}

unsigned int CongVien::SoVeTungPhan() {
    unsigned int dem = 0;
    for(int i = 0; i < DanhSachVe.size(); i++)
        if(DanhSachVe[i] -> TinhTien() == 70000)
            dem++;
    return dem;
}

unsigned long CongVien::TongTien() {
    unsigned long TongTien = 0;
    for(int i = 0; i < DanhSachVe.size(); i++) {
        if(DanhSachVe[i] -> TinhTien()) {
            TongTien = TongTien + 70000 + DanhSachVe[i]->SoTroChoi1() * 20000;
        } else {
            TongTien = TongTien + 200000;
        }
    }
    return TongTien;
}
int main() {
    CongVien x;
    x.Nhap();
    x.Xuat();
    cout << '\n';
    cout << "Tong so tien thu duoc tu viec ban ve: " << x.TongTien() << "VND" << endl;
    cout << "Tong so ve tung phan da ban duoc: " << x.SoVeTungPhan() << endl;
    return 0;
}
... viết 18:50 ngày 30/09/2018

Mình nghĩ trong lớp công viên nên thay phần nhập ở chổ chọn vé trọn gói hay vé từng phần, bằng cách thêm 1 thuộc tính kiểu bool có tên là is_total. Như thế khi bạn cho khách hàng chọn, bạn chỉ cần in ra dòng

cout << "Chon ve toan phan (1) hoac ve tung phan (0): ";
cin >> is_total;

sẽ ngắn gọn hơn rất nhiều, sau này muốn xử lý trên trường đó cũng dễ hơn. Thuộc tính là thứ gắn liền với đối tượng ngay từ khi mới tạo ra.

Bài liên quan
0