Khi một tình huồng ngoại lệ xảy ra, chương trình sẽ nhảy đến các khối mã được xác định trước, được gọi là các khối "catch", để xử lý tỉnh huống đó.. Có 2 loai Exception: —_ Đông bộ: Ngoạ
Trang 1
IE
BỘ GIÁO DỤC & ĐÀO TẠO TRƯỜNG ĐẠI HỌC KHOA HỌC TỰ NHIÊN, ĐHQG-HCM
KHOA CONG NGHE THONG TIN
«2 LLll«»
yar KHO4
N: o “a
BTLT-Group-W09-10
Bộ môn: Phương pháp lập trình hướng đối tượng
Mã lớp: CQ2022/5
GVHD: Hỗ Tuan Thanh
Tên nhóm: See2plus
Thành viên:
Nguyễn Đăng Trí MSSV: 22120383
Nguyén Van Ty MSSV: 22120419 Pham Tuan Anh MSSV: 22120452
Trang 2BTLT-Group-W09-10 GVHD: H6 Tuan Thanh
Muc luc
SECTION 1: Phan công nhiệm vụ và đánh giả mức độ hoàn thành 1
Trang 3BTLT-Group-W09-10 GVHD: H6 Tuan Thanh
SECTION 1: Phan cong nhiém vụ và dánh giá mức độ hoàn thành
1 (24) Tim hiéu vé exception handling
trong C++ Cho vi du minh hoa
Pham Tuan Anh 100%
2 (28) Tim hiéu ít nhất 5 class trong
std:exception Cho vi dy minh họa
Trần Anh Tú 100%
3 (24) Tim hiéu nguyén ly L trong SOLID
principles Cho vi dy minh hoa thực
tê
4(28) Tìm hiệu nguyên lý I trong SOLID
principles Cho ví dy minh hoa thực
tê
Nguyễn Văn Tý 100%
5 (28) Tìm hiệu nguyên lý D trong SOLID
principles Cho ví dy minh hoa thực
z A
te
Đỗ Thái Hoc 100%
Phân công nhiệm vụ, giám sát,
kiêm tra quá trình làm bài của các
thành viên trong nhóm Kiểm tra
bài làm, tổng hợp bài làm và viết
báo cáo
Trang 4
BTLT-Group-W09-10 GVHD: H6 Tuan Thanh
SECTION 2: Noi dung bai lam
Exception handling la gi?
Exception handling trong C++ là một cơ chế cho phép xử lý các tình huống ngoại lệ trong quá trình thực thi chương trình Khi một tình huồng ngoại lệ xảy ra, chương trình sẽ
nhảy đến các khối mã được xác định trước, được gọi là các khối "catch", để xử lý tỉnh
huống đó Điều này giúp chương trình có thể kiêm soát và xử lý các tình huống không mong muôn mà không cần phải dừng hoàn toàn hoặc crash
Có 2 loai Exception:
—_ Đông bộ: Ngoại lệ xảy ra khi có sự cô xảy ra do lỗi trong dữ liệu đầu vào hoặc
khi chương trình không được trang bị để xử lý loại dữ liệu hiện tại mà nó đang làm việc, chăng hạn như chia số cho không
— Không đồng bộ: Các ngoại lệ nằm ngoài tầm kiểm soát của chương trình, chẳng hạn như lỗi đĩa, ngắt bàn phím, v.v
C++ try and catch
C++ cung cap mét tinh nang san co cho Xtrly ngoailé No co thé duoc thyc hién bang cách sử dung cac tr khéa chuyén nganh sau: “try”, “catch” va “throw” voi méi từ
khóa có một mục đích khác nhau
—_ “Try” trong C++: đại điện cho một khối mã có thể ném một ngoại lệ được đặt
bên trong khối thử Tiếp theo là một hoặc nhiều khối bắt Nếu một ngoại lệ xảy
ra, hãy thử chặn ném ngoại lệ đó
—_ “Catch” trong C++: đại diện cho một khối mã được thực thi khi một ngoại lệ cụ
thê được ném ra khỏi khối thử Mã đề xử lý ngoại lệ được viết bên trong khối bắt
— “Throw” trong C++: Dugc su dung dé ném một ngoại lệ Cũng được sử dụng dé
liệt kê các trường hợp ngoại lệ mà một hàm ném ra, nhưng không xử lý chính nó
Trang 5BTLT-Group-W09-10 GVHD: H6 Tuan Thanh
Uu diém:
— Tach ma xtr ly 16i khdi ma thong thuong: Trong cac mA xtr ly lỗi truyền thống, luôn có các điều kiện khác đề xử lý lỗi Các điều kiện này và mã để xử lý lỗi được trộn lẫn với luồng bình thường Điều này làm cho mã ít đọc và có thể duy trì Với các khối try - catch, mã đề xử lý lỗi trở nên tách biệt với luồng thông thường
— Function / methods co thé xtr ly bat kỳ ngoại lệ nào họ chọn: Một hàm có thé đưa
ra nhiều ngoại lệ, nhưng có thể chọn xử ly một số ngoại lệ Các ngoại lệ khác
được ném, nhưng không bắt được có thê được xử lý bởi người gọi Nếu người gọi chọn không bắt chúng, thì các ngoại lệ được xử lý bởi người gọi của người gọi
Trong C++, mét function có thê chỉ định các ngoại lệ mà nó ném bằng cách sử
dụng từ khóa throw Người gọi hàm này phải xử lý ngoại lệ theo một cách nào đó (bằng cách chỉ định lại hoặc bắt nó)
—_ Nhóm các loại lỗi: Trong C++, cả loại và đối tượng cơ bản đều có thê được ném
thành ngoại lệ Chúng ta có thê tạo một hệ thông phân cấp của các đôi tượng ngoại
lệ, ngoại lệ nhóm trong không gian tên hoặc lớp, phân loại chúng theo các loại
Ví dụ:
Trang 6BTLT-Group-W09-10 GVHD: H6 Tuan Thanh
//Các test case khác
//process(-1);
//process(101);
//process(10);
Trong ví dụ nay, ham process kiém tra nhiéu diéu kién khac nhau dé sinh ra các loại ngoại lệ khác nhau Trong hàm main(), chúng ta sử dụng một khối try-catch đề bắt các loại ngoại lệ được sinh ra bởi hàm process Các loại ngoại lệ cụ thể như "unt ime_ error, out_of_range, và overflow_error đều là các lớp con của lớp cơ sở exception, vì vậy chúng ta có thê bắt chúng bằng cách sử dụng một khối catch đa dạng
Ngoài ra, chúng ta cũng có một khối catch cuỗi cùng mà không có thông tin về loại ngoại lệ cu thé (catch ( )), điều này đảm bảo rằng bất kỳ ngoại lệ nào không được xác định trước cũng sẽ được bắt và xử lý
Trang 7BTLT-Group-W09-10 GVHD: H6 Tuan Thanh Kết quả khi hàm process truyền số 0:
2.1 class logic_error
Xác định một loại đỗi tượng được ném ra nhự một ngoại lệ Nó báo cáo các lỗi là hậu
quả của lỗi logic trong chương trình, chăng hạn như vi phạm các điều kiện tiên quyết logic hoặc bắt biến lớp và có thê phòng ngừa được
Member Functions:
— Constructor: khoi tao | logic error object voi thong bao đã có
— Operator=: Thay thé logic error object
Trang 8BTLT-Group-W09-10 GVHD: H6 Tuan Thanh
Ví dụ:
students // Ham at() sẽ ném ra một logic error néu
chi s6 ngoai gidi han
Caught a logic error: invalid vector subscript
2.2, class bad_typeid
Một ngoại lệ của loại này được đưa ra khi toán tử typeid được áp dụng cho giá trị con
trỏ null được tham chiếu của loại đa hình
Member Functions:
— Constructor: khéi tao 1 bad_typeid moi
— operator=: thay thé bad_typeid
— what: tra vé chudi giải thích
Trang 9BTLT-Group-W09-10 GVHD: H6 Tuan Thanh
Ví dụ:
Trang 10BTLT-Group-W09-10 GVHD: H6 Tuan Thanh
Caught a logic error: Attempted a typeid of nullptr pointer!
2.3 class bad_cast
Một ngoại lệ của loại này dugc ném ra khi dynamic cast véi mét loai tham chiéu khong thanh céng trong thdi gian chay va ca tir std::use_facet néu khia canh duoc yéu cau không tôn tại trong ngôn ngữ
Member Functions:
— Constructor: Ham khdéi tao m6t bad_cast object
— operator=: Ham thay thé mét bad cast object
— what: tra vé chudi giải thích
Ví dụ:
Trang 11BTLT-Group-W09-10
void test DynamicCast(Base &base)
{
try
{
// lỗi khi cố gắng ép kiểu base sang kiéu derived
Derived &derived = dynamic_cast<Derived &>(base);
std::cout << "Dynamic cast to Derived succeeded." << std::endl;
Ỳ
catch (const std::bad_cast &e)
{
std::cerr << "Caught a bad_cast exception: "<< e.what() << std::endl;
Ỳ
Ỳ
int mainQ
{
AnotherClass anotherObject;
test DynamicCast(anotherObject);
return 0;
Output:
2.4, class bad_alloc
GVHD: H6 Tuan Thanh
std::bad_alloc la loai déi tượng được các hàm phân bố đưa ra dưới đạng ngoại lệ dé
báo cáo lỗi phân bồ bộ nhớ
Member Functions:
— Constructor: Ham khdi tao mét bad_alloc object
— operator=: Ham thay thé mot bad_alloc object
— what: tra vé chudi giải thích
Trang 12BTLT-Group-W09-10
Vi du:
#include <iostream>
#include <exception>
int mainQ
{
try
{
// Kích thước rất lớn, có thể gây ra lỗi cấp phát
size_t largeSize = static_cast<size_t>(-1);
int *largeArray = new int[largeSize];
largeArray[0] = 1;
std::cout << largeArray[0];
delete[] largeArray;
Ỳ
catch (const std::bad_alloc &e)
{
std::cerr << "Caught a bad_alloc exception: "<< e.what() << std::endl;
}
return 0;
Output:
2.5, class invalid_argument
GVHD: H6 Tuan Thanh
Xác định một loại đối tượng được ném ra như một ngoại lệ Nó báo lỗi phát sinh do giá trị đối số chưa được chấp nhận Ngoại lệ này được ném ra bởi std::bitset::bitset và các
ho ham std::stoi va std::stof
10
Trang 13BTLT-Group-W09-10
Member Functions:
— Constructor: Ham khdi tao mét bad_alloc object
— operator=: Ham thay thé mot bad_alloc object
— what: tra vé chudi giải thích
Vi du:
#include <iostream>
#include <exception>
#include <string>
using namespace std;
int mainQ
{
try
{
int num = stoi("ABCD");
cout << num << endl;
Ỳ
catch (invalid_argument const &ex)
{
cout << "Exception: " << ex.what() << endl;
Output:
GVHD: H6 Tuan Thanh
Nguyên lý L trong SOLID principles la nguyén ly thay thé Liskov (Liskov Substitution Principle - LSP) Noi dung của nguyên ly như sau: “ Trong một chương trình, các object của class con có thê thay thế class cha mà không làm thay đổi tính đúng đắn của chương trình”
lãi
Trang 14BTLT-Group-W09-10 GVHD: H6 Tuan Thanh LSP yêu cầu rằng các lớp con phải duy trì hành vi của lớp cha Điều này có nghĩa là nếu một lớp con kế thừa một lớp cha, nó phải có khả năng sử dụng ở bất kỳ đâu mà lớp cha được sử dụng mà không làm thay đối tính đúng đắn của chương trình, cho phép dễ dàng thêm mới các lớp con mà không cần sửa đổi mã nguồn hiện có, giúp hệ thống linh hoạt hơn
va dé dàng mở rộng
Ví dụ minh họa: Trong cuộc sông, khi ổi mua sắm, ăn uông đê thanh toán cho các loại chi phi thì có rất nhiều cách đề thực hiện: thẻ ngân hàng, ví điện tử Đề triển khai vấn
đề này thành I chương trình nên áp dụng nguyên lí L trong SOLID principles vào tôi ưu hóa chương trình
#include<iostream>
class Payment
{
public:
virtual void pay(float money) = 0;
I
class CreditCardPayment : public Payment
{
public:
void pay(float money)
{
std::cout << "Processing credit card payment of "<<
money << std::endl;
t
i
12
Trang 15BTLT-Group-W09-10 GVHD: H6 Tuan Thanh class Digital WalletPayment : public Payment
{
public:
void pay(float money)
{
std::cout << "Processing digital wallet payment of "<<
money << std::endl;
t
i
class PayPalPayment : public Payment
{
public:
void pay(float money)
{
std::cout << "Processing PayPal payment of " << money <<
std::endl;
t
I
class MobileAppPayment : public Payment
{
public:
void pay(float money)
{
std::cout << "Processing mobile app payment of "<< money
<< std::endl;
t
I
13
Trang 16BTLT-Group-W09-10 GVHD: H6 Tuan Thanh
Nguyén ly I trong SOLID principles la nguyén ly phan tách giao dién ( Interface Segregation principle - ISP) Nội dung của nguyên lý I như sau: "Không nên bắt các khách hàng phải phụ thuộc vào những giao diện mà họ không sử dụng” Nói cách khác, thay vì tạo ra một giao diện lớn chứa nhiều phương thức mà không phải tất cả khách hàng đều cần
dén, ta nén tao ra nhiéu giao diện nhỏ, chuyên biệt
Ap dụng nguyên lý ISP làm giảm sự phụ thuộc không cần thiết, các lớp chi phụ thuộc vào những giao diện mà chúng thực sự cần Khi các giao diện nhỏ gọn và chuyên biệt, việc thay đôi chúng ít ảnh hưởng đến các phần khác của hệ thống Ngoài ra cũng tăng khả năng tái sử dụng của các giao diện qua các lớp khác nhau mà không gây gánh nặng cho các lớp nảy
Ví dụ minh họa: Khi tạo 1 interface Document với quá nhiều phương thức khác nhau: createDocument, readDocument, deleteDocument, va con nhiéu phương thức khác nữa,
nhưng không phải loại tài liệu nào cũng cần sử dụng hết toàn bộ các phương thức đó, điều
nảy v1 phạm nguyên lí I trong SOLID principles
class Document {
public:
virtual void createDocument() = 0;
virtual void readDocument() = 0;
virtual void updateDocument() = 0;
virtual void deleteDocument() = 0;
virtual void convertDocument() = 0;
I
Thay vì tạo như | interface qua lon như vậy thì nên áp dụng nguyên li [SP vao trường hợp này đề tôi ưu hơn
14
Trang 17BTLT-Group-W09-10
class CreateDocument
{
public:
virtual void createDocument() = 0;
h
class ReadDocument
{
public:
virtual void readDocument() = 0;
h
class UpdateDocument
{
public:
virtual void updateDocument() = 0;
h
class DeleteDocument
{
public:
virtual void deleteDocument() = 0;
h
class ConvertDocument
{
public:
virtual void convertDocument() = 0;
h
GVHD: H6 Tuan Thanh
15
Trang 18BTLT-Group-W09-10 GVHD: H6 Tuan Thanh
Nguyên lý D trong SOLID là viết tat cua Dependency Inversion Principle Ndi dung của nguyên ly nay có 2 ý như sau:
— _ “Các module cấp cao không nên phụ thuộc vào các module cấp thấp Cả hai nên phụ thuộc vào abstraction (interface).”
— “Abstraction (interface) không nên phụ thuộc vào chỉ tiết Ngược lại, chỉ tiết (concrete implementation) nén phụ thuộc vào abstraction (interface).”
Nguyên lý này gợi ý cho chúng ta cách thiết kế va cài đặt chương trình tốt hơn về mặt nâng cấp, mở rộng, hay chỉnh sửa lại các chức năng Khi áp dụng nguyên tắc này, việc nâng cấp, mở rộng, chỉnh sửa các chức năng sẽ trở nên nhanh chóng và dễ dàng hơn Vì khi đó,
chúng ta sẽ chỉ cần chính sửa trên các abstract class và các concrete class sẽ được tự động
kế thừa Như vậy, chúng ta sẽ không cần phải chỉnh sửa trên tất cả các class liên quan đến chức năng mà chúng ta cần thay đôi
Một ví dụ thực tế và quen thuộc trong cuộc sông như sau: Chúng ta có rất nhiều thiết
bị điện tử khác nhau trong nhà như tivi, tủ lạnh, máy giặt, Nhưng dù là thiết bị nào thì cũng sẽ có dây cắm là loại phích cắm 2 chấu Vậy thì mỗi khi chúng ta muốn sử dụng loại thiết bị nào đó thi chi can lấy phích cắm nối vào ô điện mà không cần quan tâm loại thiết
bị đó là gì
Trong ví dụ trên có thê xem phích cắm 2 chấu là một interface (abstraction), các thiết
bị điện tử là một concrete class Khi cần thay đôi gì đó thì chi can thay d6i trén interface (abstraction) là được Như ở Việt Nam thì hầu hết sử dụng phích 2 chấu, còn ở một số nước khac sé str dyng phich 3 chau Nhu vay thi chi can thay d6i interface (abstraction) 2 chau thành 3 chấu là hoàn thành mà không cần thay đôi các thiết bị điện tử
16