Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C++

Cách ném (throw) ngoại lệ trong C++

Từ khóa throw dùng để ném một ngoại lệ (exception) khi phát hiện điều kiện lỗi. Ngoại lệ có thể là bất kỳ kiểu dữ liệu nào.

Cú pháp cơ bản

throw expression;

Ví dụ cơ bản: Chia cho 0

#include <iostream>
using namespace std;

double divide(int a, int b) {
    if (b == 0) {
        throw "Lỗi: Chia cho 0!";  // ném const char*
    }
    return static_cast(a) / b;
}

int main() {
    int x = 50, y = 0;
    
    try {
        double result = divide(x, y);
        cout << "Kết quả: " << result << endl;
    } catch (const char* msg) {
        cerr << "Ngoại lệ: " << msg << endl;
    }
    
    return 0;
}

Kết quả

Ngoại lệ: Lỗi: Chia cho 0!

Các kiểu dữ liệu thường ném

1. Chuỗi literal (C-style)

throw "Error message";

Đơn giản nhưng không khuyến khích (không có thông tin kiểu, stack trace).

2. std::exception và lớp dẫn xuất (Khuyến nghị)

#include <stdexcept>
#include <string>

throw std::runtime_error("File not found: " + filename);
throw std::invalid_argument("Invalid parameter: " + paramName);
throw std::out_of_range("Index " + to_string(i) + " out of range");
throw std::logic_error("Logic error");
throw std::bad_alloc(); // hết bộ nhớ

3. Custom exception class

class MyException : public std::exception {
    string message;
public:
    MyException(const string& msg) : message(msg) {}
    const char* what() const noexcept override { return message.c_str(); }
};

// Sử dụng
throw MyException("Custom error details");

4. Ném đối tượng kiểu tự định nghĩa

struct ErrorInfo {
    int code;
    string message;
    string file;
    int line;
};

throw ErrorInfo{404, "Not found", __FILE__, __LINE__};

Quy tắc tốt (Best Practices)

  • Ném bằng giá trị, bắt bằng const reference: catch (const MyException& e)
  • Kế thừa từ std::exception để tương thích chuẩn
  • Ghi đè what() trả về mô tả lỗi
  • Không ném trong destructor (gọi std::terminate)
  • Dùng noexcept cho hàm không ném ngoại lệ

Re-throw (ném lại)

catch (const std::exception& e) {
    log(e.what());
    throw; // ném lại nguyên vẹn exception hiện tại
}