Xử lý ngoại lệ – Exception Handling trong C++ | CppDeveloper

Bản thân C + + không có khái niệm “ errors – lỗi ”. Khi mọi thứ xảy ra không thông thường, không như kỳ vọng thì C + + gọi đó là “ exception – ngoại lệ ”, “ exception ” có nghĩa rộng hơn “ error ”. Tất cả những error đều là exception, nhưng không phải toàn bộ exception đều là error. Khi có điều gì đó sai sai trong một chương trình, một exception phát sinh. Exceptions phát sinh theo 2 cách, trường hợp thứ nhất là phát sinh tự động từ những hàm trong thư viện của C + +, trọn vẹn ngoài tầm trấn áp của tất cả chúng ta, trong khi trường hợp khác được phát sinh thủ công bằng tay theo ý muốn của người tăng trưởng .
Một exception cũng chính là data, là tài liệu. Hãy tưởng tượng một exception như một chiếc hộp tài liệu có cánh, có năng lực bay, Open khi một cái gì đó sai sai xảy ra. Hộp chứa tài liệu hoàn toàn có thể giúp người tăng trưởng xác lập nguyên do của lỗi. Dữ liệu ở đấy hoàn toàn có thể là bất kể kiểu tài liệu nào : nó hoàn toàn có thể là kiểu int, float, string hay một đối tượng người dùng của class bất kể nào đó. Bạn sẽ phải chọn kiểu tài liệu hữu dụng nhất trong trường hợp của mình .

Xử lý exception – exception handling trong C++

Các đoạn code có năng lực gây ra lỗi cần phải được lưu lại trong một loại block code đặc biệt quan trọng. Block đó sẽ được theo dõi cẩn trọng trong quy trình thực thi. Một exception mới phát sinh được miêu tả là “ một exception đã bị throw ( ném ra ) ”. Khi một exception được ném ra, việc thực thi của block code đó sẽ chấm hết, nhưng bản thân chương trình vẫn còn sống. Exception mới phát sinh mở màn bay mang theo tài liệu và bay đến cuối của block. Nếu không ai muốn bắt exception, nó vẫn liên tục bay đến cấp cao hơn của chuỗi functions với kỳ vọng rằng có ai đó muốn catch ( bắt ) nó. Nếu exception không bị catch ở cấp cao nhất ( trong hàm main ( ) ), điều này sẽ khiến chương trình dừng lại và phát ra thông tin chẩn đoán thích hợp. Đây là ngữ cảnh xấu nhất .
Trong C++ thì xử lý exception được thực hiện thông qua 3 keywords chính là: try, catch, throw.

  • try − Nếu bạn muốn phát hiện các exception, bạn cần đánh dấu các phần code mà trong đó các exception có thể xảy ra. Bạn làm điều này bằng cách sử dụng câu lệnh try. Trên thực tế, câu lệnh try không thực sự làm bất cứ điều gì đặc biệt, nó không thay đổi việc thực thi của phần code bên trong nó. Nó chỉ kích hoạt chức năng quan sát và theo dõi các exception →

12345

try{

:

:

:

}

Trong C + + thì giải quyết và xử lý exception được thực thi trải qua 3 keywords chính là :Như bạn hoàn toàn có thể thấy, tên của câu lệnh rất trực quan sinh động – thử thực thi đoạn code bên trong xem điều gì xảy ra .

  • throw − Khi có bất thường xảy ra trong chương trình, sử dụng keyword throw để ném ra một ngoại lệ.
  • catch − Nếu bạn muốn bắt bất kỳ exception nào, thì bạn cần phải đặt câu lệnh catch sau câu lệnh try. Có thể coi câu lệnh catch như một hàm không có tên với một tham số xác định kiểu của exception. Lệnh catch sẽ chỉ bắt những exception tương thích với kiểu đã được chỉ định.

Giả sử một đoạn code nào đó có thể sẽ ném ra một ngoại lệ, một hàm sẽ bắt một ngoại lệ bằng cách sử dụng kết hợp các từ khóa trycatch. Một khối try / catch được rào xung quanh đoạn code có thể ném ra ngoại lệ. Code trong khối lệnh try được gọi là code được bảo vệ. Ví dụ về cú pháp sử dụng try / catch như sau →

123456789

try{

/ / protected code

}catch(ExceptionTypee1){

/ / catch block

}catch(ExceptionTypee2){

/ / catch block

}catch(ExceptionTypeeN){

/ / catch block

}

catch để bắt các exception có kiểu khác nhau.

Throwing Exceptions – Ném ngoại lệ

