Đề cương OOP Lập trình hướng đối tượng – ĐẠI HỌC QUÞC GIA TH¿NH PHÞ HÞ CHÕ MINH ĐẠI HỌC C‘NG NGHỆ – StuDocu

ĐẠI HỌC QUÞC GIA TH¿NH PHÞ HÞ CHÕ MINH

ĐẠI HỌC C‘NG NGHỆ TH‘NG TIN

– – – ú  û – – –

ĐÀ C ̄¡NG ÔN TÀP

Môn: OOP – Lập trình h°ớng đối t°ợng

Đặng Minh Tuấn – 20522106 – HTTT

N⌀i dung

  • CÂU 1.
    • [2013-2014]
      • Giải:
    • [2014-2015]
      • Giải:
    • [2015-2016]
      • Giải:
    • [2016-2017]
      • Giải:
    • [2017-2018]
      • Giải:
    • [2018-2019]
      • Giải:
    • [2019-2020]
      • Giải:
  • CÂU 2.
    • [2013-2014]
      • Giải:
    • [2014-2015]
      • Giải:
    • [2015-2016]
      • Giải:
    • [2016-2017]
      • Giải:
    • [2017-2018]
      • Giải:
    • [2018-2019]
      • Giải:
    • [2019-2020]
      • Giải:
  • CÂU 3.
    • [2013-2014]
      • Giải:
    • [2014-2015]
      • Giải:
    • [2015-2016]
      • Giải:
    • [2016-2017]
      • Giải:
    • [2017-2018]
      • Giải:
    • [2018-2019]
      • Giải:
    • [2019-2020]
      • Giải:

CÂU 1.

[2013-2014]

HK

a. Phân biệt các phạm vi truy cập private, protected, public và cho ví dụ
minh họa.

b. Nêu khái niệm về sự kế thừa và những °u điểm của kế thừa trong việc lập
trình. Cho ví dụ minh họa.

HK

a. Nêu khái niệm Constructor và Destructor. Phân biệt Constructor mặc định
và Constructor khác.

b. Phân biệt các kiểu kế thừa private, protected, public.

Giải:
HK

a.

  • Thành phần private á lớp cha thì không truy xuất đ°ợc á lớp con

  • Kế thừa public: Lớp con kế thừa public từ lớp cha thì các thành phần protected của
    lớp cha trá thành protected của lớp con, các thành phần public của lớp cha trá thành
    public của lớp con.

  • Kế thừa private: Lớp con kế thừa private từ lớp cha thì các thành phần protected
    và public của lớp cha trá thành private của lớp con.

  • Kế thừa protected: Lớp con kế thừa protected từ lớp cha thì các thành phần
    protected và public của lớp cha trá thành protected của lớp con.

b.

  • Khái niệm:

K¿ thừa trong lÁp trình là cách 1 lớp có thể thừa h°ởng lại những thuộc tính,
ph°¢ng thức từ 1 lớp khác
và sử dụng chúng nh° là của bản thân mình.

Một định nghĩa trừu t°ợng h¡n về kế thừa: là một đặc điểm của ngôn ngữ h°ớng đối
t°ợng dùng để biểu diễn mối quan hệ đặc biệt hoá – tổng quát hoá giữa các lớp.

  • ̄u điểm:

  • Cho phép xây dựng 1 lớp mới từ lớp đã có.
    ▪ Lớp mới gọi là lớp con (subclass) hay lớp d¿n xuất (derived class).
    ▪ Lớp đã có gọi là lớp cha (superclass) hay lớp c¢ sở (base class).

  • Cho phép chia sẻ các thông tin chung nhằm tái sử dụng và đồng thßi giúp ta
    dễ dàng nâng cấp, dễ dàng bảo trì.

  • Định nghĩa sự t°¡ng thích giữa các lớp, nhß đó ta có thể chuyển kiểu tự động.
    HK

a.

  • Khái niệm:

Ph°¢ng thức khởi tạo (Constructor) là một ph°¡ng thức đặc biệt đ°ợc gọi tự động
tại thßi điểm đối t°ợng đ°ợc tạo. Các hàm khái tạo có nhiệm vụ khái tạo thông tin
ban đầu cho các đối t°ợng thuộc về lớp ngay khi đối t°ợng đ°ợc khai báo.

Ph°¢ng thức phá hủy (Destructor) có nhiệm vụ dọn dẹp <xác chết= của đối t°ợng
khi đối t°ợng <đi bán muối=. Nói một cách khác, ph°¡ng thức phá hủy có nhiệm vụ
thu hồi lại tất cả các tài nguyên đã cấp phát cho đối t°ợng khi đối t°ợng hết phạm vi
hoạt động.

  • Constructor mặc định khác với các Constructor khác á các điểm:

  • Không có tham số đầu vào.

b.

  • Thành phần private á lớp cha thì không truy xuất đ°ợc á lớp con

  • Kế thừa public: Lớp con kế thừa public từ lớp cha thì các thành phần protected của
    lớp cha trá thành protected của lớp con, các thành phần public của lớp cha trá thành
    public của lớp con.

  • Kế thừa private: Lớp con kế thừa private từ lớp cha thì các thành phần protected
    và public của lớp cha trá thành private của lớp con.

  • Kế thừa protected: Lớp con kế thừa protected từ lớp cha thì các thành phần
    protected và public của lớp cha trá thành protected của lớp con.

[2014-2015]

HK

Phân biệt các kiểu kế thừa private, protected, public (2 điểm)

Giải:
HK
  • Thành phần private á lớp cha thì không truy xuất đ°ợc á lớp con

  • Kế thừa public: Lớp con kế thừa public từ lớp cha thì các thành phần protected của
    lớp cha trá thành protected của lớp con, các thành phần public của lớp cha trá thành
    public của lớp con.

  • Kế thừa private: Lớp con kế thừa private từ lớp cha thì các thành phần protected
    và public của lớp cha trá thành private của lớp con.

  • Kế thừa protected: Lớp con kế thừa protected từ lớp cha thì các thành phần
    protected và public của lớp cha trá thành protected của lớp con.

[2015-2016]

HK

a. Phân biệt các kiểu kế thừa private, protected, public. (1 điểm)
b. Trình bày các đặc điểm quan trọng của lập trình h°ớng đối t°ợng. (1 điểm)

HK

a. Định nghĩa constructor (ph°¡ng thức khái tạo) và default constructor
(ph°¡ng thức khái tạo mặc định) (1 điểm)
b. Phân biệt các kiểu kế thừa private, protected, public (1 điểm)

Giải:
HK

a.

  • Thành phần private á lớp cha thì không truy xuất đ°ợc á lớp con

  • Kế thừa public: Lớp con kế thừa public từ lớp cha thì các thành phần protected của
    lớp cha trá thành protected của lớp con, các thành phần public của lớp cha trá thành
    public của lớp con.

  • Kế thừa private: Lớp con kế thừa private từ lớp cha thì các thành phần protected
    và public của lớp cha trá thành private của lớp con.

  • Kế thừa protected: Lớp con kế thừa protected từ lớp cha thì các thành phần
    protected và public của lớp cha trá thành protected của lớp con.

b.

  • Trừu t°ợng hóa – Abstraction Cách nhìn khái quát hóa về một tập các đối t°ợng
    có chung các đặc điểm đ°ợc quan tâm (và bỏ qua những chi tiết không cần thiết).

  • Đóng gói – Encapsulation Nhóm những gì có liên quan với nhau vào làm một, để
    sau này có thể dùng một cái tên để gọi đến. Vd: các hàm/ thủ tục đóng gói các câu
    lệnh, các đối t°ợng đóng gói dữ liệu của chúng và các thủ tục có liên quan.

  • Thừa kế – Inheritance cho phép một lớp D có đ°ợc các thuộc tính và thao tác của
    lớp C, nh° thể các thuộc tính và thao tác đó đã đ°ợc định nghĩa tại lớp D. Cho phép
    cài đặt nhiều quan hệ giữa các đối t°ợng: Đặc biệt hóa – Tổng quát hóa.

  • Đa hình – Polymorphism Là c¡ chế cho phép một tên thao tác hoặc thuộc tính có
    thể đ°ợc định nghĩa tại nhiều lớp và có thể có nhiều cài đặt khác nhau tại mỗi lớp
    trong các lớp đó.

HK

a.

Ph°¢ng thức khởi tạo (Constructor) là một ph°¡ng thức đặc biệt đ°ợc gọi tự động
tại thßi điểm đối t°ợng đ°ợc tạo. Các ph°¡ng thức khái tạo có nhiệm vụ khái tạo
thông tin ban đầu cho các đối t°ợng thuộc về lớp ngay khi đối t°ợng đ°ợc khai báo.

Ph°¢ng thức khởi tạo mặc định (Default Constructor) là ph°¡ng thức thiết lập
các thông tin ban đầu cho đối t°ợng thuộc về lớp bằng những giá trị mặc định. Khi
sử dụng một constructor, nếu không có giá trị khái tạo nào do ng°ßi dùng cung cấp
đ°ợc truyền cho constructor này, thì constructor mặc định sẽ đ°ợc gọi.

b.

  • Thành phần private á lớp cha thì không truy xuất đ°ợc á lớp con

  • Kế thừa public: Lớp con kế thừa public từ lớp cha thì các thành phần protected của
    lớp cha trá thành protected của lớp con, các thành phần public của lớp cha trá thành
    public của lớp con.

  • Kế thừa private: Lớp con kế thừa private từ lớp cha thì các thành phần protected
    và public của lớp cha trá thành private của lớp con.

  • Kế thừa protected: Lớp con kế thừa protected từ lớp cha thì các thành phần
    protected và public của lớp cha trá thành protected của lớp con.

[2016-2017]

HK

a. Nêu khái niệm về sự kế thừa và những °u điểm của kế thừa trong việc lập
trình. Cho ví dụ minh họa. (2 điểm)
b. Xét đoạn ch°¡ng trình sau:
class A{
A(int i);
};
void main(){
A a1;

A b2(5);
}
Hãy cho biết đoạn ch°¡ng trình trên có lỗi xảy ra hay không? Nếu có hãy giải
thích và chỉ ra cách sửa lỗi. (1 điểm)

HK

a. Trình bày khái niệm của lớp c¡ sá trừu t°ợng (abstract class). Lớp c¡ sá
trừu t°ợng đ°ợc cài đặt trong C++ nh° thế nào? (1 điểm)
b. Xét đoạn ch°¡ng trình sau:

#include <iostream>
using namespace std;
class Array{
int A[100];
int n;
public:
Array(int n)
{
//….
}
//….
};

void main()
{
Array M1;
Array M2(10);
cout<<M[3];
}

Cho biết đoạn ch°¡ng trình trên khi biên dịch có lỗi xảy ra hay không? Nếu
có lỗi, hãy chỉ ra các lỗi đó và sửa lỗi để ch°¡ng trình có thể thực thi đ°ợc.
(1 điểm)

HK

a. Phân biệt private, protected, public. (1 điểm)
b. Trình bày về constructor. (1 điểm)

Giải:
HK

a.

  • Khái niệm:

K¿ thừa trong lÁp trình là cách 1 lớp có thể thừa h°ởng lại những thuộc tính,
ph°¢ng thức từ 1 lớp khác
và sử dụng chúng nh° là của bản thân mình.

Một định nghĩa trừu t°ợng h¡n về kế thừa: là một đặc điểm của ngôn ngữ h°ớng đối
t°ợng dùng để biểu diễn mối quan hệ đặc biệt hoá – tổng quát hoá giữa các lớp.

  • ̄u điểm:

  • Cho phép xây dựng 1 lớp mới từ lớp đã có.
    ▪ Lớp mới gọi là lớp con (subclass) hay lớp d¿n xuất (derived class).
    ▪ Lớp đã có gọi là lớp cha (superclass) hay lớp c¢ sở (base class).

  • Cho phép chia sẻ các thông tin chung nhằm tái sử dụng và đồng thßi giúp ta
    dễ dàng nâng cấp, dễ dàng bảo trì.

  • Định nghĩa sự t°¡ng thích giữa các lớp, nhß đó ta có thể chuyển kiểu tự động.

b.

  • Đoạn ch°¡ng trình trên có lỗi xảy ra vì thiếu từ khóa dẫn xuất (á đây là public để
    cho hàm thành phần trong nó có thể truy xuất đ°ợc trong hàm main), thiếu các hàm
    khái tạo ( hàm khởi tạo mặc địnhhàm khởi tạo nhÁn tham số đầu vào ) bên
    trong lớp.

  • Sửa:

class A{
public:
A(){
}
A(int i){
}

};
void main(){
A a1;
A b2(5);
}

HK

a.

  • Lớp c¡ sá trừu t°ợng (Abstract Class): lớp có ít nhất 1 ph°¡ng thức đ°ợc khai
    báo là hàm thuần ảo (pure virtual), hàm thuần ảođ°ợc xác định là một hàm
    virtual có kết thúc khai báo hàm là <= 0=.
    Ví dụ: virtual double tinhChuVi () = 0;
  • Trong tr°ßng hợp lớp c¡ sá trừu t°ợng có tất cả các ph°¡ng thức là thuần ảo
    thì đ°ợc gọi là interface (giao diện).

class Xe

{

private:

string id;

string loai;

double gia_tien;

public:

virtual void Nhap() = 0;

virtual double TinhGiatien() = 0;

};

b.

  • Đoạn ch°¡ng trình trên có lỗi xảy ra vì:

  • Sai dòng A a; Array M1; vì ch°a có ph°¡ng thức khái tạo mặc định.

  • Sai dòng cout<<M[3]; vì ch°a khai báo đối t°ợng M, mảng A đ°ợc khai
    báo bên ngoài từ khóa dẫn xuất public nên nó không thể truy xuất đ°ợc trong
    hàm main.

  • Sửa:

#include <iostream>

using namespace std;

class Array{

public:

int A[100];

int n;

Array()

{
}

Array(int n)

{

//….

}

//….

};

void main()

{

Array M1;

Array M2(10);

Array M;

cout<<M[3];

}

HK

a.

  • Thành phần private á lớp cha thì không truy xuất đ°ợc á lớp con

  • Kế thừa public: Lớp con kế thừa public từ lớp cha thì các thành phần protected của
    lớp cha trá thành protected của lớp con, các thành phần public của lớp cha trá thành
    public của lớp con.

  • Kế thừa private: Lớp con kế thừa private từ lớp cha thì các thành phần protected
    và public của lớp cha trá thành private của lớp con.

  • Kế thừa protected: Lớp con kế thừa protected từ lớp cha thì các thành phần
    protected và public của lớp cha trá thành protected của lớp con.

b.

Ph°¢ng thức thi¿t lÁp (Constructor) là một ph°¡ng thức đặc biệt đ°ợc gọi tự động
tại thßi điểm đối t°ợng đ°ợc tạo. Các ph°¡ng thức thiết lập có nhiệm vụ thiết lập
thông tin ban đầu cho các đối t°ợng thuộc về lớp ngay khi đối t°ợng đ°ợc khai báo.

Đặc điểm:

  • Có tên trùng với tên lớp.
  • Không có kiểu dữ liệu trả về.
  • Đ°ợc tự động gọi thực hiện ngay khi một đối t°ợng đ°ợc khai báo.
  • Có thể có nhiều ph°¡ng thức thiết lập trong 1 lớp.
  • Trong một quá trình sống của đối t°ợng thì chỉ có 1 lần duy nhất một ph°¡ng
    thức thiết lập đ°ợc gọi thực hiện mà thôi, đó là khi đối t°ợng ra đßi.
  • Các ph°¡ng thức thiết lập của lớp thuộc nhóm các ph°¡ng thức khái tạo.
_________________________________

[2017-2018]

HK

a. Phân biệt các phạm vi truy cập private, protected và public. (1 điểm)
b. Cho biết ý nghĩa và mục đích của các hàm get/set trong một lớp. (1 điểm)

HK

a. Hàm thuần ảo là gì? Lớp trừu t°ợng là gì? Cho ví dụ minh họa. (1 điểm)
b. Hãy nêu các đặc điểm quan trọng của lập trình h°ớng đối t°ợng. (1 điểm)

Giải:
HK

a.

  • Thành phần private á lớp cha thì không truy xuất đ°ợc á lớp con

  • Kế thừa public: Lớp con kế thừa public từ lớp cha thì các thành phần protected của
    lớp cha trá thành protected của lớp con, các thành phần public của lớp cha trá thành
    public của lớp con.

  • Kế thừa private: Lớp con kế thừa private từ lớp cha thì các thành phần protected
    và public của lớp cha trá thành private của lớp con.

  • Kế thừa protected: Lớp con kế thừa protected từ lớp cha thì các thành phần
    protected và public của lớp cha trá thành protected của lớp con.

b.

Hàm get: truy vấn dữ liệu private từ các đối t°ợng (đọc giá trị các thành viên dữ
liệu). Đặc điểm quan trọng của ph°¡ng thức truy vấn là nó không nên thay đổi trạng
thái hiện tại của đối t°ợng.

Hàm set: cập nhật dữ liệu private từ các đối t°ợng (ghi giá trị cho các thành viên dữ
liệu). Ph°¡ng thức cập nhật th°ßng để thay đổi trạng thái của đối t°ợng bằng cách
sửa đổi một hoặc nhiều thành viên dữ liệu của đối t°ợng đó.

HK

a.

Hàm thuần ảo (Ph°¢ng thức ảo thuần tuý) có ý nghĩa cho việc tổ chức s¡ đồ phân
cấp các lớp, nó đóng vai trò chừa sẵn chỗ trống cho các lớp con điền vào với phiên
bản phù hợp. Ph°¡ng thức ảo thuần tuý là ph°¡ng thức ảo không có nội dung, đ°ợc
khai báo với từ khóa virtual và đ°ợc gán giá trị =0.

Khi lớp có ph°¡ng thức ảo thuần tuý, lớp trá thành lớp c¡ sá trừu t°ợng. Lớp c¡ sá
trừu t°ợng không có đối t°ợng nào thuộc chính nó.

class Shape //Abstract
{
public :
//Pure virtual Function
virtual void draw() = 0;
}

Trong ví dụ trên, các hàm thành phần trong lớp Shape là ph°¡ng thức ảo thuần tuý
và lớp Shape là lớp c¡ sá trừu t°ợng. Nó bảo đảm không thể tạo đ°ợc đối t°ợng
thuộc lớp Shape.

b.

  • Trừu t°ợng hóa – Abstraction: Cách nhìn khái quát hóa về một tập các đối t°ợng
    có chung các đặc điểm đ°ợc quan tâm (và bỏ qua những chi tiết không cần thiết).

  • Đóng gói – Encapsulation: Nhóm những gì có liên quan với nhau vào làm một, để
    sau này có thể dùng một cái tên để gọi đến. Vd: các hàm/ thủ tục đóng gói các câu
    lệnh, các đối t°ợng đóng gói dữ liệu của chúng và các thủ tục có liên quan.

  • Thừa kế – Inheritance: Cho phép một lớp D có đ°ợc các thuộc tính và thao tác của
    lớp C, nh° thể các thuộc tính và thao tác đó đã đ°ợc định nghĩa tại lớp D. Cho phép
    cài đặt nhiều quan hệ giữa các đối t°ợng: Đặc biệt hóa – Tổng quát hóa

  • Đa hình – Polymorphism: Là c¡ chế cho phép một tên thao tác hoặc thuộc tính có
    thể đ°ợc định nghĩa tại nhiều lớp và có thể có nhiều cài đặt khác nhau tại mỗi lớp
    trong các lớp đó.

[2018-2019]

HK

a. Phân biệt khái niệm lớp và đối t°ợng trong lập trình h°ớng đối t°ợng. (
điểm)
b. Trình bày khái niệm đa hình trong lập trình h°ớng đối t°ợng (1 điểm). Cho
ví dụ (0 điểm).

HK

a. Phân biệt khái niệm overload (tải chồng) và override (ghi đè). (1 điểm)
b. Phân biệt các kiểu kế thừa private, protected và public. (1 điểm)

Giải:
HK

a.

  • Lớp là một mô tả trừu t°ợng của nhóm các đối t°ợng cùng bản chất, ng°ợc
    lại mỗi một đối t°ợng là một thể hiện cụ thể cho những mô tả trừu t°ợng đó.
  • Lớp là cái ta thiết kế và lập trình. Đối t°ợng là cái ta tạo (từ một lớp) tại thßi
    gian chạy.

b.

Đa hình: Là hiện t°ợng các đối t°ợng thuộc các lớp khác nhau có khả năng hiểu
cùng một thông điệp theo các cách khác nhau.

Ví dụ: Nhận đ°ợc cùng một thông điệp <nhảy=, một con kangaroo và một con cóc
nhảy theo hai kiểu khác nhau: chúng cùng có hành vi <nhảy= nh°ng có hành vi này
có nội dung khác nhau.

HK

a.

Override Overload

Khái
niệm

Là một tính năng cho phép một
lớp con hoặc lớp con cung cấp một
triển khai cụ thể của một ph°¡ng
thức đã đ°ợc cung cấp bái một
trong các lớp siêu hoặc các lớp cha
của nó. Nói cách khác, nếu lớp con
cung cấp trình triển khai cụ thể
của ph°¡ng thức mà đã đ°ợc cung
cấp bái một trong các lớp cha của
nó, thì đó là ghi đè ph°¡ng thức.

Nạp chồng ph°¡ng thức đ¡n giản
là có vài ph°¡ng thức trùng tên
nh°ng khác nhau về đối số. Cài
chồng ph°¡ng thức cho phép ta
tạo nhiều phiên bản của một
ph°¡ng thức, mỗi phiên bản chấp
nhận một danh sách đối số khác
nhau, nhằm tạo thuận lợi cho việc
gọi ph°¡ng thức.

Hành vi
Thay đổi hành vi hiện tại của
ph°¡ng thức.

Thêm hoặc má rộng cho hành vi
của ph°¡ng thức.
Đa hình Thể hiện tính đa hình tại run time. Thể hiện tính đa hình tại compile
Danh
sách
tham số

Danh sách tham số phải giống
nhau.

Danh sách tham số khác nhau (số
l°ợng, thứ tự, kiểu dữ liệu)
Giá trị
trả vÁ

Kiểu trả về bắt buộc phải giống
nhau.
Kiểu trả về có thể khác nhau.

Phạm vi
Xảy ra giữa 2 class có quan hệ kế
thừa
Xảy ra trong phạm vi cùng 1 class.

b.

  • Thành phần private á lớp cha thì không truy xuất đ°ợc á lớp con

  • Kế thừa public: Lớp con kế thừa public từ lớp cha thì các thành phần protected của
    lớp cha trá thành protected của lớp con, các thành phần public của lớp cha trá thành
    public của lớp con.

  • Kế thừa private: Lớp con kế thừa private từ lớp cha thì các thành phần protected
    và public của lớp cha trá thành private của lớp con.

  • Kế thừa protected: Lớp con kế thừa protected từ lớp cha thì các thành phần
    protected và public của lớp cha trá thành protected của lớp con.

_________________________________

[2019-2020]

HK

a. Hãy trình bày những đặc điểm của tính đóng gói (encapsulation) lập trình
h°ớng đối t°ợng. Tr°ßng hợp nào thì có thể vi phạm tính đóng gói? Cho ví
dụ minh họa. (1 điểm)
b. Hãy trình bày những °u điểm của kế thừa trong việc lập trình h°ớng đối
t°ợng và cho ví dụ minh họa. (1 điểm)

Giải:

a.

– Đóng gói – Encapsulation: Nhóm những gì có liên quan với nhau vào làm một,
để sau này có thể dùng một cái tên để gọi đến. Tính đóng gói “đóng gói” thuộc tính
và ph°¡ng thức của đối t°ợng (hoặc lớp) thông qua việc giới hạn quyền truy cập
(hoặc thay đổi) giá trị của thuộc tính hoặc quyền gọi ph°¡ng thức. Nói cách khác
tính đóng gói cho phép kiểm soát quyền truy cập (và thay đổi) giá trị của thuộc tính
hoặc quyền gọi ph°¡ng thức của đối t°ợng (hoặc lớp) và đối t°ợng (hoặc lớp) con.

  • Tr°ßng hợp có thể vi phạm tính đóng gói: khi khai báo lớp con là bạn của lớp cha.

Ví dụ:

class Nguoi

{

friend class SinhVien;

char *HoTen;

int NamSinh;

public:

//…

};

class SinhVien : public Nguoi{

char *MaSo;

public:

//…

void Xuat() const{

cout<<“Sinh vien, ma so: “<<MaSo<<“, ho ten: “<<HoTen;

}

};

Khai báo lớp bạn như trên, lớp SinhVien có thể truy xuất các thành phần private
của lớp Nguoi.

b.

  • ̄u điểm:

  • Cho phép xây dựng 1 lớp mới từ lớp đã có.
    ▪ Lớp mới gọi là lớp con (subclass) hay lớp d¿n xuất (derived class).
    ▪ Lớp đã có gọi là lớp cha (superclass) hay lớp c¢ sở (base class).

  • Cho phép chia sẻ các thông tin chung nhằm tái sử dụng và đồng thßi giúp ta
    dễ dàng nâng cấp, dễ dàng bảo trì.

  • Định nghĩa sự t°¡ng thích giữa các lớp, nhß đó ta có thể chuyển kiểu tự động.

CÂU 2.

[2013-2014]

HK1

a. Xét đoạn ch°¡ng trình sau:

#include <iostream>
using namespace std;
class A {
public:
A( ) {
cout << “Constructing A “;
}
~A( ) {
cout << “Destructing A “;
}
};
class B: public A {
public:
B( ) {
cout << “Constructing B “;
}
~B( ) {
cout << “Destructing B “;
}
};
int main() {
B b1;
return 0;
}
Hãy cho biết kết quả xuất ra màn hình khi thực thi đoạn ch°¡ng trình trên.
Giải thích ngắn gọn tại sao có kết quả đó. (1 điểm)

b. Xét đoạn ch°¡ng trình sau:

#include <iostream>
using namespace std;
class A {
private:
int x;

public:
A(int t) {
x = t;
}
static void f() {
cout<<x;
}
int f2() {
return x;
}
};
void main() {
A a;
f2(a);
}
Cho biết đoạn ch°¡ng trình trên khi biên dịch có lỗi xảy ra hay không? Nếu
có lỗi, hãy chỉ ra các lỗi đó và sửa lỗi để ch°¡ng trình có thể thực thi đ°ợc.
(1 điểm)

HK2

a. Xét lớp phân số đ°ợc khai báo nh° sau:

class PhanSo{
private:
int ts, ms;
public:
PhanSo (int ts=0, int ms=1);
PhanSo operator +(PhanSo);
};
Hãy cho biết trong các dòng lệnh sau đây, dòng nào có lỗi xảy ra, giải thích
và sửa lỗi nếu có:

PhanSo a, b(3, 4), c(2, 5);

a = b + c;

a = b + 3;

a = 5 + c;

b. Xét đoạn ch°¡ng trình sau:

#include <iostream>
using namespace std;
class A {
public:
A( ) {
cout << “\nHam dung mac dinh lop A “;
}
~A( ) {
cout << “\nHam huy lop A “;
}
};
class B {
public:
B( ) {
cout << “\nHam dung mac dinh lop B “;
}
~B( ) {
cout << “\nHam huy lop B “;
}
};
class C: public A, private B {
public:
C( ) {
cout << “\nHam dung mac dinh lop C “;
}
~C( ) {
cout << “\nHam huy lop C “;
}
};
void main() {
C c;
}
Hãy cho biết kết quả xuất ra màn hình khi thực thi đoạn ch°¡ng trình trên.
Giải thích ngắn gọn tại sao có kết quả đó.

Giải:
HK1

a.

  • Kết quả xuất ra màn hình:

Constructing A Constructing B Destructing B Destructing A

  • Giải thích:

Các lớp c¡ sá luôn đ°ợc xây dựng tr°ớc các thành viên dữ liệu. Các thành viên dữ
liệu đ°ợc xây dựng theo thứ tự mà chúng đ°ợc khai báo trong lớp. Thứ tự này không
có gì để làm với danh sách khái tạo. Khi một thành viên dữ liệu đang đ°ợc khái tạo,
nó sẽ xem qua danh sách khái tạo của bạn để biết các tham số và gọi hàm tạo mặc
định nếu không có kết quả khớp. Hàm hủy cho các thành viên dữ liệu luôn đ°ợc gọi
theo thứ tự ng°ợc lại.

b.

  • Đoạn ch°¡ng trình trên có lỗi xảy ra vì:

  • Sai dòng static void f() { cout<<x; } vì ph°¡ng thức static chỉ dùng biến static.
    Có thể sửa lại bằng cách khai báo x bên trong ph°¡ng thức f.

  • Sai dòng A a; vì ch°a có ph°¡ng thức khái tạo mặc định.

  • Sai dòng f2(a); vì hàm f2 là ph°¡ng thức thuộc class A. Cú pháp để gọi một
    ph°¡ng thức thuộc lớp phải là: <object>.method

Sửa:

#include <iostream>

using namespace std;

class A {

private:

int x;

public:

A()

{

}

A(int t)

{

x = t;

}

static void f(int x)

{

cout << x;

}

int f2()

{

return x;

}

};

void main()

{

A a;

a();

}

HK2

a.

Dòng lệnh: a = 5 + c; có lỗi vì ch°a xây dựng ph°¡ng thức cộng (operator +) để
cộng một số nguyên với một phân số và trả về phân số. Trong C++, x + y (tr°ßng
hợp trên) đ°ợc dịch theo kiểu: x+(y). Khi gọi operator. trong x. thì x không
đ°ợc chuyển kiểu tự động; y có thể chuyển ngầm đ°ợc vì class của x đã đ°ợc xác
định, số l°ợng hàm cần kiểm thử chuyển kiểu tự động cho y là nhỏ.

  • Sửa: a = c + 5;

b.

  • Kết quả xuất ra màn hình:

Ham dung mac dinh lop A

Ham dung mac dinh lop B

Ham dung mac dinh lop C

Ham huy lop C

Ham huy lop B

Ham huy lop A

  • Giải thích:

Các lớp c¡ sá luôn đ°ợc xây dựng tr°ớc các thành viên dữ liệu. Các thành viên dữ
liệu đ°ợc xây dựng theo thứ tự mà chúng đ°ợc khai báo trong lớp. Thứ tự này không
có gì để làm với danh sách khái tạo. Khi một thành viên dữ liệu đang đ°ợc khái tạo,
nó sẽ xem qua danh sách khái tạo của bạn để biết các tham số và gọi hàm tạo mặc
định nếu không có kết quả khớp. Hàm hủy cho các thành viên dữ liệu luôn đ°ợc gọi
theo thứ tự ng°ợc lại.

[2014-2015]

HK2

Xây dựng lớp đa thức bậc nhất để thể hiện các đa thức bật nhất có dạng:

F(x)= ax + b (a luôn khác 0)

Xây dựng các ph°¡ng thức: (3 điểm)

a. Ph°¡ng thức cho phép xác định giá trị của đa thức ứng với x=xo (tính F(xo)
).

b. Ph°¡ng thức trả về nghiệm đa thức bậc 1 (nghĩa là F(x)=0).

c. Phép toán cộng (operator +) để cộng hai đa thức bậc nhất.

Giải:

class DaThucBacNhat
{
private:

float a;
float b;
public:
DaThucBacNhat();
DaThucBacNhat(float a1, float b1);
DaThucBacNhat(DaThucBacNhat& dt);

float TinhGiaTri(DaThucBacNhat dt, float x0);
float Nghiem(DaThucBacNhat dt);
DaThucBacNhat operator+(const DaThucBacNhat&);
};

DaThucBacNhat::DaThucBacNhat()
{
a = 1;
b = 0;
}
DaThucBacNhat::DaThucBacNhat(float a1, float b1)
{
a = a1;
b = b1;
}
DaThucBacNhat::DaThucBacNhat(DaThucBacNhat& dt)
{
a = dt;
b = dt;
}
float DaThucBacNhat::TinhGiaTri(DaThucBacNhat dt, float x0)
{
return a * x0 + b;
}

float DaThucBacNhat::Nghiem(DaThucBacNhat dt)
{
if (b == 0)
return 0;
else
return -b / a;
}

DaThucBacNhat DaThucBacNhat::operator+(const DaThucBacNhat& dt)
{
DaThucBacNhat tong;
tong = this->a + dt;
tong = this->b + dt;
return tong;
}

[2015-2016]

HK2

Xây dựng lớp Thßi gian (giß, phút, giây) (1 điểm).

Định nghĩa các phép toán:
++ để tăng thßi gian thêm 1 giây (1 điểm).
>> và << để nhập, xuất dữ liệu thßi gian (1 điểm).

HK3

Xây dựng lớp Phân số (1 điểm). Định nghĩa các phép toán
+, – để thực hiện phép cộng và trừ giữa hai phân số (1 điểm).
>> và << để nhập, xuất dữ liệu phân số (1 điểm).

Giải:
HK2

class CTime
{
private:
int gio;
int phut;
int giay;
public:
CTime();
CTime(int h, int m, int s);
~CTime();

friend ostream& operator<<(ostream& os, const CTime& T);
friend istream& operator>>(istream& is, CTime& T);

CTime operator+(int a);
CTime operator++();
CTime operator++(int);
};

CTime::CTime() {
this->gio = this->phut = this->giay = 0;
}
CTime::CTime(int h, int m, int s)
{
this->gio = h;
this->phut = m;
this->giay = s;
}
CTime::~CTime()
{
}

istream& operator>>(istream& is, CTime& T)
{
cout << “Nhap gio: “;

is >> T;
cout << “Nhap phut: “;
is >> T;
cout << “Nhap giay: “;
is >> T;
return is;
}
ostream& operator<<(ostream& os, const CTime& T)
{
os << T << ” gio ” << T << ” phut ” << T << ” giay “;
return os;
}

long CTime::GetTong()
{
return this->giay + this->phut * 60 + this->gio * 60 * 60;
}long CTime::GetTong()
{
return this->giay + this->phut * 60 + this->gio * 60 * 60;
}
CTime CTime::operator+(int a)
{
CTime Time;
Time = (this->GetTong() + a) / 3600;

Time = ((this->GetTong() + a – Time * 3600) / 60) % 60;
Time = (this->GetTong() + a) % 60;
return Time;
}
CTime CTime::operator++()
{
return *this + 1;
}

CTime CTime::operator++(int a)
{
CTime temp;
temp = *this;
*this + 1;
return temp;
}

HK3

class PhanSo
{
private:
int ts, ms;
public:
PhanSo();
PhanSo(int a);
void Reduce();
PhanSo operator+(const PhanSo&);
PhanSo operator-(const PhanSo&);
PhanSo operator*(const PhanSo&);

PhanSo operator/(const PhanSo&);
bool operator==(PhanSo&);
bool operator!=(PhanSo&);
bool operator>(PhanSo&);
bool operator>=(PhanSo&);
bool operator<(PhanSo&);
bool operator<=(PhanSo&);
friend istream& operator>>(istream& is, PhanSo& x);
friend ostream& operator<<(ostream& os, const PhanSo& x);
~PhanSo();
};

PhanSo::PhanSo(){
ts = 0;
ms = 1;
}
PhanSo::PhanSo(int a)
{
ts = a;
ms = 1;
}
void PhanSo::Reduce() {
int ucln;
int a = abs(ts);
int b = abs(ms);
if (ts == 0 && ms == 0) {
ucln = ts + ms;
}
else {
while (a != b) {
if (a > b) {
a -= b;
}
else
{
b -= a;
}
}
ucln = a;
}
ts /= ucln;
ms /= ucln;
}
PhanSo::~PhanSo()
{
}

istream& operator>>(istream& is, PhanSo& x)
{
cout << “Nhap tu so: “;
is >> x;
cout << “Nhap mau so: “;
is >> x;
return is;
}

ostream& operator<<(ostream& os, const PhanSo& x)
{
os << “Tu so: “;
os << x;
os << ” Mau so: “;
os << x;
return os;
}

PhanSo PhanSo::operator+(const PhanSo& y)
{
PhanSo temp;
temp = this->ts * y + y * this->ms;
temp = this->ms * y;
temp();
return temp;
}
PhanSo PhanSo::operator-(const PhanSo& y)
{
PhanSo temp;
temp = this->ts * y – y * this->ms;
temp = this->ms * y;
temp();
return temp;
}

[2016-2017]

HK1

Cho đoạn ch°¡ng trình tính toán với phân số nh° sau:

Hãy khai báo và cài đặt lớp phân số thích hợp để ch°¡ng trình chạy đúng. L°u
ý rằng không đ°ợc chỉnh sửa hàm main và sinh viên cần viết các lệnh #include
thích hợp. (2 điểm)

HK2

Xây dựng lớp Thßi gian (giß, phút, giây) (0 điểm).
Định nghĩa các phép toán:
>> và << để nhập, xuất dữ liệu thßi gian (1 điểm)
— để thực hiện giảm thßi gian đi 1 giây (1 điểm)

HK3

Xây dựng lớp đa thức bậc hai (1 điểm) để thể hiện các đa thức bật hai có dạng:

F(x)= ax 2 + bx + c (a luôn khác 0)

Xây dựng các ph°¡ng thức: (2 điểm)

a. Ph°¡ng thức cho phép xác định giá trị của đa thức ứng với x=xo (tính F(xo)
).

b. Phép toán cộng (operator +) để cộng hai đa thức bậc hai.

Giải:
HK1

#include<iostream>
using namespace std;
#pragma once
class PhanSo
{
private:
int ts, ms;
public:
void Xuat();
PhanSo();
PhanSo(int a, int b);
PhanSo(int a);
void Reduce();
PhanSo operator+(const PhanSo&);
};

#include “PhanSo”
PhanSo::PhanSo()
{
ts = 0;
ms = 1;
}
PhanSo::PhanSo(int a, int b)
{
ts = a;
ms = b;
}
PhanSo::PhanSo(int a)

{
ts = a;
ms = 1;
}
void PhanSo::Reduce() {
int ucln;
int a = abs(ts);
int b = abs(ms);
if (ts == 0 && ms == 0) {
ucln = ts + ms;
}
else {
while (a != b) {
if (a > b) {
a -= b;
}
else
{
b -= a;
}
}
ucln = a;
}
ts /= ucln;
ms /= ucln;
}
PhanSo::~PhanSo()
{
}
PhanSo PhanSo::operator + (const PhanSo& y)
{
PhanSo temp;
temp = this->ts * y + y * this->ms;
temp = this->ms * y;
temp();
return temp;
}
void PhanSo::Xuat()
{
cout << “\nTu so: ” << TuSo;
cout << “\nMau so: ” << MauSo << endl;
}

HK2

class CTime
{
private:
int gio;
int phut;
int giay;
public:
CTime();
CTime(int h, int m, int s);
~CTime();

friend ostream& operator<<(ostream& os, const CTime& T);
friend istream& operator>>(istream& is, CTime& T);

CTime operator-(int a);
CTime operator–();
CTime operator–(int);
};

CTime::CTime() {
this->gio = this->phut = this->giay = 0;
}
CTime::CTime(int h, int m, int s)
{
this->gio = h;
this->phut = m;
this->giay = s;
}
CTime::~CTime()
{
}
istream& operator>>(istream& is, CTime& T)
{
cout << “Nhap gio: “;
is >> T;
cout << “Nhap phut: “;
is >> T;
cout << “Nhap giay: “;
is >> T;
return is;
}
ostream& operator<<(ostream& os, const CTime& T)
{
os << T << ” gio ” << T << ” phut ” << T << ” giay “;
return os;
}

long CTime::GetTong()
{
return this->giay + this->phut * 60 + this->gio * 60 * 60;
}long CTime::GetTong()
{
return this->giay + this->phut * 60 + this->gio * 60 * 60;
}
CTime CTime::operator-(int a)
{
CTime Time;
if (this->GetTong() – a < 0)
{
cout << “Loi!” << endl;
return Time;
}
else
{

Time = (this->GetTong() – a) / 3600;
Time = ((this->GetTong() – a – Time * 3600) / 60) % 60;
Time = (this->GetTong() – a) % 60;
return Time;
}
}
CTime CTime::operator–()
{
return *this – 1;
}

CTime CTime::operator–(int a)
{
CTime temp;
temp = *this;
*this – 1;
return temp;
}

HK3

class DaThucBacHai
{
private:
float a;
float b;
float c;
public:
DaThucBacHai();
DaThucBacHai(float a1, float b1, float c1);
DaThucBacHai(DaThucBacHai& dt);

float TinhGiaTri(DaThucBacHai dt, float x0);
DaThucBacHai operator+(const DaThucBacHai&);
};

DaThucBacHai::DaThucBacHai()
{
a = 1;
b = 0;
c = 0;
}
DaThucBacHai::DaThucBacHai(float a1, float b1, float c1)
{
a = a1;
b = b1;
c = c1;
}
DaThucBacHai::DaThucBacHai(DaThucBacHai& dt)
{
a = dt;
b = dt;
c = dt;
}
float DaThucBacHai::TinhGiaTri(DaThucBacHai dt, float x0)

{
return a * pow(x0, 2) + b * x0 + c;
}

DaThucBacHai DaThucBacHai::operator+(const DaThucBacHai& dt)
{
DaThucBacHai tong;
tong = this->a + dt;
tong = this->b + dt;
tong = this->c + dt;
return tong;
}

[2017-2018]

HK1

void main()
{
cNgay ng1; // ng1 sẽ có giá trị là ngày 1 tháng 1 năm 1
cNgay ng2(2017, 1); // ng2 sẽ có giá trị là ngày 1 tháng 1 năm 2017
cNgay ng3(2017, 1, 7); // ng3 sẽ có giá trị là ngày 7 tháng 1 năm 2017
cin>>ng1;
cout<<ng1;
if(ng1 < ng2)
cout << “Ngay 1 truoc ngay 2” << endl;
else
cout << “Ngay 1 khong truoc ngay 2” << endl;
}
Hãy định nghĩa lớp cNgay thích hợp để ch°¡ng trình không bị lỗi biên dịch
và chạy đúng. L°u ý rằng không đ°ợc chỉnh sửa hàm main và sinh viên cần
viết cả các lệnh #include thích hợp. (3 điểm)

HK2

Xây dựng lớp Đa thức bậc n với các toán tử >>, <<, +. (3 điểm)

Giải:
HK1

#include<iostream>
using namespace std;
#pragma once
class cNgay

{
private:
int nam, thang, ngay;
public:
cNgay();
cNgay(int a, int b);
cNgay(int a, int b, int c);
friend istream& operator>>(std::istream&, cNgay&);
friend ostream& operator<<(std::ostream&, const cNgay);
bool operator<(cNgay&);
};

#include “Ngay”
cNgay::cNgay()
{
nam = 1;
thang = 1;
ngay = 1;
}
cNgay::cNgay(int a, int b)
{
nam = a;
thang = b;
}
cNgay::cNgay(int a, int b, int c)
{
nam = a;
thang = b;
nam = c;
}
istream& operator>>(std::istream& is, cNgay& x)
{
cout << “\nNhap nam :”;
is >> x;
cout << “\nNhap thang :”;
is >> x;
cout << “\nNhap ngay :”;
is >> x;
return is;
}
ostream& operator<<(std::ostream& os, const cNgay x)
{
os << “\nNgay ” << x << ” thang ” << x << ” nam ” << x << endl;
return os;
}
bool cNgay::operator<(cNgay& b)
{
if (nam <= b)
{
if (nam < b)
return true;
else
{
if (thang <= b)
{

if (thang < b)
return true;
else
{
if (ngay < b)
return true;
}
}
}
}
return false;
}

HK2

#include<iostream>
using namespace std;
#pragma once
class DaThuc
{
private:
int n;
int* arr;
public:
DaThuc();

friend istream& operator>>(std::istream&, DaThuc&);
friend ostream& operator<<(std::ostream&, const DaThuc);

DaThuc operator+(const DaThuc&);
};

#include “DaThuc”
DaThuc::DaThuc()
{
int n = 1;
arr = new int[1];
arr[0] = 1;
}
istream& operator>>(std::istream& is, DaThuc& y)
{
cout << “\nNhap bac cua da thuc :”;
int m;
is >> m;
y = m;
y = new int[y + 1];
for (int i = y; i >= 0; i–)
{
cout << “\nNhap he bac ” << i << ” :”;
cin >> y[i];
}
return is;
}
ostream& operator<<(std::ostream& os, const DaThuc y)
{

os << “\nHe so cua bac giam dan la:”;
for (int i = y; i >= 0; i–)
{
os << y[i] << ” “;
}
return os;
}
DaThuc DaThuc::operator+(const DaThuc &y)
{
DaThuc z;
if (this->n > y)
{
z = this->n;
z = new int[z + 1];
for (int i = y; i >= 0; i–)
{
z[i] = this->arr[i] + y[i];
}
int j = this->n;
while (j > y)
{
z[j] = this->arr[j];
j–;
}
return z;
}
if (this->n < y)
{
DaThuc z;
z = y;
//z = z(y);
z = new int[y + 1];
for (int i = this->n; i >= 0; i–)
{
z[i] = this->arr[i] + y[i];
}
int j = z;
while (j > this->n)
{
z[j] = y[j];
j–;
}
return z;
}
if (this->n == y)
{
DaThuc z;
z = this->n;
z = new int[this->n + 1];
//z = z(x);
for (int i = y; i >= 0; i–)
{
z[i] = this->arr[i] + y[i];
}
return z;

}
}

[2018-2019]

HK1

Định nghĩa lớp CDate biểu diễn khái niệm ngày, tháng, năm (0 điểm) với
các phép toán ++ (thêm một ngày) theo dạng prefix ++a và postfix a++ (1
điểm). Phép toán <<, >> để xuất, nhập dữ liệu Cdate (1 điểm).

HK2

Xây dựng lớp thßi gian (giß, phút, giây) với các toán tử >>, << để nhập xuất
và toán tử ++ để tăng thßi gian thêm 1 giây. (3 điểm)

Giải:
HK1

#include<iostream>
using namespace std;
#pragma once
class CDate
{
private:
int ngay, thang, nam;
public:
CDate();
friend std::istream& operator>>(std::istream&, CDate&);
friend std::ostream& operator<<(std::ostream&, const CDate);

friend CDate operator+(const CDate, const int);
CDate& operator++();
CDate operator++(int);

bool ktNamNhuan();
long long TongNgay();
long operator-(CDate& y);
};

#include “CDate”
#include<iostream>
using namespace std;

CDate::CDate()
{
ngay = 0;
thang = 0;
nam = 0;
}

std::istream& operator>>(std::istream& is, CDate& x)
{
cout << “\nNhap ngay :”;
is >> x;
cout << “\nNhap thang :”;
is >> x;
cout << “\nNhap nam :”;
is >> x;
return is;
}
std::ostream& operator<<(std::ostream& os, const CDate x)
{
os << “\nNgay ” << x << ” thang ” << x << ” nam ” << x;
return os;
}

CDate& CDate::operator++()
{
int k = ngay + 1;
do
{
switch (thang)
{
case 1:case 3:case 5: case 7:case 8: case 10: case 12:
if (k > 31)
{
thang++;
if (thang == 13)
{
thang = 1;
nam++;
}
k -= 31;
}
else
{
ngay = k;
k = 0;
}
break;
case 4:case 6: case 9: case 11:
if (k > 30)
{
thang++;
k -= 30;
}
else
{
ngay = k;
k = 0;
}
break;
case 2:
if (nam % 400 == 0 || (nam % 4 == 0 && nam % 100 != 0))
{

if (k > 29)
{
thang++;
k -= 29;
}
else
{
ngay = k;
k = 0;
}
}
else
{
if (k > 28)
{
thang++;
k -= 28;
}
else
{
ngay = k;
k = 0;
}
}
break;
}
} while (k > 0);
return *this;
}

CDate CDate::operator++(int y)
{
CDate temp;
temp = this->nam;
temp = this->thang;
temp = this->ngay;
int k = ngay + 1;
do
{
switch (thang)
{
case 1:case 3:case 5: case 7:case 8: case 10: case 12:
if (k > 31)
{
thang++;
if (thang == 13)
{
thang = 1;
nam++;
}
k -= 31;
}
else
{
ngay = k;

k = 0;
}
break;
case 4:case 6: case 9: case 11:
if (k > 30)
{
thang++;
k -= 30;
}
else
{
ngay = k;
k = 0;
}
break;
case 2:
if (nam % 400 == 0 || (nam % 4 == 0 && nam % 100 != 0))
{
if (k > 29)
{
thang++;
k -= 29;
}
else
{
ngay = k;
k = 0;
}
}
else
{
if (k > 28)
{
thang++;
k -= 28;
}
else
{
ngay = k;
k = 0;
}
}
break;
}
} while (k > 0);
return temp;
}

HK2

class CTime
{
private:
int gio;
int phut;

int giay;
public:
CTime();
CTime(int h, int m, int s);
~CTime();

friend ostream& operator<<(ostream& os, const CTime& T);
friend istream& operator>>(istream& is, CTime& T);

CTime operator+(int a);
CTime operator++();
CTime operator++(int);
};

CTime::CTime() {
this->gio = this->phut = this->giay = 0;
}
CTime::CTime(int h, int m, int s)
{
this->gio = h;
this->phut = m;
this->giay = s;
}
CTime::~CTime()
{
}

istream& operator>>(istream& is, CTime& T)
{
cout << “Nhap gio: “;
is >> T;
cout << “Nhap phut: “;
is >> T;
cout << “Nhap giay: “;
is >> T;
return is;
}
ostream& operator<<(ostream& os, const CTime& T)
{
os << T << ” gio ” << T << ” phut ” << T << ” giay “;
return os;
}

long CTime::GetTong()
{
return this->giay + this->phut * 60 + this->gio * 60 * 60;
}long CTime::GetTong()
{
return this->giay + this->phut * 60 + this->gio * 60 * 60;
}
CTime CTime::operator+(int a)
{
CTime Time;
Time = (this->GetTong() + a) / 3600;

Time = ((this->GetTong() + a – Time * 3600) / 60) % 60;
Time = (this->GetTong() + a) % 60;
return Time;
}
CTime CTime::operator++()
{
return *this + 1;
}

CTime CTime::operator++(int a)
{
CTime temp;
temp = *this;
*this + 1;
return temp;
}

[2019-2020]

HK2

Cho lớp Phân số (CPhanSo). Hãy khai báo và định nghĩa các ph°¡ng thức cần
thiết để các đối t°ợng thuộc lớp CPhanSo có thể thực hiện đ°ợc các câu lệnh
sau:

CPhanSo a(5, 3);

CPhanSo b, c, kq;

cin>>b>> c;

kq = a + b + 5 + c;

cout<<“Ket qua la: “<<kq;

if ( a==b )

cout<<“Phan so a bang phan so b”<<endl;

Giải:
HK2

#include<iostream>
using namespace std;
#pragma once
class PhanSo
{
private:

int ts, ms;
public:
PhanSo();
PhanSo(int a);
void Reduce();
PhanSo operator+(const PhanSo&);
bool operator==(PhanSo&);
friend istream& operator>>(istream& is, PhanSo& x);
friend ostream& operator<<(ostream& os, const PhanSo& x);
~PhanSo();
};

#include “PhanSo”
PhanSo::PhanSo() {
ts = 0;
ms = 1;
}
PhanSo::PhanSo(int a)
{
ts = a;
ms = 1;
}
void PhanSo::Reduce() {
int ucln;
int a = abs(ts);
int b = abs(ms);
if (ts == 0 && ms == 0) {
ucln = ts + ms;
}
else {
while (a != b) {
if (a > b) {
a -= b;
}
else
{
b -= a;
}
}
ucln = a;
}
ts /= ucln;
ms /= ucln;
}
PhanSo::~PhanSo()
{
}
PhanSo PhanSo::operator + (const PhanSo& y)
{
PhanSo temp;
temp = this->ts * y + y * this->ms;
temp = this->ms * y;
temp();
return temp;
}

bool PhanSo::operator ==(PhanSo& y)
{
float s1 = this->ts / this->ms;
float s2 = y / y;
if (s1 == s2)
return true;
return false;
}
istream& operator>>(istream& is, PhanSo& x)
{
cout << “Nhap tu so: “;
is >> x;
cout << “Nhap mau so: “;
is >> x;
return is;
}
ostream& operator<<(ostream& os, const PhanSo& x)
{
os << “Tu so: “;
os << x;
os << ” Mau so: “;
os << x;
return os;
}

CÂU 3.

[2013-2014]

HK1

Giả sử Tr°ßng ĐH CNTT TP đào tạo sinh viên theo 2 hệ là hệ cao đẳng
và hệ đại học. Thông tin cần quản lí của một sinh viên cao đẳng bao gồm: mã
số sinh viên, họ tên, địa chỉ, tổng số tín chỉ, điểm trung bình, điểm thi tốt
nghiệp. Thông tin cần quản lí của một sinh viên đại học bao gồm: mã số sinh
viên, họ tên, địa chỉ, tổng số tín chỉ, điểm trung bình, tên luận văn, điểm luận
văn.

Cách xét tốt nghiệp của sinh viên mỗi hệ là khác nhau:

  • Sinh viên hệ cao đẳng tốt nghiệp khi có tổng số tín chỉ từ 120 trá lên, điểm
    trung bình từ 5 trá lên và điểm thi tốt nghiệp phải đạt từ 5 trá lên.

  • Sinh viên hệ đại học tốt nghiệp khi có tổng số tín chỉ từ 170 trá lên, điểm
    trung bình từ 5 trá lên và phải bảo vệ luận văn với điểm số đạt đ°ợc từ 5 điểm
    trá lên.

Bạn hãy đề xuất thiết kế các lớp đối t°ợng cần thiết để quản lý danh sách các
sinh viên của Tr°ßng và hỗ trợ xét tốt nghiệp cho các sinh viên theo tiêu chí
đặt ra nh° trên.

Hãy viết ch°¡ng trình bằng C++ cho phép thực hiện các yêu cầu sau (5 điểm) :

  • Nhập vào danh sách sinh viên, có thể sử dụng string cho các chuỗi kí tự.

  • Cho biết số l°ợng sinh viên đủ điều kiện tốt nghiệp?

  • Cho biết sinh viên đại học nào có điểm trung bình cao nhất?

HK2

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à đầy 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 là 200 VNĐ. Ng°ßi ch¡i mua
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 vé từng

phần, giá vé là 70 VNĐ (giá vé vào cổng), ngoài ra, khi ng°ßi ch¡i tham
dự một trò ch¡i nào thì cần trả thêm 20 VNĐ cho trò ch¡i đó.

Hãy viết ch°¡ng trình bằng C++ cho phép thực hiện các chức năng sau:

a. Nhập vào danh sách các vé.

b. Tính tổng tiền vé mà công viên thu đ°ợc.

c. Hãy cho biết, có bao nhiêu vé đã bán là vé từng phần.

Yêu cầu:

Sử dụng tính chất kế thừa và đa hình. Vẽ s¡ đồ lớp: mô tả các lớp, các thuộc
tính, các ph°¡ng thức và mối liên hệ các lớp (2 điểm). Lập trình các chức năng
đ°ợc yêu cầu (3 điểm).

Giải:
HK1
  • S¡ đồ lớp đối t°ợng:

  • Ch°¡ng trình:

#include <bits/stdc++.h>

using namespace std;

class SinhVien
{
protected:
int MSSV;
string HoTen;
string DiaChi;
float DTB;
int TongSoTinChi;

public:
SinhVien() {}
~SinhVien() {}
virtual void Nhap();
virtual void Xuat();
virtual bool XetTotNghiep() = 0;
float getDTB() { return DTB; }
};

void SinhVien::Nhap()

{
cout << “Nhap thong tin sinh vien\n”;
cout << “Nhap MSSV: “;
cin >> MSSV;
cout << “Nhap HoTen: “;
cin >> HoTen;
cout << “Nhap DiaChi: “;
cin >> DiaChi;
cout << “Nhap DTB: “;
cin >> DTB;
cout << “Nhap So Tin Chi: “;
cin >> TongSoTinChi;
}

void SinhVien::Xuat()
{
cout << “Thong tin sinh vien\n”;
cout << “MSSV: ” << MSSV << “\n”;
cout << “HoTen: ” << HoTen << “\n”;
cout << “DiaChi: ” << DiaChi << “\n”;
cout << “DTB: ” << DTB << “\n”;
cout << “Tong So Tin Chi: ” << TongSoTinChi << “\n”;
}

class SinhVienCaoDang : public SinhVien
{
protected:
float DiemTotNghiep;

public:
SinhVienCaoDang() {}
~SinhVienCaoDang() {}
void Nhap();
void Xuat();
bool XetTotNghiep();
};

void SinhVienCaoDang::Nhap()
{
SinhVien::Nhap();
cout << “Diem tot nghiep: “;
cin >> DiemTotNghiep;
}

void SinhVienCaoDang::Xuat()
{
SinhVien::Xuat();
cout << “Diem tot nghiep: ” << DiemTotNghiep << “\n”;
}

bool SinhVienCaoDang::XetTotNghiep()
{
if (TongSoTinChi >= 120 and DTB >= 5)
return true;
else

return false;
}

class SinhVienDaiHoc : public SinhVien
{
protected:
string TenLuanVan;
float DiemLuanVan;

public:
SinhVienDaiHoc() {}
~SinhVienDaiHoc() {}
void Nhap();
void Xuat();
bool XetTotNghiep();
};

void SinhVienDaiHoc::Nhap()
{
SinhVien::Nhap();
cout << “Nhap ten luan van: “;
cin >> TenLuanVan;
cout << “Nhap diem luan van: “;
cin >> DiemLuanVan;
}

void SinhVienDaiHoc::Xuat()
{
SinhVien::Xuat();
cout << “Ten luan van: ” << TenLuanVan << “\n”;
cout << “Diem luan van: ” << DiemLuanVan << “\n”;
}

bool SinhVienDaiHoc::XetTotNghiep()
{
if (TongSoTinChi >= 170 and DTB >= 5 and DiemLuanVan >= 5)
return true;
else
return false;
}

int main()
{
cout << “Hello World!\n”; //TestCode
//cau 1
int SoLuongSinhVien;
cout << “Nhap so luong sinh vien: “;
cin >> SoLuongSinhVien;
SinhVien* arr[SoLuongSinhVien];
int loai;
for (int i = 0; i < SoLuongSinhVien; i++)
{
cout << “1. Sinh vien cao dang 2. Sinh vien dai hoc\n”;
cout << “Nhap loai sinh vien: “;
cin >> loai;

if (loai == 1)
arr[i] = new SinhVienCaoDang();
else
arr[i] = new SinhVienDaiHoc();
arr[i]->Nhap();
}
//cau 2
int SoLuongSinhVienTotNghiep = 0;
for (int i = 0; i < SoLuongSinhVien; i++)
{
if (arr[i]->XetTotNghiep() == true)
++SoLuongSinhVienTotNghiep;
}
cout << “SoLuongSinhVienTotNghiep: ” << SoLuongSinhVienTotNghiep;
//cau 3
float DiemCaoNhat = -1;
int pos;
for (int i = 0; i < SoLuongSinhVien; i++)
{
if (arr[i]->getDTB() > DiemCaoNhat)
{
DiemCaoNhat = arr[i]->getDTB();
pos = i;
}
}
cout << “Diem trung binh cao nhat la: ” << DiemCaoNhat << “\n”;
cout << “Sinh vien do la: “;
arr[pos]->Xuat();
return 0;
}

(Source: anhkiet1227)

HK2

  • S¡ đồ lớp đối t°ợng:

  • Ch°¡ng trình:

#include <bits/stdc++.h>
using namespace std;

class Ve
{
protected:
string MaVe, HoTen;
int NamSinh, SoTroChoi;
int GiaVe;
int SoLuongTroChoi;
public:
Ve() {}
~Ve() {}
virtual int getGiaVe() = 0;

virtual void Nhap();
virtual int getLoai() = 0;
};
void Ve::Nhap()
{
cout << “Nhap thong tin\n”;
cout << “Ma Ve: “;
cin >> MaVe;
cout << “Ho Ten: “;
cin >> HoTen;
cout << “Nam Sinh: “;
cin >> NamSinh;
cout << “So luong tro choi: “;
cin >> SoLuongTroChoi;
}

class VeTronGoi : public Ve
{
public:
VeTronGoi() {}
~VeTronGoi() {}
int getGiaVe()
{
return 200000;
}
void Nhap()
{
Ve::Nhap();
}
int getLoai() { return 1; }
};

class VeTungPhan : public Ve
{
public:
VeTungPhan() {}
~VeTungPhan() {}
int getGiaVe()
{
return 70000 + 20000 * SoLuongTroChoi;
}
void Nhap()
{
Ve::Nhap();
}
int getLoai() { return 2; }
};
int main()
{
cout << “Hello World!\n”;
//cau A
int SoLuongVe;
cout << “Nhap so luong ve: “;
cin >> SoLuongVe;
Ve* arr[SoLuongVe];

int loai;
for (int i = 0; i < SoLuongVe; i++)
{
cout << “Nhap loai ve: 1 Ve tron goi 2 Ve tung phan\n”;
cin >> loai;
if (loai == 1)
{
arr[i] = new VeTronGoi();
}
if (loai == 2)
{
arr[i] = new VeTungPhan();
}
arr[i]->Nhap();
}
//cau B
int TongTien = 0;
for (int i = 0; i < SoLuongVe; i++)
TongTien += arr[i]->getGiaVe();
cout << “Tong tien ve thu duoc: ” << TongTien << “\n”;
//cau C
int SoVeTungPhan = 0;
for (int i = 0; i < SoLuongVe; i++)
if (arr[i]->getLoai() == 2)
++SoVeTungPhan;
cout << “So luong ve tung phan: ” << SoVeTungPhan << “\n”;
return 0;
}

(Source: anhkiet1227)

[2014-2015]

HK2

Xây dựng ch°¡ng trình mô phỏng trò ch¡i cß t°ớng với các mô tả nh° sau:

Bàn cß là một hình chữ nhật do 9 đ°ßng dọc và 10 đ°ßng ngang cắt nhau
vuông góc tại 90 điểm hợp thành. Một khoảng trống gọi là sông (hay hà) nằm
ngang giữa bàn cß, chia bàn cß thành hai phần đối xứng bằng nhau.

Mỗi bên có một cung T°ớng hình vuông (Cung) do 4 ô hợp thành tại các
đ°ßng dọc 4, 5, 6 kể từ đ°ßng ngang cuối của mỗi bên, trong 4 ô này có vẽ
hai đ°ßng chéo xuyên qua.

LuÁt ch¢i

Quân cß đ°ợc di chuyển theo luật sau:

  1. T°ớng: Đi từng ô một, đi ngang hoặc dọc. T°ớng luôn luôn phải á trong
    phạm vi cung và không đ°ợc ra ngoài. Cung tức là hình vuông 2X2 đ°ợc đánh
    dấu bằng đ°ßng chéo hình chữ X

  2. Sĩ: Đi xéo 1 ô mỗi n°ớc. Sĩ luôn luôn phải á trong cung nh° T°ớng.

  3. T°ợng: Đi chéo 2 ô (ngang 2 và dọc 2) cho mỗi n°ớc đi. T°ợng chỉ đ°ợc
    phép á một bên của bàn cß, không đ°ợc di chuyển sang nửa bàn cß của đối
    ph°¡ng. N°ớc đi của t°ợng sẽ không hợp lệ khi có một quân cß nằm chặn
    giữa đ°ßng đi.

  4. Xe: Đi ngang hay dọc trên bàn cß miễn là đừng bị quân khác cản đ°ßng từ
    điểm đi đến điểm đến.

  5. Mã: Đi ngang 2 ô và dọc 1 ô (hay dọc 2 ô và ngang 1 ô) cho mỗi n°ớc đi.
    Nếu có quân nằm ngay bên cạnh mã và cản đ°ßng ngang 2 (hay đ°ßng dọc
    2), mã bị cản không đ°ợc đi đ°ßng đó.

  6. Pháo: Đi ngang và dọc giống nh° xe. Điểm khác biệt là nếu pháo muốn ăn
    quân, pháo phải nhảy qua đúng 1 quân nào đó. Khi không ăn quân, tất cả
    những điểm từ chỗ đi đến chỗ đến phải không có quân cản.

  7. Tốt: đi một ô mỗi n°ớc. Nếu tốt ch°a v°ợt qua sông, nó chỉ có thể đi thẳng
    tiến. Khi đã v°ợt sông rồi, tốt có thể đi ngang 1 n°ớc hay đi thẳng tiến 1 b°ớc
    mỗi n°ớc.

Áp dụng kiến thức lập trình h°ớng đối t°ợng (kế thừa, đa hình) thiết kế s¡ đồ
chi tiết các lớp đối t°ợng (1 điểm) , khai báo và định nghĩa các lớp gồm thuộc
tính và ph°¡ng thức (1 điểm) để thực hiện các yêu cầu sau:

  1. Tạo bàn cß ban đầu (với các mô tả nh° trên) (1 điểm).

  2. Yêu cầu ng°ßi dùng chọn một quân cß, xuất cách đi của quân cß t°¡ng ứng
    (1 điểm).

Lưu ý: Trong tr°ßng hợp sinh viên không ch¡i trò ch¡i này tr°ớc đây thì phải
đọc kỹ thông tin về trò ch¡i trên (các thông tin trên đủ để sinh viên thực hiện
các yêu cầu của đề thi) và nghiêm túc làm bài.

Giải:
HK2
  • S¡ đồ lớp đối t°ợng:

  • Ch°¡ng trình:

#include <bits/stdc++.h>

using namespace std;

class QuanCo
{
protected:
string mau;
int x, y;

public:
QuanCo(string mau, int x, int y)
{
this->mau = mau;
this->x = x;
this->y = y;
}

virtual void DiChuyen() = 0;
};

class Tuong_Vua : public QuanCo
{
public:
Tuong_Vua(string mau, int x, int y) : QuanCo(mau, x, y) {}

void DiChuyen()
{
cout << “Di tung o mot, di ngang hoac doc. Tuong luon luÙn phai o trong pham vi
cung va khong đ±ợc ra ngoai. Cung tuc la hinh vuong 2X2 duoc danh dau bang duong cheo
hinh chu X\n”;
}
};

