2011-12-06 33 views
24

Tôi nhận thấy rằng có một vài tờ khai thú vị hơn trong số <exception> trong C++ 11. Ai có thể làm sáng tỏ những gì họ muốn nói và cách sử dụng chúng?Có mô tả hay về :: std :: nested_exception và bạn bè không?

Những cái tôi đang tự hỏi về là:

  1. ::std::nested_exception
  2. ::std::throw_with_nested
  3. ::std::rethrow_if_nested

Thêm vào đó, trong khi họ có vẻ tự giải thích, nó có thể là tốt đẹp để biết làm thế nào những hoạt động này:

  1. ::std::exception_ptr
  2. ::std::make_exception_ptr
  3. ::std::current_exception
  4. ::std::rethrow_exception
+1

Mô tả tốt (tốt nhất?) Có sẵn trong tiêu chuẩn. Bạn có thể đọc bản thảo [có sẵn công khai mới nhất] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf) miễn phí. – ybungalobill

Trả lời

22

Một số mã cấp cao sẽ quát chỉ bắt std::exception và in what(). Bạn muốn ép càng nhiều thông tin càng tốt vào cơ chế chung này, nhưng không mất bất kỳ thông tin nào. Xem xét việc triển khai một số thư viện lưu trữ:

archive::archive(const char* filename) 
{ 
    ifstream file(filename) 
    file.exceptions(ios_base::badbit); 
    open_archive(file); // throws ios_base::failure, or some other low-level exception. 
} 

Thông tin có sẵn cho lưu trữ không được ghi lại (ví dụ: tên tệp). Bên cạnh đó bạn muốn phân biệt các ngoại lệ đến từ lớp lưu trữ từ các ngoại lệ khác.

archive::archive(const char* filename) 
{ 
    try { 
     ifstream file(filename) 
     file.exceptions(ios_base::badbit); 
     open_archive(file); // throws ios_base::failure, or some other low-level exception. 
    } catch(const std::exception& e) { 
     throw archive_exception("Can't open archive", filename, e.what()); 
    } 
} 

Bây giờ chúng tôi đã thêm thông tin ngữ nghĩa cấp cao hơn mà archive lớp biết được, nhưng chúng tôi cũng bị mất các thông tin về nguyên nhân gốc của vấn đề (loại e). nested_exception có nghĩa là để giải quyết vấn đề này:

archive::archive(const char* filename) 
{ 
    try { 
     ifstream file(filename) 
     file.exceptions(ios_base::badbit); 
     open_archive(file); // throws ios_base::failure, or some other low-level exception. 
    } catch(...) { 
     throw_with_nested(archive_exception("Can't open archive", filename)); 
    } 
} 

Tất cả thông tin có sẵn được ghi lại. Bây giờ chúng ta có thể lấy nó một cách tổng quát trong trang bắt:

void print_exception_info(const std::exception& e) 
{ 
    cerr << e.what() << "\n"; 
    try { 
     rethrow_if_nested(e); 
    } catch(const std::exception& ne) { 
     print_exception_info(ne); 
    } catch(...) { } 
} 

int main() { 
    try { 
     run(); 
    } catch(const std::exception& e) { 
     print_exception_info(e); 
    } 
} 

Đầu ra sẽ mô tả hơn trước đây. Nó sẽ mô tả các vấn đề bắt đầu từ cấp cao đến cấp thấp:

Không thể mở kho lưu trữ "my_archive.bin"

Truy cập bị từ chối.

Hoặc có lẽ:

Không thể mở kho lưu trữ "my_archive.bin"

Ghi 'AABB' không tìm thấy.

Các chức năng hoạt động với exception_ptr được thiết kế để chuyển ngoại lệ giữa các chủ đề hoặc nói chung, lưu trữ ngoại lệ để sử dụng sau này. Làm thế nào họ làm việc phụ thuộc vào việc thực hiện. Mục đích là exception_ptr sẽ là một con trỏ được chia sẻ với đối tượng ngoại lệ. Tuy nhiên khi con trỏ này được tạo ra, khi ném ngoại lệ hoặc khi cố gắng để có được một exception_ptr với nó, là tùy thuộc vào việc thực hiện. Việc triển khai vẫn miễn phí để sao chép ngoại lệ khi bạn gọi current_exception().

+1

Chẳng phải 'print_exception_info' trông đẹp hơn như' try {std :: rethrow_if_nested(); } bắt ... '? – Cubbi

+0

Tôi thường được đặt chỗ để nhồi nhét ngoại lệ ở mức độ thấp trong trường hợp ngoại lệ cấp cao của mình khi tôi muốn làm điều này. Nhưng tôi có thể thấy cơ chế chung chung này tốt hơn như thế nào vì bạn có thể có một trình xử lý rất phổ biến để mở rộng tất cả. – Omnifarious

+0

Tôi đã mượn nhiều ví dụ của bạn cho [cppreference.com] (http://en.cppreference.com/w/cpp/error/exception/nested_exception) - vui lòng chỉnh sửa wiki đó nếu bạn muốn xóa hoặc cải thiện nó. – Cubbi

Các vấn đề liên quan