Có thể dùng nhiều câu lệnhđể bắt những exception có kiểu khác nhau .

Nếu bạn muốn “ném” một exception, bạn phải sử dụng câu lệnh throw. Câu lệnh throw cần phải được cung cấp dữ liệu mà sẽ được “đóng gói” thành một exception. Nếu bạn định gửi giá trị int, bạn sẽ phải viết một cái gì đó kiểu như thế này →

1

throw997;

Nếu bạn muốn ném một exception mang theo một đối tượng của class bất kỳ nào, bạn cần phải gọi constructor của class đó để chuẩn bị dữ liệu, ví dụ một exception kiểu string sẽ như sau →

1

throwstring(” Bye world ! “);

Sau đây là một ví dụ về việc ném một ngoại lệ khi chia cho điều kiện kèm theo 0 xảy ra →

123456

doubledivision(inta,intb){

if(b==0){

throw” Division by zero ! “;

}

return(a/b);

}

Catching Exceptions – Bắt ngoại lệ

Nếu bạn muốn bắt bất kỳ exception nào, thì bạn cần phải đặt câu lệnh catch sau câu lệnh try. Có thể coi câu lệnh catch như một hàm không có tên với một tham số xác định kiểu của exception. Lệnh catch sẽ chỉ bắt những exception tương thích với kiểu đã được chỉ định.

12345

try{

/ / protected code

}catch(ExceptionTypee){

/ / code to handle ExceptionType exception

}

Đoạn code trên sẽ bắt một exception được ném ra nởi protected code trong khối try nếu exception đó có kiểu là ExceptionType. Nếu muốn lệnh catch bắt exception thuộc bất kỳ kiểu dữ liệu nào thì không cần chỉ định kiểu của exception mà thay vào đó là dấu “…”. Ví dụ như sau →

12345

try{

/ / protected code

}catch(…){

/ / code to handle any exception

}

Sau đây là một ví dụ ném ra một exception khi xảy ra lỗi chia cho 0, và thực hiện bắt nó trong với câu lệnh catch →

123456789101112131415161718192021222324

#include

usingnamespacestd;

doubledivision(inta,intb){

if(b==0){

throw” Division by zero ! “;

}

return(a/b);

}

intmain(){

intx=50;

inty=0;

doublez=0;

try{

z=division(x,y);

cout<

}catch(constchar*msg){

cerr<

}

return0;

}

Bời vì chúng ta ném ra 1 exception kiểu const char* nên khi bắt exception này chúng ta cần sử dụng kiểu const char* trong lệnh catch. Nếu chúng ta biên dịch và chạy ví dụ trên thì kết quả in ra màn hình như sau

1

Divisionby

zero

!

Các exception chuẩn của C++

C++ cung cấp một danh sách exception chuẩn mà chúng ta có thể sử dụng được luôn, chúng được định nghĩa trong file header .

No Kiểu Ý nghĩa (Giải thích sơ bộ)
1 std::exception Exception chung nhất và là class cụ tổ của tất cả các exception chuẩn khác trong C++
2 std::bad_alloc Cấp phát bộ nhớ không thành công. Có thể được ném ra bởi toán tử new
3 std::bad_cast Ép kiểu động không thành công. Có thể được ném ra bởi dynamic_cast
4 std::bad_exception Có một exception nào đó được ném ra một cách không mong muốn
5 std::bad_typeid Được ném ra khi toán tử typeid thực hiện trên một con trỏ null
6 std::logic_error Các lỗi liên quan tới logic, thuật toán, tính hợp lệ của dữ liệu. Là class cha của các exception liên quan đến logic
7 std::domain_error Dữ liệu vượt quá khoảng cho phép
8 std::invalid_argument Truyền tham số không đúng cách
9 std::length_error Sử dụng các giá trị không hợp lệ để chỉ định kích thước / độ dài của tập hợp dữ liệu
10 std::out_of_range Sử dụng các indexs / keys không hợp lệ trong khi truy cập các bộ dữ liệu được đánh số / key
11 std::runtime_error Nó được thiết kế để đại diện cho tất cả các exceptions gây ra bởi các tình huống có thể xảy ra trong quá trình chạy của chương trình
12 std::overflow_error Tràn bộ nhớ do dữ liệu quá lớn so với kích thước bộ nhớ dùng để chứa nó
13 std::range_error Kết quả tính toán vượt quá khoảng cho phép
14 std::underflow_error Dữ liệu quá nhỏ để có thể biểu diễn giá trị có ý nghĩa

Tham khảo

— Phạm Minh Tuấn ( Shun ) —