class Si : public QuanCo
{
public:
Si(string mau, int x, int y) : QuanCo(mau, x, y) {}

void DiChuyen()
{
cout << “Di cheo 1 o moi nuoc. Si luon luon phai o trong cung.\n”;
}
};

class Tuong : public QuanCo
{
public:
Tuong(string mau, int x, int y) : QuanCo(mau, x, y) {}

void DiChuyen()
{
cout << “Di cheo 2 o (ngang 2 va doc 2) cho moi buoc di. Tuong chi duoc phep di
mot ben cua ban co khong duoc di chuyen sang nua ban co doi phuong. Nuoc di cua tuong se
khong hop le khi co mot quan nam giua duong di\n”;
}
};

class Ma :public QuanCo
{
public:
Ma(string mau, int x, int y) : QuanCo(mau, x, y) {}

void DiChuyen()
{
cout << “Di ngang 2 o va doc 1 o (hay doc 2 o va ngang 1 o) cho moi nuoc di. Neu
co quan nam ngay ben canh ma va can duong ngang 2 (hay duong doc 2), ma bi can khogn duoc
di duong do.\n”;
}
};

class Xe : public QuanCo
{
public:
Xe(string mau, int x, int y) : QuanCo(mau, x, y) {}

void DiChuyen()
{
cout << “Di ngang hay doc tren ban co mien la dung bi quan khac can duong di den
diem den.\n”;
}
};

class Phao : public QuanCo
{
public:
Phao(string mau, int x, int y) : QuanCo(mau, x, y) {}

void DiChuyen()
{
cout << “Di ngang va doc giong nhu xe. Diem khac biet la phao muon an quan co,
phao phai nhay qua 1 quan. Khi khong an quan, tat ca nhung diem tu cho di den den cho
phai den khong co quan can.\n”;
}
};

class Tot : public QuanCo
{
private:
string mau;
int x, y;
public:
Tot(string mau, int x, int y) : QuanCo(mau, x, y) {}

void DiChuyen()
{
cout << “Di mot o moi nuoc. Neu tot chua vuot song chi co the di thang tien. Khi
da vuot song roi, tot co the di ngang hoac thang 1 buoc.\n”;
}
};

int main()

{
// Cau 1
QuanCo* a[32];
string trang = “trang”;
string den = “den”;
cout << “Khoi tao ban co\n”;
a[0] = new Tuong_Vua(trang, 1, 5);
a[1] = new Tuong_Vua(den, 10, 5);
a[2] = new Si(trang, 1, 4);
a[3] = new Si(trang, 1, 6);
a[4] = new Si(den, 10, 4);
a[5] = new Si(den, 10, 6);
a[6] = new Ma(trang, 1, 2);
a[7] = new Ma(trang, 1, 8);
a[8] = new Ma(den, 10, 2);
a[9] = new Ma(den, 10, 8);
a[10] = new Xe(trang, 1, 1);
a[11] = new Xe(trang, 1, 9);
a[12] = new Xe(den, 10, 1);
a[13] = new Xe(den, 10, 9);
a[14] = new Phao(trang, 3, 2);
a[15] = new Phao(trang, 3, 8);
a[16] = new Phao(den, 8, 2);
a[17] = new Phao(den, 8, 8);
a[18] = new Tot(trang, 4, 1);
a[19] = new Tot(trang, 4, 3);
a[20] = new Tot(trang, 4, 5);
a[21] = new Tot(trang, 4, 7);
a[22] = new Tot(trang, 4, 9);
a[23] = new Tot(den, 7, 1);
a[24] = new Tot(den, 7, 3);
a[25] = new Tot(den, 7, 5);
a[26] = new Tot(den, 7, 7);
a[27] = new Tot(den, 7, 9);
a[28] = new Tuong(trang, 1, 3);
a[29] = new Tuong(trang, 1, 7);
a[30] = new Tuong(den, 10, 3);
a[31] = new Tuong(den, 10, 7);

// Cau 2
cout << “Nhap quan co muon di chuyen, tu 0 – 31 \n”;
int CoDuocChon;
cin >> CoDuocChon;
a[CoDuocChon]->DiChuyen();
return 0;
}

(Source: anhkiet1227)

[2015-2016]

HK2

Xây dựng ch°¡ng trình mô phỏng biên soạn nhạc với các mô tả ký kiệu âm
nhạc nh° sau:
Nốt nhạc: là ký hiệu trong bản nhạc dùng để xác định cao độ (độ cao), trường
độ (độ dài, độ ngân vang) của từng âm thanh đ°ợc vang lên trong bản nhạc.

Có 7 ký hiệu nốt nhạc dùng để
xác định cao độ theo thứ tự từ
thấp đến cao, đó là Đô (C), Rê
(D), Mi (E), Fa (F), Sol (G), La
(A), và Si (B).
Để xác định tr°ßng độ của nốt nhạc có cao độ kể trên, ng°ßi ta cũng dùng 7
hình nốt để thể hiện, đó là:

Dấu lặng (Z – Zero) là ký hiệu cho biết phải ng°ng, không diễn tấu âm thanh
(không có cao độ) trong một thßi gian nào đó. Các dấu lặng trong thßi gian
t°¡ng ứng (giá trị tr°ßng độ) với dạng dấu nhạc nào, thì cũng có tên gọi t°¡ng
tự.

Tr°ßng độ 4 2 1 1/2 1/4 1/8 1/16

Ví dụ: Ký hiệu bản nhạc

Tr°ờng
độ

1 1/2 1/2 1/2 1 1/2 1 1 2

Cao độ C C A G
Không
có (Z)

D C C F

Nốt
Đô
đen

Đô
móc
đ¡n

La
móc
đ¡n

Sol
móc
đ¡n

Dấu
lặng
đen


móc
đ¡n

Đô
đen

Đô
đen

Fa
trắng

Áp dụng kiến thức lập trình h°ớng đối t°ợng (kế thừa, đa hình) thiết kế s¡ đồ
chi tiết các lớp đối t°ợng (1 điểm) và xây dựng ch°¡ng trình thực hiện các
yêu cầu sau:

  1. Soạn một bản nhạc. (1 điểm)

  2. Tìm và đếm có bao nhiêu dấu lặng đen (Q) trong bản nhạc. (1 điểm)

  3. Cho biết nốt nhạc có cao độ cao nhất trong bản nhạc. (1 điểm)

Lưu ý: Trong tr°ßng hợp sinh viên không biết về nhạc lý tr°ớc đây thì phải
đọc kỹ thông tin trên (các thông tin trên đủ để sinh viên thực hiện các yêu cầu
của đề thi) và nghiêm túc làm bài. Giám thị coi thi không giải thích gì thêm.

HK3

Xây dựng ch°¡ng trình mô phỏng game võ lâm truyền kì với các mô tả nh°
sau:

Võ lâm truyền kì là một tựa game theo phong cách nhập vai kiếm hiệp xuất
hiện từ những ngày đầu trên thị tr°ßng game online Việt Nam. Trong game,

ng°ßi ch¡i có thể t°¡ng tác với nhau để giải trí hoặc tiêu diệt quái vật để phát
triển nhân vật của mình.

Nhân vật: Đ°ợc xem nh° đại diện cho một ng°ßi ch¡i. Mỗi nhân vật thuộc về
một môn phái nào đó trong tổng số 10 môn phái của game. Một nhân vật có
một giá trị thể hiện cấp độ và mức sát th°¡ng. Trong đó Sát th°¡ng = Cấp độ
x 5

Quái vật: Để gia tăng cấp độ nhân vật của mình, mỗi ng°ßi ch¡i sẽ thông qua
việc tiêu diệt các quái vật. Có hai loại quái vật : thông th°ßng và đầu lĩnh. Các
quái vật cũng sẽ có khả năng tấn công lại ng°ßi ch¡i. Quái vật thông th°ßng:
Sát th°¡ng = Cấp độ x 3. Quái vật đầu lĩnh: Sát th°¡ng = Cấp độ x 7.

Một nét đặc sắc của game đó là hệ thống ngũ hành t°¡ng sinh t°¡ng khắc,
mỗi một môn phái và quái vật sẽ thuộc về một <hành= nhất định và t°¡ng tác
giữa các ng°ßi ch¡i với nhau, giữa ng°ßi ch¡i với quái vật đều dựa trên các
quy tắc về ngũ hành.

Quy tắc tương sinh : (S) Sát th°¡ng gây ra cho ng°ßi ch¡i hoặc quái vật + 10
%

Ví dụ: Hoả sinh thổ, sát th°¡ng ng°ßi ch¡i (hoặc quái vật ) hệ hoả gây ra cho
ng°ßi ch¡i (hoặc quái vật) hệ thổ + 10 %

Quy tắc tương khắc : (K) Sát th°¡ng gây ra cho ng°ßi ch¡i hoặc quái vật ±
20 %

Ví dụ: Mộc khắc thổ, sát th°¡ng ng°ßi ch¡i (hoặc quái vật ) hệ mộc gây ra
cho ng°ßi ch¡i (hoặc quái vật) hệ thổ + 20 %. Ng°ợc lại, sát th°¡ng ng°ßi
ch¡i (hoặc quái vật) hệ thổ gây ra cho ng°ßi ch¡i (hoặc quái vật) hệ mộc – 20
%

Áp dụng kiến thức lập trình h°ớng đối t°ợng (kế thừa, đa hình) thiết kế s¡ đồ
chi tiết các lớp đối t°ợng (1 điểm) và xây dựng ch°¡ng trình thực hiện các
yêu cầu sau:

  1. Tạo và quản lý một danh sách các ng°ßi ch¡i và quái vật. (1 điểm)

  2. Cho biết ph