You are on page 1of 64

om

.c
ng
CHƢƠNG 7.

co
an
TEMPLATE, EXCEPTION
th
o ng
du
u
cu

CuuDuongThanCong.com https://fb.com/tailieudientucntt
Template

om
1 Lập trình tổng quát

.c
ng
Lập trình tổng quát trong C++

co
2

an
th
3 C++ template
ng
o
du

4 Khuôn mẫu hàm


u
cu

5 Khuôn mẫu lớp

11/13/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 2


Giới thiệu

om
Ví dụ xét hàm hoán vị như sau:

.c
void swap ( int& a, int& b){

ng
co
int temp;

an
temp = a; a = b; b = temp;
}
th
o ng
du

Nếu ta muốn thực hiện công việc tương tự cho


u

một kiểu dữ liệu khác, chẳng hạn float?


cu

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 3


Giới thiệu

om
Ví dụ khác: Ta định nghĩa một lớp biểu diễn cấu

.c
trúc ngăn xếp cho kiểu int

ng
co
class Stack {

an
public:

th
Stack(); ng
~Stack();
o
du

void push ( const int& i);


void pop ( int& i);
u
cu

bool isEmpty() const;


//...
};
13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 4
Giới thiệu

om
Khai báo và định nghĩa của Stack phụ thuộc tại

.c
một mức độ nào đó vào kiểu dữ liệu int.

ng
co
Một số phương thức lấy tham số và trả về kiểu int

an
Nếu ta muốn tạo ngăn xếp cho một kiểu dữ liệu khác
thì sao?
th
o ng
Ta có nên định nghĩa lại hoàn toàn lớp Stack (kết quả
du

sẽ tạo ra nhiều lớp chẳng hạn IntStack, FloatStack,…)


u
cu

hay không?

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 5


Lập trình tổng quát

om
Lập trình tổng quát là phương pháp lập trình độc

.c
lập với chi tiết biểu diễn dữ liệu.

ng
co
Tư tưởng là ta định nghĩa một khái niệm không phụ

an
thuộc một biểu diễn cụ thể nào, và sau đó mới chỉ ra

th
kiểu dữ liệu thích hợp làm tham số.
o ng
Như vậy trong một số trường hợp, đưa chi tiết về
du

kiểu dữ liệu vào trong định nghĩa hàm hoặc lớp là


u
cu

điều không có lợi.

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 6


Lập trình tổng quát trong C

om
Sử dụng trình tiền xử lý của C

.c
Trình tiền xử lý thực hiện thay thế text trước khi dịch

ng
co
Do đó, ta có thể dùng #define để chỉ ra kiểu dữ liệu và

an
thay đổi tại chỗ khi cần.

th
ng
#define TYPE int
o
void swap(TYPE & a, TYPE & b) {
du

TYPE temp;
u
cu

temp = a; a = b; b = temp;
}

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 7


Lập trình tổng quát trong C

om
#define TYPE int

.c
void swap(TYPE & a, TYPE & b) {

ng
TYPE temp;

co
temp = a; a = b; b = temp;

an
th
} ng
Sử dụng trình tiền xử lý của C
o
du

Nhàm chán và dễ lỗi


u
cu

Chỉ cho phép đúng một định nghĩa trong một chương
trình.

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 8


C++ Template

om
Template (khuôn mẫu) là một cơ chế thay thế cho

.c
phép tạo các cấu trúc mà không phải chỉ rõ kiểu

ng
dữ liệu ngay từ đầu.

co
an
th
ng
Từ khóa template được dùng trong C++ để báo
o
du

cho trình biên dịch biết rằng đoạn mã theo sau sẽ


u
cu

thao tác một hoặc nhiều kiểu dữ liệu chưa xác


định

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 9


C++ Template

om
Từ khóa template được theo sau bởi một cặp

.c
ngoặc nhọn chứa tên của các kiểu dữ liệu tùy ý

ng
được cung cấp.

co
an
template <typename T>
th
ng
template <typename T, typename U>
o
du
u
cu

Một lệnh template chỉ có hiệu quả đối với khai


báo ngay sau nó

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 10


C++ Template

om
Hai loại khuôn mẫu cơ bản:

.c
Function template – khuôn mẫu hàm cho phép

ng
co
định nghĩa các hàm tổng quát dùng đến các

an
kiểu dữ liệu tùy ý.
th
ng
Class template – khuôn mẫu lớp cho phép
o
du

định nghĩa các lớp tổng quát dùng đến các


u
cu

kiểu dữ liệu tùy ý.

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 11


Khuôn mẫu hàm

om
Khuôn mẫu hàm là dạng khuôn mẫu đơn giản

.c
nhất cho phép ta định nghĩa các hàm dùng đến

ng
các kiểu dữ liệu tùy ý.

co
an
Ví dụ sau định nghĩa hàm swap() bằng khuôn
th
ng
mẫu:
template <typename T>
o
du

void swap(T & a, T & b) {


u
cu

T temp;
temp = a; a = b; b = temp;
}
13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 12
Khuôn mẫu hàm

om
Thực chất, khi sử dụng template, ta đã định

.c
nghĩa một tập “vô hạn” các hàm chồng nhau với

ng
co
tên swap()

an
Để gọi một trong các phiên bản này, ta chỉ cần
th
ng
gọi nó với kiểu dữ liệu tương ứng
o
du

int x = 1, y = 2;
u
cu

float a = 1.1, b = 2.2;


swap(x, y); //Gọi hàm swap() với kiểu int
swap(a, b); //Gọi hàm swap() với kiểu float
13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 13
Khuôn mẫu hàm

om
Chuyện gì xảy ra khi ta biên dịch mã?

.c
Trước hết, sự thay thế "T" trong khai báo/định

ng
co
nghĩa hàm swap() không phải thay thế text

an
đơn giản và cũng không được thực hiện bởi
th
ng
trình tiền xử lý.
o
du

Việc chuyển phiên bản mẫu của swap() thành


u
cu

các cài đặt cụ thể cho int và float được thực


hiện bởi trình biên dịch.

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 14


Khuôn mẫu hàm

om
Hãy xem xét hoạt động của trình biên dịch khi

.c
gặp lời gọi swap() thứ nhất (với hai tham số int)

ng
co
Trước hết, trình biên dịch tìm xem có một hàm

an
swap() được khai báo với 2 tham số kiểu int
th
ng
hay không? không tìm thấy nhưng tìm thấy
o
du

một template có thể dùng được.


u
cu

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 15


Khuôn mẫu hàm

om
Tiếp theo, nó xem xét khai báo của template

.c
swap() để xem có thể khớp được với lời gọi hàm

ng
co
hay không?

an
Lời gọi hàm cung cấp hai tham số thuộc cùng một kiểu
(int)
th
o ng
Trình biên dịch thấy template chỉ ra hai tham số thuộc
du

cùng kiểu T, nên nó kết luận rằng T phải là kiểu int


u
cu

Do đó, trình biên dịch kết luận rằng template khớp với
lời gọi hàm

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 16


Khuôn mẫu hàm

om
Khi đã xác định được template khớp với lời gọi

.c
hàm, trình biên dịch kiểm tra xem đã có một

ng
phiên bản của swap() với hai tham số kiểu int

co
an
được sinh ra từ template hay chưa?
th
ng
Nếu đã có, lời gọi được liên kết (bind) với phiên bản
o

đã được sinh ra
du
u

Nếu không, trình biên dịch sẽ sinh một cài đặt của
cu

swap() lấy hai tham số kiểu int - và liên kết lời gọi hàm
với phiên bản vừa sinh.

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 17


Khuôn mẫu hàm

om
Như vậy, đến cuối quy trình biên dịch đoạn mã

.c
trong ví dụ, sẽ có hai phiên bản của swap() được

ng
tạo với các lời gọi hàm của ta được liên kết với

co
an
phiên bản thích hợp.
th
ng
Chi phí về thời gian biên dịch đối với việc sử dụng
o

template?
du
u

Chi phí về không gian liên quan đến mỗi cài đặt của
cu

swap() được tạo trong khi biên dịch?

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 18


Khuôn mẫu lớp

om
Tương tự với khuôn mẫu hàm với tham số thuộc

.c
các kiểu tùy ý, ta cũng có thể định nghĩa khuôn

ng
mẫu lớp (class template) sử dụng các thể hiện

co
an
của một hoặc nhiều kiểu dữ liệu tùy ý.
th
ng
Việc khai báo một khuôn mẫu lớp cũng tương tự
o
du

với khuôn mẫu hàm


u
cu

template <class T> class ClassName {


definition
}
13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 19
Khuôn mẫu lớp

om
Ví dụ: ta sẽ tạo một cấu trúc cặp đôi giữ một cặp

.c
giá trị thuộc kiểu tùy ý.

ng
co
Trước hết, xét khai báo Pair cho một cặp giá trị

an
kiểu int như sau:
th
ng
struct Pair {
o
du

int first;
u
cu

int second;
};

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 20


Khuôn mẫu lớp

om
Ta có thể sửa khai báo trên thành một khuôn

.c
mẫu lấy kiểu tùy ý:

ng
co
template <typename T>

an
struct Pair {
T first;
th
o ng
T second;
du

};
u
cu

Tuy nhiên hai thành viên first và second phải


thuộc cùng kiểu
13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 21
Khuôn mẫu lớp

om
Ta có thể cho phép hai thành viên nhận các kiểu

.c
dữ liệu khác nhau:

ng
co
template <typename T, typename U>

an
struct Pair {
th
ng
T first;
o
du

U second;
u

};
cu

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 22


Khuôn mẫu lớp

om
Để tạo các thể hiện của template Pair, ta phải

.c
dùng ký hiệu cặp ngoặc nhọn (khác với khuôn

ng
mẫu hàm)

co
an
Pair p; // Không được
th
ng
Pair<int, int> q; // Creates a pair of ints
o
du

Pair<int, float> r; // Creates a pair with an int and


u
cu

a float

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 23


Khuôn mẫu lớp

om
Khi thiết kế khuôn mẫu (cho lớp hoặc hàm),

.c
thông thường, ta nên tạo một phiên bản cụ thể

ng
trước, sau đó mới chuyển nó thành một template.

co
an
Ví dụ, ta sẽ bắt đầu bằng việc cài đặt hoàn chỉnh
th
ng
Stack cho số nguyên.
o
du

Điều đó cho phép phát hiện các vấn đề về khái


u
cu

niệm trước khi chuyển thành phiên bản cho sử


dụng tổng quát.

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 24


Khuôn mẫu lớp – Ví dụ

om
Ví dụ: Xét lớp Stack với số nguyên

.c
class Stack {

ng
private:

co
static const int max = 10;

an
int contents[max], current;
public:
th
ng
Stack(); ~Stack();
o
du

void push(const int& i);


u

void pop(int& i);


cu

bool isEmpty() const;


bool isFull() const;
};
13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 25
Khuôn mẫu lớp – Ví dụ

om
Stack::Stack() { this->current = 0; }

.c
Stack::~Stack() {}

ng
void Stack::push(const int& i) {

co
if (this->current < this->max) this->contents[this->current++] = i;

an
}

th
void Stack::pop(int& i) { ng
if (this->current > 0) i = this->contents[--this->current];
o
du

}
bool Stack::isEmpty() const { return (this->current == 0;) }
u
cu

bool Stack::isFull() const {


return (this->current == this->max);
}

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 26


Khuôn mẫu lớp – Ví dụ

om
template <class T>
class Stack {

.c
private:

ng
static const int max = 10;

co
T contents[max];

an
int current;

th
public: ng
Stack(); ~Stack();
o
du

void push(const T& i);


u

void pop(T& i);


cu

bool isEmpty() const;


bool isFull() const;
};

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 27


Khuôn mẫu lớp – Ví dụ

om
template <class T>
Mỗi phương thức cần một

.c
Stack<T>::Stack() { lệnh template đặt trước

ng
this->current = 0;

co
}
Mỗi khi dùng toán tử phạm

an
template <class T>
vi, cần một ký hiệu ngoặc

th
Stack<T>::~Stack() { }
nhọn kèm theo tên kiểu.
ng
template <class T>
Ta đang định nghĩa một lớp
o
du

void Stack<T>::push(const T& i) Stack<type>, chứ không


{ phải định nghĩa lớp Stack
u
cu

if (this->current < this->max)


this->contents[this->current++] = i;
}

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 28


Khuôn mẫu lớp – Ví dụ

om
template <class T>

.c
void Stack<T>::pop(T& i) {
if (this->current > 0)

ng
i = this->contents[--this->current];

co
}

an
template <class T>

th
bool Stack<T>::isEmpty() const {
ng
return (this->current == 0;)
o

Thay thế kiểu của đối tượng


du

}
được lưu trong ngăn xếp (trước
u

template <class T> là int) bằng kiểu tùy ý T


cu

bool Stack<T>::isFull() const {


return (this->current == this->max);
}
13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 29
Khuôn mẫu lớp – Ví dụ

om
int x = 5,

.c
char c = 'a',

ng
co
Stack<int>

an
Stack<char>
th
ng
s.push(x);
o
du

t.push(c);
u
cu

s.pop(y);
t.pop(d);

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 30


Các tham số khuôn mẫu khác

om
Phần trước chúng ta chỉ mới nói đến các lệnh

.c
template với tham số thuộc "kiểu" class.

ng
co
Tuy nhiên, chúng ta có thể sử dụng các tham số

an
kiểu và tham số biểu thức trong khuôn mẫu lớp
th
ng
template <class T, int elements>
o
du

Stack <double, 100> s;


u
cu

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 31


Các tham số khuôn mẫu khác

om
Trong cài đặt Stack, ta có một hằng max quy định

.c
số lượng tối đa các đối tượng mà ngăn xếp có

ng
thể chứa mỗi thể hiện sẽ có cùng kích thước

co
an
đối với mọi kiểu của đối tượng được chứa.
th
ng
Ta không muốn mọi Stack đều có kích thước tối
o
du

đa như nhau Có thể thêm một tham số vào


u

lệnh template chỉ ra một số int (giá trị này sẽ


cu

được dùng để xác định giá trị cho max)


template <typename T, int M>
13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 32
Các tham số khuôn mẫu khác

om
template <typename T, int M>
class Stack {

.c
public: Khai báo tham số mới

ng
Stack();

co
~Stack(); Sử dụng tham số mới

an
void push(const T& i); để xác định giá trị
void pop(T& i);
thmax của một lớp
ng
bool isEmpty() const; thuộc một kiểu nào đó
o
du

bool isFull() const;


private:
u
cu

static const int max = M;


T contents[max];
int current;
};
13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 33
Các tham số khuôn mẫu khác

om
template <typename T, int I>
Sửa các lệnh

.c
Stack<T, I>::Stack() { this->current = 0; } template

ng
co
template <typename T, int I>

an
Stack<T, I>::~Stack() {}

th
ng
template <typename T, int I>
Sửa tên lớp
o
du

void Stack<T, I>::push(const T& i) { dùng cho các


toán tử phạm vi
u

if (this->current < this->max)


cu

this->contents[this->current++] = i;
}
13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 34
Các tham số khuôn mẫu khác

om
Giờ ta có thể tạo các thể hiện của các lớp Stack

.c
với các kiểu dữ liệu và kích thước đa dạng

ng
co
Stack<int, 5> s;

an
th
Stack<int, 10> t; ng
o
Stack<char, 5> u;
du
u
cu

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 35


Ngoại lệ (Exception)

om
1 Giới thiệu

.c
ng
Cách xử lý lỗi truyền thống

co
2

an
th
3 Ngoại lệ trong C++
ng
o
du

4 Kiểm soát ngoại lệ


u
cu

5 Lớp ngoại lệ exception

11/13/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 36


Giới thiệu

om
Mọi đoạn chương trình đều tiềm ẩn khả năng

.c
sinh lỗi

ng
co
Lỗi chủ quan: do lập trình sai

an
Lỗi khách quan: do dữ liệu, do trạng thái của hệ thống

th
ng
Lỗi có 2 loại?
o
du

Ngoại lệ (Exception): các trường hợp hoạt động


u
cu

không bình thường

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 37


Cách xử lý lỗi truyền thống

om
Cài đặt mã xử lý tại nơi phát sinh ra lỗi

.c
Làm cho chương trình trở nên khó hiểu

ng
co
Không phải lúc nào cũng đầy đủ thông tin để xử lý

an
Không nhất thiết phải xử lý

th
ng
Truyền trạng thái lên mức trên
o
du

Thông qua tham số, giá trị trả lại hoặc biến tổng thể
u

(flag)
cu

Dễ nhầm
Khó hiểu
13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 38
Cách xử lý lỗi truyền thống

om
int devide(int num, int denom, int& error){

.c
if (0 != denom){

ng
error = 0;

co
return num/denom;

an
} else {
th
ng
error = 1;
o
du

return 0;
u
cu

}
}

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 39


Cách xử lý lỗi truyền thống

om
Khó kiểm soát được hết các trường hợp

.c
Lỗi số học

ng
co
Lỗi bộ nhớ

an
…

th
ng
Lập trình viên thường quên không xử lý lỗi
o
du

Bản chất con người


u
cu

Thiếu kinh nghiệm, cố tình bỏ qua

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 40


C++ Exception

om
Exception – Ngoại lệ là cơ chế thông báo và xử lý

.c
lỗi giải quyết được các vấn đề gặp phải ở trên.

ng
co
Tách được phần xử lý lỗi ra khỏi phần thuật toán

an
chính.
th
ng
Cho phép một hàm có thể thông báo về nhiều
o
du

loại ngoại lệ
u
cu

Cơ chế ngoại lệ mềm dẻo hơn kiểu xử lý lỗi


truyền thống

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 41


Các kiểu ngoại lệ

om
Một ngoại lệ là một đối tượng chứa thông tin về

.c
một lỗi và được dùng để truyền thông tin đó tới

ng
cấp thực thi cao hơn.

co
an
Ngoại lệ có thể thuộc kiểu dữ liệu bất kỳ của C++
th
ng
Có sẵn, chẳng hạn int, char*, …
o
du

Hoặc kiểu người dùng tự định nghĩa (thường dùng)


u
cu

Các lớp ngoại lệ trong thư viện <exception>

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 42


Cơ chế ngoại lệ

om
Quá trình truyền ngoại lệ từ ngữ cảnh thực thi

.c
hiện hành tới mức thực thi cao hơn gọi là ném

ng
một ngoại lệ (throw an exception).

co
an
Vị trí trong mã của hàm nơi ngoại lệ được ném được
gọi là điểm ném (throw point)
th
o ng
Khi một ngữ cảnh thực thi tiếp nhận và truy nhập
du
u

một ngoại lệ, nó được coi là bắt ngoại lệ (catch


cu

the exception)

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 43


Cơ chế ngoại lệ

om
Quy trình gọi hàm và trả về trong trường hợp

.c
bình thường:

ng
co
void main() {

an
int x, y;
cout << “Nhập 2 số: ”; th
o ng
cin >> x >> y;
du

cout << “Kết quả x/y=”;


u
cu

cout<< MyDivide(x, y) << “\n”;


}

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 44


Cơ chế ngoại lệ

om
Quy trình ném và bắt ngoại lệ:

.c
ng
co
an
th
ng catches
exeption
o
du
u
cu

throws
exception

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 45


Cú pháp xử lý ngoại lệ

om
Cơ chế xử lý ngoại lệ của C++ có 3 tính năng

.c
chính:

ng
co
Khả năng tạo và ném ngoại lệ (sử dụng từ khoá

an
throw)
th
ng
Khả năng bắt và giải quyết ngoại lệ (sử dụng từ
o
du

khoá catch)
u

Khả năng tách logic xử lý ngoại lệ trong một hàm


cu

ra khỏi phần còn lại của hàm (sử dụng từ khoá try)

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 46


Ném ngoại lệ – throw

om
Để ném một ngoại lệ, ta dùng từ khóa throw, kèm

.c
theo đối tượng mà ta định ném.

ng
Ta có thể dùng mọi thứ làm ngoại lệ, kể cả giá trị

co
thuộc kiểu có sẵn.

an
th
double MyDivide(double numerator, double denominator){
ng
if (denominator == 0.0) {
o
du

throw string(“The denominator cannot be 0.”);


u

} else {
cu

return numerator / denominator;


}
}
13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 47
Kiểm soát ngoại lệ

om
Khối try – catch dùng để:

.c
Tách phần giải quyết lỗi ra khỏi phần có thể sinh lỗi

ng
co
Quy định các loại ngoại lệ được bắt tại mức thực thi

an
hiện hành

th
ng
try {
o
// Code that could generate an exception
du

}
u
cu

catch (<Type of exception>) {


// Code that resolves an exception of that type
};

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 48


Kiểm soát ngoại lệ

om
Có thể có nhiều khối catch, mỗi khối chứa mã để

.c
giải quyết một loại ngoại lệ cụ thể:

ng
try {

co
// Code that could generate an exception

an
}

th
catch (<Exception type1>) { ng
// Code that resolves a type1 exception
o
}
du

catch (<Exception type2>) {


u

// Code that resolves a type2 exception


cu

}
catch (<Exception typeN>) {
// Code that resolves a typeN exception
};
13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 49
Kiểm soát ngoại lệ – Ví dụ

om
void main() {
int x, y;

.c
double result;

ng
cout << “Nhập 2 số: ”;

co
cin >> x >> y;

an
try {
th
result = MyDivide(x, y);
ng
cout << “Kết quả x/y = ”<< result << “\n”;
o
du

}
u

catch (string &s) {


cu

cout<<s<<endl; //resolve error


};
}

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 50


Kiểm soát ngoại lệ – Ví dụ

om
void main(){
int x, y;

.c
double result;
bool success;

ng
do {

co
success = true;
cout << "Nhập 2 số: ";

an
cin >> x >> y;

th
try { ng
result = Divide(x, y);
cout << "Kết quả x/y = "<< result << "\n";
o
du

}
catch (string& s) {
u

cout << s << endl;


cu

success = false;
};
} while (success == false);
}

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 51


So khớp ngoại lệ

om
Khi một ngoại lệ được ném từ trong một khối try,

.c
hệ thống xử lý ngoại lệ sẽ kiểm tra các kiểu được

ng
liệt kê trong khối catch theo thứ tự liệt kê:

co
an
Khi tìm thấy kiểu đã khớp, ngoại lệ được coi là
th
ng
được giải quyết, không cần tiếp tục tìm kiếm.
o
du

Nếu không tìm thấy, mức thực thi hiện hành bị


u
cu

kết thúc, ngoại lệ được chuyển lên mức cao


hơn.

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 52


So khớp ngoại lệ

om
Khi tìm các kiểu dữ liệu khớp với ngoại lệ, trình

.c
biên dịch nói chung sẽ không thực hiện đổi kiểu

ng
tự động.

co
an
Nếu một ngoại lệ kiểu float được ném, nó sẽ không

th
khớp với một khối catch cho ngoại lệ kiểu int
o ng
Một đối tượng hoặc tham chiếu kiểu dẫn xuất sẽ
du
u

khớp với một lệnh catch dành cho kiểu cơ sở


cu

Nếu một ngoại lệ kiểu Car được ném, nó sẽ khớp với


một khối catch cho ngoại lệ kiểu MotorVehicle
13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 53
So khớp ngoại lệ

om
try {
//…

.c
ng
}

co
catch (MotorVehicle& mv) {…}

an
catch (Car& c) {…}

th
catch (Truck& t) {…};
o ng
Vấn đề gặp phải?
du
u

Mọi ngoại lệ là đối tượng được sinh từ cây


cu

MotorVehicle sẽ khớp lệnh catch đầu tiên (các


lệnh còn lại sẽ không bao giờ chạy)
13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 54
So khớp ngoại lệ

om
Nếu muốn bắt các ngoại lệ dẫn xuất tách khỏi

.c
ngoại lệ cơ sở, ta phải xếp lệnh catch cho lớp

ng
dẫn xuất lên trước:

co
an
try {
//… th
o ng
}
du

catch (Car& c) {…}


u
cu

catch (Truck& t) {…}


catch (MotorVehicle& mv) {…};
13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 55
So khớp ngoại lệ

om
Nếu ta muốn bắt tất cả các ngoại lệ được ném

