You are on page 1of 19

TRƯỜNG ĐẠI HỌC CÔNG NGHỆ GTVT

KHOA CÔNG NGHỆ THÔNG TIN


-----o0o-----

BÁO CÁO BÀI TẬP NHÓM MÔN HỌC C++

NHÓM SINH VIÊN: BÙI ĐỨC HUỲNH


PHAN THỊ NHƯ HẬU
LỚP: 70DCHT23

HÀ NỘI 6 - 2021
I. Lý thuyết cơ sở.
I.1. Lập trình hướng đối tượng có mấy đặc trưng( mỗi đặc trưng cho một ví
dụ).
 Tính trừu tượng: (Abstraction).
− Tính trừu tượng là tính chất không thể hiện cụ thể mà chỉ nêu tên vấn đề. Đó là
một quá trình che giấu các hoạt động bên trong và chỉ hiển thị những tính năng
thiết yếu của đối tượng tới người dùng.
− Ví dụ: một người sử dụng điện thoại để gửi tin nhắn thì anh ta sẽ nhập nội dung
tin nhắn, thông tin người nhận và ấn nút gửi. Khi anh ta bắt đầu gửi tin thì anh
ấy không biết những gì diễn ra bên trong quá trình gửi mà chỉ biết được là kết
quả của tin nhắn đã được gửi đến người nhận thành công hay chưa.
− Tính trừu tượng giúp chúng ta giảm sự phức tạp. Có hai cách thực hiện tính trừu
tượng như bên dưới:
• Lớp trừu tượng (Abstract Class).
• Giao diện (Interface).
 Tính đóng gói:
− Đóng gói là sự che giấu bên trong dữ liệu riêng của mỗi đối tượng của lớp được
khai báo và chỉ được truy xuất thông qua hệ thống các phương thức có sẵn của
lớp.
− Đặc điểm:
• Tạo ra cơ chế để ngăn ngừa việc gọi phương thức của lớp này tác động hay truy
xuất dữ liệu của đối tượng thuộc về lớp khác.
• Dữ liệu riêng (khi được khai báo là private) của mỗi đối tượng được bảo vệ
khỏi sự truy xuất không hợp lệ từ bên ngoài.
• Người lập trình có thể dựa vào cơ chế này để ngăn ngừa việc gán giá trị không
hợp lệ vào thành phần dữ liệu của mỗi đối tượng.
• Cho phép thay đổi cấu trúc bên trong của một lớp mà không làm ảnh hưởng đến
những lớp bên ngoài có sử dụng lớp đó.
Để cài đặt tính đóng gói, chúng ta có 2 bước như sau:
• Khai báo các thuộc tính của đối tượng trong lớp là private để các lớp khác
không thể truy cập trực tiếp/sửa đổi được.
• Cung cấp các phương thức getter/setter có phạm vi truy cập là public.
 Tính kế thừa:
− Cho phép xây dựng một lớp mới dựa trên các định nghĩa của một lớp đã có.
1
− Lớp đã có gọi là lớp Cha, lớp mới phát sinh gọi là lớp Con .
− Lớp con kế thừa tất cả các thành phần của lớp Cha, có thể mở rộng các thành
phần kế thừa và bổ sung thêm các thành phần mới.
− Ví dụ: Ta có sẵn một lớp thực vật. Ta xây dựng lớp cây xoài dựa trên lớp thực
vật (protected).

 Tính đa hình (polymorphism): Đa hình có nghĩa là nhiều hình thức, trong đó


‘poly’ có nghĩa là nhiều, còn ‘morph’ có nghĩa là hình thức.
Ví dụ: Khi bạn ở trong trường học là sinh viên thì bạn có nhiệm vụ học, nghe
giảng,...
I.2. Lớp là gì? Cho ví dụ.
A. khái niệm.
 Lớp là một khái niệm trừu tượng, dùng để chỉ một tập hợp các đối tượng có mặt
trong hệ thống.
 Ví dụ:
