[Học OOP] Bài 9: Hiểu kế thừa như thế nào cho đúng trong hướng đối tượng (Phần 2)

Kế thừa trong lập trình hướng đối tượng bao gồm rất nhiều vấn đề quan trọng cần chú ý, bài viết này sẽ chú trọng đến một số lỗi hiểu sai vấn đề khi các bạn làm các bài tập dạng này.

Lấy bài tập sau đây để phân tích vấn đề:

1. Đề bài hướng đối tượng minh họa

Xây dựng lớp Học Sinh, Giáo Viên và một số class khác nếu cần. Hãy viết các hàm/phương thức phù hợp cho phép nhập xuất thông tin của các đối tượng trên. Tất nhiên phải đầy đủ các thông tin cơ bản như, họ tên, ngày sinh (Ngày sinh phải được tổ chức là một class), Học sinh phải có lớp, mã học sinh, tương tự giáo viên cũng có các thông tin phù hợp như mã GV, trình độ giảng dạy,…

Sử dụng tính kế thừa trong lập trình hướng đối tượng để giải quyết bài toán trên.

2. Phân tích bài toán

Bài toán bên trên yêu cầu chúng ta sử dụng tính kế thừa trong lập trình hướng đối tượng nên chúng ta sẽ dễ dàng nhận ra giữa giaoVien và hocSinh có những điểm chung về thuộc tính như hoten, ngaysinh,… Đây là mối quan hệ đặc biệt hóa, tổng quát hóa , trong đó giaoVien  Người, hocSinh Người. Như vậy chúng ta sẽ xây dựng thêm 1 class conNguoi để 2 class giaoVien và hocSinh kế thừa.

Chúng ta cùng theo dõi bài giải dưới đây:

File ngay.h

#pragma once
class ngay
{
protected:
    int d, m, y;

public:
    ngay();
    ngay(int D, int M, int Y);
    void xuat();
    void nhap();
    ~ngay();
};

File conNguoi.h

#pragma once
#include "ngay.h"
#include <string>
#include <iostream>
using namespace std;

class conNguoi: public ngay
{
protected:
    string hoten;

public:
    conNguoi();
    void nhap()
    {
        cout << "Nhap ten: "; getline(cin,hoten);
        cout << "Nhap ngay sinh: ";
        ngay::nhap();
    }
    void xuat();
    ~conNguoi();
};

File hocSinh.h

#pragma once
#include "conNguoi.h"
#include <string>
#include <iostream>
using namespace std;
class hocSinh : public conNguoi
{
protected:
    int mahs;
    string lop;

public:
    hocSinh();
    void nhap()
    {
        cout << "Nhap thong tin hoc sinh: \n";
        conNguoi::nhap();
        cout << "Nhap ma HS: "; cin >> mahs;
        cout << "Nhap lop: "; getline(cin, lop);
    }
    void xuat();
    ~hocSinh();
};

File giaoVien.h

#pragma once
#include "conNguoi.h"
#include <string>
#include <iostream>
using namespace std;
class giaoVien : public conNguoi
{
protected:
    int magv;
    string trinhdo;

public:
    giaoVien();
    void nhap()
    {
        cout << "Nhap thong tin giao vien: \n";
        conNguoi::nhap();
        cout << "Nhap ma GV: "; cin >> magv;
        cout << "Nhap trinh do giang day: "; getline(cin, trinhdo);
    }
    void xuat();
    ~giaoVien();
};

Nhận xét

Các bạn chú ý vào file conNguoi.h những dòng mình tô màu class conNguoi: public ngay lớp con người kế thừa lớp ngày, điều này có ổn không??? Ở class Con người, GV và HS vẫn có nhập được ngày sinh, chương trình vẫn chạy và cho kết quả chính xác, như vậy liệu có đúng không?

Câu trả lời là không, bạn có thể làm đúng kết quả nhưng hiểu sai vấn đề. Mình đưa ví dụ này vào vì trên thực tế phần lớn nhiều bạn vẫn sai ở trường hợp này.

