Xử lý ngoại lệ C ++

Một ngoại lệ là một vấn đề phát sinh trong quá trình thực hiện một chương trình. Một ngoại lệ C ++ là một phản ứng đối với một trường hợp ngoại lệ phát sinh trong khi chương trình đang chạy, chẳng hạn như nỗ lực chia cho không.

Ngoại lệ cung cấp một cách để chuyển quyền kiểm soát từ một phần của chương trình sang phần khác. Xử lý ngoại lệ C ++ được xây dựng dựa trên ba từ khóa:try, catch,throw.

  • throw- Một chương trình ném ra một ngoại lệ khi một vấn đề xuất hiện. Điều này được thực hiện bằng cách sử dụngthrow từ khóa.

  • catch- Một chương trình bắt một ngoại lệ với một trình xử lý ngoại lệ tại vị trí trong một chương trình mà bạn muốn xử lý vấn đề. Cáccatch từ khóa chỉ ra việc bắt một ngoại lệ.

  • try - A trykhối xác định một khối mã mà các ngoại lệ cụ thể sẽ được kích hoạt. Tiếp theo là một hoặc nhiều khối bắt.

Giả sử một khối sẽ tạo ra một ngoại lệ, một phương thức bắt một ngoại lệ bằng cách sử dụng kết hợp trycatchtừ khóa. Một khối try / catch được đặt xung quanh mã có thể tạo ra một ngoại lệ. Mã trong khối try / catch được gọi là mã được bảo vệ và cú pháp để sử dụng try / catch như sau:

try {
   // protected code
} catch( ExceptionName e1 ) {
   // catch block
} catch( ExceptionName e2 ) {
   // catch block
} catch( ExceptionName eN ) {
   // catch block
}

Bạn có thể liệt kê nhiều catch các câu lệnh để bắt các loại ngoại lệ khác nhau trong trường hợp try khối tăng nhiều hơn một ngoại lệ trong các tình huống khác nhau.

Ngoại lệ ném

Các ngoại lệ có thể được ném vào bất kỳ đâu trong một khối mã bằng cách sử dụng throwtuyên bố. Toán hạng của câu lệnh ném xác định kiểu cho ngoại lệ và có thể là bất kỳ biểu thức nào và kiểu kết quả của biểu thức xác định kiểu ngoại lệ được ném ra.

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

double division(int a, int b) {
   if( b == 0 ) {
      throw "Division by zero condition!";
   }
   return (a/b);
}

Bắt ngoại lệ

Các catch khối theo sau trykhối bắt bất kỳ ngoại lệ nào. Bạn có thể chỉ định loại ngoại lệ bạn muốn bắt và điều này được xác định bởi khai báo ngoại lệ xuất hiện trong dấu ngoặc đơn theo sau từ khóa catch.

try {
   // protected code
} catch( ExceptionName e ) {
  // code to handle ExceptionName exception
}

Đoạn mã trên sẽ bắt một ngoại lệ ExceptionNamekiểu. Nếu bạn muốn chỉ định rằng khối catch phải xử lý bất kỳ loại ngoại lệ nào được đưa vào khối try, bạn phải đặt dấu chấm lửng, ..., giữa các dấu ngoặc đơn bao quanh khai báo ngoại lệ như sau:

try {
   // protected code
} catch(...) {
  // code to handle any exception
}

Sau đây là một ví dụ, ném một phép chia cho không ngoại lệ và chúng tôi bắt nó trong khối bắt.

#include <iostream>
using namespace std;

double division(int a, int b) {
   if( b == 0 ) {
      throw "Division by zero condition!";
   }
   return (a/b);
}

int main () {
   int x = 50;
   int y = 0;
   double z = 0;
 
   try {
      z = division(x, y);
      cout << z << endl;
   } catch (const char* msg) {
     cerr << msg << endl;
   }

   return 0;
}

Bởi vì chúng tôi đang nêu ra một loại ngoại lệ const char*, vì vậy trong khi bắt ngoại lệ này, chúng ta phải sử dụng const char * trong khối bắt. Nếu chúng tôi biên dịch và chạy đoạn mã trên, điều này sẽ tạo ra kết quả sau:

Division by zero condition!

Ngoại lệ tiêu chuẩn C ++

C ++ cung cấp danh sách các ngoại lệ tiêu chuẩn được xác định trong <exception>mà chúng tôi có thể sử dụng trong các chương trình của mình. Chúng được sắp xếp theo thứ bậc lớp cha-con được hiển thị bên dưới:

Dưới đây là mô tả nhỏ về từng ngoại lệ được đề cập trong hệ thống phân cấp ở trên -

Sr.No Ngoại lệ & Mô tả
1

std::exception

Một ngoại lệ và lớp cha của tất cả các ngoại lệ C ++ tiêu chuẩn.

2

std::bad_alloc

Điều này có thể được ném bởi new.

3

std::bad_cast

Điều này có thể được ném bởi dynamic_cast.

4

std::bad_exception

Đây là thiết bị hữu ích để xử lý các ngoại lệ không mong muốn trong chương trình C ++.

5

std::bad_typeid

Điều này có thể được ném bởi typeid.

6

std::logic_error

Một ngoại lệ về mặt lý thuyết có thể được phát hiện bằng cách đọc mã.

7

std::domain_error

Đây là một ngoại lệ được đưa ra khi một miền không hợp lệ về mặt toán học được sử dụng.

số 8

std::invalid_argument

Điều này được ném ra do các đối số không hợp lệ.

9

std::length_error

Điều này được ném ra khi một chuỗi std :: quá lớn được tạo.

10

std::out_of_range

Điều này có thể được ném bởi phương thức 'at', ví dụ một std :: vector và std :: bitset <> :: operator [] ().

11

std::runtime_error

Một ngoại lệ về mặt lý thuyết không thể được phát hiện bằng cách đọc mã.

12

std::overflow_error

Điều này được ném ra nếu xảy ra tràn toán học.

13

std::range_error

Điều này xảy ra khi bạn cố gắng lưu trữ một giá trị nằm ngoài phạm vi.

14

std::underflow_error

Điều này được ném ra nếu một quy trình toán học xảy ra.

Xác định ngoại lệ mới

Bạn có thể xác định các ngoại lệ của riêng mình bằng cách kế thừa và ghi đè exceptionchức năng lớp. Sau đây là ví dụ, cho thấy cách bạn có thể sử dụng lớp std :: exception để triển khai ngoại lệ của riêng bạn theo cách chuẩn:

#include <iostream>
#include <exception>
using namespace std;

struct MyException : public exception {
   const char * what () const throw () {
      return "C++ Exception";
   }
};
 
int main() {
   try {
      throw MyException();
   } catch(MyException& e) {
      std::cout << "MyException caught" << std::endl;
      std::cout << e.what() << std::endl;
   } catch(std::exception& e) {
      //Other errors
   }
}

Điều này sẽ tạo ra kết quả sau:

MyException caught
C++ Exception

Đây, what()là một phương thức công khai được cung cấp bởi lớp ngoại lệ và nó đã bị ghi đè bởi tất cả các lớp ngoại lệ con. Điều này trả về nguyên nhân của một ngoại lệ.