.c
(kể cả các ngoại lệ ta không thể giải quyết)?

ng
co
Để có một lệnh catch bắt được mọi ngoại lệ, ta

an
đặt dấu ba chấm bên trong lệnh catch.
th
ng
catch(…){
o

//…
du
u

};
cu

Chỉ nên sử dụng nó cho lệnh catch cuối cùng


trong một khối try-catch.
13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 56
Lớp exception

om
Để tích hợp hơn nữa các ngoại lệ vào ngôn ngữ

.c
C++, lớp exception đã được đưa vào thư viện

ng
chuẩn.

co
an
Sử dụng #include <exception> và namespace std

th
ng
Sử dụng thư viện này, ta có thể ném các thể hiện
o
du

của exception hoặc tạo các lớp dẫn xuất từ đó.


u
cu

Lớp exception có một hàm ảo what(), có thể định


nghĩa lại what() để trả về một xâu ký tự.

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 57


Lớp exception

om
Một số lớp ngoại lệ chuẩn khác được dẫn xuất từ

.c
lớp cơ sở exception.

ng
co
File header <stdexcept> (cũng thuộc thư viện

an
chuẩn C++) chứa một số lớp ngoại lệ dẫn xuất từ
th
ng
exception. Trong đó có hai lớp quan trọng được
o
du

dẫn xuất trực tiếp từ exception:


u
cu

runtime_error
logic_error

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 58


Lớp exception

om
runtime_error: Các lỗi trong thời gian chạy (các

.c
lỗi là kết quả của các tình huống không mong

ng
đợi, chẳng hạn: hết bộ nhớ)

co
an
logic_error: Các lỗi trong logic chương trình
th
ng
(chẳng hạn truyền tham số không hợp lệ)
o
du

Thông thường, ta sẽ dùng các lớp này (hoặc các


u
cu

lớp dẫn xuất của chúng) thay vì dùng trực tiếp


exception

13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 59


Lớp exception

om
runtime_error có các lớp dẫn xuất sau:

.c
range_error điều kiện sau (post-condition) bị vi phạm

ng
overflow_error xảy ra tràn số học

co
bad_alloc không thể cấp phát bộ nhớ

an
th
logic_error có các lớp dẫn xuất sau:ng
domain_error điều kiện trước (pre-condition) bị vi
o
du

phạm
u

invalid_argument tham số không hợp lệ được truyền


cu

cho hàm
length_error tạo đối tượng lớn hơn độ dài cho phép
out_of_range tham số ngoài khoảng
13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 60
Lớp exception

om
Ta có thể viết lại hàm MyDivide() để sử dụng các

.c
ngoại lệ chuẩn tương ứng như sau:

ng
co
double MyDivide(double numerator, double denominator)

an
{

th
if (denominator == 0.0) { ng
throw invalid_argument(“The denominator cannot
o

be 0.”);
du

} else {
u
cu

return numerator / denominator;


}
}
13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 61
Lớp exception

om
void main() {
int x, y;

.c
double result;

ng
do {

co
cout << “Nhập 2 số: ”; cin >> x >> y;

an
try {

th
result = MyDivide(x, y);
ng
cout << “x/y = ” << result << “\n”;
o
}
du

catch (invalid_argument& e) {
u
cu

cout << e.what() << endl;


};
} while (1);
}
13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 62
Ƣu điểm exception trong C++

om
Dễ sử dụng

.c
Dễ dàng chuyển điều khiển đến nơi có khả năng xử lý

ng
ngoại lệ

co
Có thể “ném” nhiều loại ngoại lệ

an
th
Tách xử lý ngoại lệ khỏi thuật toán ng
Tách mã xử lý
o
du

Sử dụng cú pháp khác


u
cu

Không bỏ sót ngoại lệ (“ném” tự động)


Chương trình dễ đọc hơn, an toàn hơn
13/11/2020 CuuDuongThanCong.com Lập trình hướng đối tượng https://fb.com/tailieudientucntt 63
Q&A

om
.c
ng
co
an
th
o ng
du
u
cu

CuuDuongThanCong.com https://fb.com/tailieudientucntt

You might also like