Trong bài này mình phải hiểu rằng “class Con người có chứa ngày sinh, chứ không phải con người ngày sinh”, Như vậy với mối quan hệ quan hệ đặc biệt hóa, tổng quát hóa để xác định cái nào kế thừa, cái nào chứa thì mình cần đặt câu hỏi: Con người có chứa ngày sinh, họ tên không? Học sinh và giáo viên có là con người không? Trả lời được những câu hỏi trên sẽ giúp bạn phần nào định hình lại suy nghĩ của mình chính xác khi áp dụng kế thừa hay không.

3. Lời giải bài tập oop

Sơ đồ class bài tập mẫu về kế thừa trong hướng đối tượng

Sơ đồ class bài tập mẫu về kế thừa trong hướng đối tượng

File ngay.h

#pragma once
#include <iostream>
using namespace std;
class ngay
{
protected:
    int d, m, y;

public:
    ngay();
    ngay(int D, int M, int Y);
    void xuat();
    void nhap();
    ~ngay();
};

 

File ngay.cpp

#include "ngay.h"

ngay::ngay()
{ 
    d = m = y = 0;
}

ngay::ngay(int D, int M, int Y)
{
    d = D;
    m = M;
    y = Y;
}

void ngay::xuat()
{
    cout << d << "/" << m << "/" << y << endl;
}

void ngay::nhap()
{
    cout << "Nhap lan luot ngay, thang, nam: ";
    cin >> d >> m >> y;
}

ngay::~ngay()
{
}

 

File conNguoi.h

#pragma once
#include "ngay.h"
#include <string>
#include <iostream>
using namespace std;

class conNguoi
{
protected:
    string hoten;
    ngay ngaysinh;
public:
    conNguoi();
    void nhap();
    void xuat();
    ~conNguoi();
};

 

File conNguoi.cpp

#include "conNguoi.h"

conNguoi::conNguoi()
{
}

void conNguoi::nhap()
{
    cout << "Nhap ten: "; getline(cin, hoten);
    cout << "Nhap ngay sinh: ";
    ngaysinh.nhap();
}

void conNguoi::xuat()
{
    cout << "Ho ten: " << hoten << endl;
    cout << "Ngay sinh: ";
    ngaysinh.xuat();
}

conNguoi::~conNguoi()
{
}

 

File giaoVien.h

#pragma once
#include "conNguoi.h"
#include <string>
#include <iostream>
using namespace std;
class giaoVien : public conNguoi
{
protected:
    int magv;
    string trinhdo;

public:
    giaoVien();
    void nhap();
    void xuat();
    ~giaoVien();
};

 

File giaoVien.cpp

#include "giaoVien.h"

giaoVien::giaoVien()
{
}

void giaoVien::nhap()
{
    cout << "Nhap thong tin giao vien: \n";
    conNguoi::nhap();
    cout << "Nhap ma GV: "; cin >> magv;
    cout << "Nhap trinh do giang day: "; getline(cin, trinhdo);
}

void giaoVien::xuat()
{
    cout << "Thong tin giao vien: \n";
    conNguoi::xuat();
    cout << "Ma GV: " << magv << endl;
    cout << "trinh do giang day: " << trinhdo << endl;
}

giaoVien::~giaoVien()
{
}

 

File hocSinh.h

#pragma once
#include "conNguoi.h"
#include <string>
#include <iostream>
using namespace std;
class hocSinh : public conNguoi
{
protected:
    int mahs;
    string lop;

public:
    hocSinh();
    void nhap();
    void xuat();
    ~hocSinh();
};

 

File hocSinh.cpp

#include "hocSinh.h"

hocSinh::hocSinh()
{
}

void hocSinh::nhap()
{
    cout << "Nhap thong tin hoc sinh: \n";
    conNguoi::nhap();
    cout << "Nhap ma HS: "; cin >> mahs;
    cout << "Nhap lop: "; getline(cin, lop);
}

void hocSinh::xuat()
{
    cout << "Thong tin HS: \n";
    conNguoi::xuat();
    cout << "Ma HS: " << mahs << endl;
    cout << "Lop: " << lop << endl;
}


hocSinh::~hocSinh()
{
}

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *