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

Cách bắt tất cả ngoại lệ (catch-all) trong C++

Trong C++, có thể bắt tất cả các loại ngoại lệ bằng cú pháp catch(...) - gọi là catch-all handler.

Cú pháp

try {
    // code có thể ném ngoại lệ
} catch (SpecificException& e) {
    // Xử lý ngoại lệ cụ thể (ưu tiên cao hơn)
} catch (...) {
    // Bắt TẤT CẢ ngoại lệ còn lại
}

Ví dụ

#include <iostream>
using namespace std;

void func(int a) {
    try {
        if (a == 0) throw 23.33;      // ném double
        if (a == 1) throw 's';        // ném char
        if (a == 2) throw "error";    // ném const char*
        if (a == 3) throw std::runtime_error("runtime");
    } catch (...) {
        cout << "Đã bắt ngoại lệ (bất kỳ loại nào)!\n";
    }
}

int main() {
    func(0);  // double
    func(1);  // char
    func(2);  // const char*
    func(3);  // std::exception
    func(4);  // không ném
    return 0;
}

Kết quả

Đã bắt ngoại lệ (bất kỳ loại nào)!
Đã bắt ngoại lệ (bất kỳ loại nào)!
Đã bắt ngoại lệ (bất kỳ loại nào)!
Đã bắt ngoại lệ (bất kỳ loại nào)!

Lưu ý quan trọng

  • Không thể truy cập đối tượng ngoại lệ trong catch(...) - không biết kiểu, không lấy được thông tin
  • Nên đặt catch(...) cuối cùng sau các catch cụ thể
  • Dùng cho: logging, cleanup, chuyển đổi ngoại lệ, tránh crash chương trình
  • Trong destructor: luôn nên có catch-all để tránh ném ngoại lệ ra khỏi destructor

Ví dụ thực tế: Logging và re-throw

void criticalOperation() {
    try {
        // risky code
    } catch (const std::exception& e) {
        logError(e.what());
        throw; // re-throw nguyên vẹn
    } catch (...) {
        logError("Unknown exception");
        throw; // re-throw
    }
}

C++11: std::current_exception

Có thể lấy đối tượng ngoại lệ trong catch-all:

catch (...) {
    std::exception_ptr eptr = std::current_exception();
    // lưu, chuyển thread, hoặc re-throw sau
    std::rethrow_exception(eptr);
}