− Các chiếc xe Toyota, Honda, Porsche thuộc lớp xe hơi.
− Các con chó giữ nhà, chó săn, chó kiểng thuộc lớp chó.

2
 Lớp có thuộc tính (property) và phương thức (method):
− Thuộc tính của lớp tương ứng với thuộc tính của đối tượng.
− Phương thức của lớp tương ứng với các hành động của đối tượng.
 Một Lớp có thể có một trong các khả năng sau:
− Hoặc chỉ có thuộc tính, không có phương thức.
− Hoặc chỉ có phương thức, không có thuộc tính.
− Hoặc có cả thuộc tính và phương thức, trường hợp này là phổ biến nhất.
I.3. Nêu các phương thức có thể có trong lớp.
- Phương thức (hàm) tạo (Constructor)
- Hàm tạo có đối số.
- Hàm tạo không đối số.
- Phương thức (hàm) hủy (Destructor)
- Con trỏ This
- Phương thức getter, setter
I.4. Cú pháp của phương thức.
- Có hai loại là ngoài lớp và trong lớp:
+ Ngoài lớp: <kiểu trả về > tên lớp::<tên_phương thức>([đối sô])
{
// <thân hàm>
}
+ Trong lớp: <Kiểu trả về> <Tên phương thức> ([<Các tham số>]){…}
I.5. Getter, setter là gì? Cho ví dụ.
- Khái niệm:
 Ta cần xây dựng các getter/setter để truy suất giá trị các thuộc tính (vì thuộc
tính có phạm vi truy xuất private).
 Set: truyền giá trị vào cho biến.
 Get: lấy giá trị của biến.
- Ví dụ:
#include <iostream>
using namespace std;
class Employee {
  private:
3
    // Private attribute
    int salary;
  public:
    // Setter
    void setSalary(int s) {
      salary = s;}
// Getter
    int getSalary() {
      return salary;
    }
};
int main() {
  Employee myObj;
  myObj.setSalary(50000);
  cout << myObj.getSalary();
  return 0;
}
I.6. Nạp chồng toán tử là gì? Vì sao phải nạp chồng.
Nạp chồng toán tử:
+ Là khả năng một toán tử có thể thực hiện việc tính toán ứng với nhiều
kiểu dữ liệu khác nhau.
+ Các toán tử có thể được định nghĩa chồng như một phương thức của
lớp hoặc như hàm bạn của lớp.
Phải nạp chồng vì: chúng ta xử lí các câu lệnh ở main trở nên tường minh
và dễ hiểu hơn cho cả người code lẫn người đọc, do đó nó rất là quan trọng. Vì vậy
các bạn nên học và sử dụng chúng thường xuyên hơn.

I.7. Phân biệt phương thức tĩnh, ảo, thuần ảo.


+ Phương thức ảo: Những phương thức được khai báo từ khóa virtual ở lớp
cha. Khi đó lớp con kế thừa lại từ nó cũng cài đặt phương thức “Trùng tên” để
cho phép có thể nạp chồng lại được.
+ Phương thức thuần ảo: Cung cấp một phương thức thống nhất làm giao diện
chung. Khi sử dụng phương thức thuần ảo: Lớp cha không có thông tin nào để
tính toán thì ta sử dụng thuần ảo để cho các lớp con đảm nhận nhiệm vụ tính toán
đó.
+Phương thức tĩnh: là phương thức được sử dụng phổ biến nhất không sử dụng
bát cứ từ khóa nào trong cú pháp của phương thức thông thường.
4
I.8. Kế thừa là gì có mấy loại kế thừa, mục đích của kế thừa. cho ví dụ.
-Các loại kế thừa:
1. Đơn kế thừa(Single Inheritance):
-Đơn kế thừa: nghĩa là một lớp chỉ được kế thừa đúng một lớp khác. Hay
nói cách khác, lớp con chỉ có duy nhất lớp cha.
-Cú Pháp:
class lopcon: phamvidulieu lopcha
{
//nội dung lớp con
};
-Ví dụ:
#include <iostream>
using namespace std;
// Lớp cha
class Mayvitinh
{
public:
Mayvitinh()
{
cout << "This is a computer" << endl;
}
};
// Lớp con kế thừa từ lớp cha
class mayAcer : public Mayvitinh
{
};
// main function
int main()
{

5
mayAcer may1;
return 0;
}
2. Đa kế thừa(Multiple Inheritance):
Đa kế thừa là một tính năng của ngôn ngữ C++. Trong đó một lớp có thể kế
thừa từ nhiều hơn một lớp khác. Nghĩa là một lớp con được kế thừa từ nhiều
hơn một lớp cơ sở
-Cú Pháp :
class lopcon:phamvitruycap lopcha1, phamvitruycap lopcha2, ...
{
// nội dung của lớp con
};
-Ví dụ:
#include <iostream>
using namespace std;
// Lớp cơ sở thứ nhất
class Mayvitinh
{
public:
Mayvitinh()
{
cout << "This is a computer's brand" << endl;
}
};
// Lớp cơ sở thứ hai
class Maylaptop
{
public:
Maylaptop()
{
cout << "This is a laptop's brand" << endl;
6
}
};
// Lớp con kế thừa từ 2 lớp cha
class mayAcer : public Mayvitinh, public Maylaptop
{
};
// main function
int main()
{
mayAcer may1;
return 0;
}
3. Kế thừa đa cấp (Multievel Inheritance):
Kế thừa đa cấp: Trong kiểu thừa kế này, một lớp dẫn xuất được tạo từ một
lớp dẫn xuất khác.
-Ví dụ:
#include <iostream>
using namespace std;
// Lớp cha
class Mayvitinh
{
public:
Mayvitinh()
{
cout << "This is a computer's brand" << endl;
}
};
// Lớp con kế thừa từ lớp cha
class Maylaptop : public Mayvitinh
{

7
public:
Maylaptop()
{
cout << "This is a laptop's brand" << endl;
}
};
// Lớp con kế thừa từ lớp cha thứ 2
class mayAcer : public Maylaptop
{
public:
mayAcer(){
cout << "This brand is Acer" << endl;
}
};
// main function
int main()
{
mayAcer may1;
return 0;
}
4. Kế thừa phân cấp (Hierarchical Inheritance):
Kế thừa phân cấp: Trong kiểu kế thừa này, sẽ có nhiều hơn một lớp con
được kế thừa từ một lớp cha duy nhất.
Ví dụ:
#include <iostream>
using namespace std;
// Lớp cha
class Mayvitinh
{
public:

8
Mayvitinh()
{
cout << "This is a computer's brand" << endl;
}
};
// Lớp con thứ nhất
class mayAsus : public Mayvitinh
{
};
// Lớp con thứ hai
class mayAcer : public Mayvitinh
{
};
// main function
int main()
{
mayAcer may1;
mayAsus may2;
return 0;
}
5. Kế thừa lai (Kế thừa ảo) – Hybrid (Virtual) Inheritance:
Kế thừa lai( Kế thừa ảo): được thực hiện bằng cách kết hợp nhiều hơn một
loại thừa kế.
Ví dụ:
#include <iostream>
using namespace std;
// Lớp cha
class Mayvitinh
{
public:

9
Mayvitinh()
{
cout << "This is a computer's brand" << endl;
}
};
// Lớp cha
class Maylaptop
{
public:
Maylaptop()
{
cout << "This is a laptop's brand" << endl;
}
};
// Lớp con thứ nhất
class mayAcer : public Mayvitinh
{
};
// Lớp con thứ hai
class mayAsus : public Mayvitinh, public Maylaptop
{
};
// main function
int main()
{
mayAsus may1;
mayAcer may2;
return 0;
}

10
I.9. Đa hình là gì. Cho ví dụ.
 Sự kế thừa trong LTHĐT cho phép có sự tương ứng giữa lớp cơ sở và các lớp
dẫn xuất trong sơ đồ kế thừa.
 Một con trỏ có kiểu lớp cơ sở luôn có thể trỏ đến địa chỉ của một đối tượng của
lớp dẫn xuất.
Phương thức của lớp mà con trỏ có kiểu được gọi chứ không phải phương thức
của đối tượng mà con trỏ đang trỏ tới được gọi.
Để giải quyết vấn đề này, LTHĐT đưa ra một khái niệm:
Phương thức của lớp cha khi thực hiện sẽ được thay thế bằng một phương thức
của lớp con thì phương thức này gọi là có tính đa hình.
Tính đa hình giúp cho việc lập trình đơn giản và dễ mở rộng. Để cài đặt phương
thức có tính đa hình ta dùng phương thức ảo và phương thức thuần ảo.
Có hai loại đa hình:
a) Phương thức ảo
Những phương thức được khai báo từ khóa virtual ở lớp cha. Khi đó lớp con kế
thừa lại từ nó cũng cài đặt phương thức “Trùng tên” để cho phép có thể nạp
chồng lại được.
Cú pháp ở lớp cha: virtual<Kiểu dữ liệu><Tên phương thức>(danh sách tham
số nếu có);
Tác dụng từ khóa virtual:
+ Cho phép các lớp con nạp chồng lại được phương thức có trùng tên của lớp cha
(tức là ta new ra đối tượng con nào thì khi trỏ tới phương thức trùng tên, nó sẽ
hiểu là gọi vào phương thức của đối tượng con đó).
+ Nếu lớp cha không cài đặt từ khóa virtual thì new ra bất kỳ lớp con nó luôn
luôn vẫn gọi về lớp cha.
Ví dụ:
#include <iostream>
using namespace std;
class inDuLieu
{
public:
void hamIn(int i) {
cout << "In so nguyen: " << i << endl;
11
}
void hamIn(double f) {
cout << "In so thuc: " << f << endl;
}
void hamIn(string s) {
cout << "In chuoi: " << s << endl;
}
};
int main(void)
{
inDuLieu idl;
// Goi ham hamIn de in so nguyen
idl.hamIn(1235);
// Goi ham hamIn de in so thuc
idl.hamIn(67.02);
// Goi ham hamIn de in chuoi
idl.hamIn("Codelearn.io");
return 0;
}
b) Phương thức thuần ảo
Mục đích:
-Tránh lãng phí bộ nhớ.
-Cung cấp một phương thức thống nhất làm giao diện chung.
Khai báo lớp cha:
virtual <kiểu dữ liệu> <tên phương thức>([tsố])=0;
Khi sử dụng phương thức thuần ảo: Lớp cha không có thông tin nào để tính toán
thì ta sử dụng thuần ảo để cho các lớp con đảm nhận nhiệm vụ tính toán đó.
Lưu ý: Khi lớp cha sử dụng phương thức thuần ảo thì bắt buộc “tất cả” mọi lớp
con đều phải cài đặt cho nó, nếu có lớp con nào không cài đặt thì khi new lớp
con đó chương trình sẽ bị lỗi.
Ví dụ:
12
class A
{
public:
virtual void nhap()
{
cout<<"\nNhap lop A";
}
virtual void xuat()
{
cout << "\n Lop A " ;
}
};
class B:public A
{
public:
void nhap()
{
cout<<"\nNhap lop B";
}
void xuat()
{
cout << "\n Lop B " ;
}
class C:public A
{
public:
void nhap()
{
cout<<"\nNhap lop C";
}
13
void xuat()
{
cout << "\n Lop C " ;
}
};
main()
{
A *p =new C;
p->nhap() ;
p->xuat() ;
}
I.10. Interface là gì? Cho ví dụ.
- Khái niệm:
Giao diện (Interface): là một chức năng mà ta có thể thêm và bất kì class nào.
Chức năng ở đây không đồng nghĩa với phương thức (hoặc hàm).
Interface có thể bao gồm nhiều hàm/phương thức và tất cả chúng cùng phục vụ
cho một chức năng.
Interface không phải là lớp. Các lớp dẫn xuất từ 1 Interface đều phải định nghĩa
đầy đủ các phương thức và thuộc tính kế thừa từ Interface
Ví dụ: lớp cha cung cấp một Interface tới lớp cơ sở để triển khai một
hàm tinhDienTich().
#include <iostream>
using namespace std;
// day la lop co so (base class)
class Hinh
{
public:
// khai bao pure virtual function
virtual int tinhDienTich() = 0;
void setChieuRong(int rong)
{

14
chieurong = rong;
}
void setChieuCao(int cao)
{
chieucao = cao;
}
protected:
int chieurong;
int chieucao;
};
// cac lop ke thua
class HinhChuNhat: public Hinh
{
public:
int tinhDienTich()
{
return (chieurong * chieucao);
}
};
class TamGiac: public Hinh
{
public:
int tinhDienTich()
{
return (chieurong * chieucao)/2;
}
};
int main(void)
{
HinhChuNhat hcn;
15
TamGiac tag;
hcn.setChieuRong(25);
hcn.setChieuCao(4);
// in dien tich cua doi tuong
cout << "Tong dien tich HinhChuNhat la: " << hcn.tinhDienTich() << endl;
tag.setChieuRong(20);
tag.setChieuCao(15);
// in dien tich cua doi tuong.
cout << "Tong dien tich TamGiac la: " << tag.tinhDienTich() << endl;
return 0;
}
II. Bài tập.
Câu 16: Viết chương trình thực hiện các yêu cầu sau:
1. Khai báo lớp hình vuông với thuộc tính: độ dài cạnh.
Khai báo lớp hình chữ nhật kế thừa từ lớp hình vuông và thêm thuộc tính: độ dài
cạnh thứ 2.
2. Xây dựng các phương thức: nhập, xuất, tính chu vi, diện tích hình vuông, hình chữ
nhật.
3. Nhập vào n hình vuông. In ra màn hình hình vuông có diện tích lớn nhất và vị trí
của hình vuông đó trong danh sách vừa nhập.

#include<iostream>
using namespace std;
class hinhvuong
{
protected:
double ddc;//khai báo thuộc tính
public:
//phương thức nhập
void nhap(){
do{
cout<<"\nNhap do dai canh: ";cin>>ddc;
if(ddc<=0) cout<<"\nNhap lai!!(canh>0)";
}
while(ddc<=0);}
//phương thức xuất
16
void xuat(){
cout<<"Do dai canh vua nhap la: "<<ddc;
}
// phương thức tính chu vi
double tinhCV(){
return ddc*4;
}
// phương thức tính diện tích
double tinhS(){
return ddc*ddc;
}
};
class hinhchunhat:public hinhvuong{
private:
double ddc2; ;//khai báo thuộc tính
public:
//phương thức nhập
void nhap(){
hinhvuong::nhap();
do{
cout<<"\nNhap do dai canh 2: ";cin>>ddc2;
if(ddc2<=0) cout<<"\nNhap lai!!(canh>0)";
}
while(ddc2<=0);
}
//phương thức xuất
void xuat(){
hinhvuong::xuat();
cout<<"\nDo dai canh thu 2: "<<ddc2;
}
double tinhCV(){
return (ddc+ddc2)*2;
}
double tinhS(){
return ddc*ddc2;
}
};
int main(){
int n;

17
cout<<"\nNhap so hinh vuong: ";cin>>n;
hinhvuong *a;// khai báo mảng a
a = new hinhvuong[n]; //cấp phát bộ nhớ mảng động
for(int i =0;i<n;i++){
cout<<"\nNhap hinh vuong thu "<<i+1;
a[i].nhap();
}
double max=0;
// tìm diện tích lớn nhất
for(int i=0;i<n;i++){
if (a[i].tinhS()>max) max=a[i].tinhS();
}
cout<<"\nDien tich hinh vuong lon nhat la: "<<max;
//tìm vị trí hình vuông lớn nhất
for (int i=0;i<n;i++){
if(a[i].tinhS()==max) cout<<"\nVi tri: "<<i+1;
}
}

18

You might also like