簡體   English   中英

C ++ 11異常設計。 成語和最佳實踐發生了變化?

[英]C++11 exception design. Idioms and best practices changed?

我想知道,自從C ++ 11以來,添加了線程之間的異常並添加了嵌套異常,一般來說,異常捕獲的習語是否已更改。

現在我們有:

  1. std::rethrow_if_nested
  2. std::rethrow_with_nested
  3. std::rethrow_exception
  4. std::current_exception

嵌套異常應該用於不丟失異常的上下文。

所以現在你可以這樣做:

void open_file(std::string const & file_name) {
   try {
      std::ifstream file;
      file.exceptions(ios::failbit | ios::badbit);
      file.open(file_name);
   }
   catch (...) {
      std::rethrow_with_nested(std::logic_error("File " + file_name + 
      " could not be open"));
   }
}

如果我沒錯,你可以得到這樣的回溯:

void print_backtrace(std::exception const & e, int depth = 0) {
   std::cerr << std::string(depth, ' ') << e.what() << std::endl;
   try {
      std::rethrow_if_nested(e);
   }
   catch (std::exception const & ex) {
      print_backtrace(ex, ++depth);
   }
}

因此,如果您將print_backtraceopen_file一起使用,它應該在輸出中為您提供std::logic_error + ios_base::failure

我的問題是:

  1. 這個習慣用法是在c ++ 11中處理異常的“正確”方法,因為我想在不丟失上下文的情況下捕獲所有異常嗎?
  2. print_backtrace函數中是否有一種方法可以使用catch (...)捕獲異常以捕獲絕對所有內容?
  3. 我不知道為什么需要std::rethrow_exception ,我也不知道什么時候。

我不知道我稱之為成語。 如果用''“正確”'表示類似於std::vector是如何默認使用的'正確'容器,我認為確實沒有一種特定的“正確”處理錯誤的方法。 這是一種正確的方式,因為它是明確定義的行為。

2.首先,您必須在不限於某些異常的上下文中調用print_backtrace() ,這意味着您必須在catch(...)塊中調用它:

    try {
      run();
    } catch(...) {
      print_backtrace();
    }

但是,您沒有傳遞給函數的已知類型的例外。 相反,您必須編寫函數來以不同方式訪問異常; 通過拋出該異常並在內部捕獲它(因為這是您可以將已知類型的變量綁定到任意異常的唯一機制)。

void print_backtrace(int depth = 0) {
  try {
    throw;
  }

  // this block shows how to handle exceptions of some known type
  // You can have your own types instead of std::exception
  catch (const std::exception & e) {
    std::cerr << std::string(depth, ' ') << e.what() << std::endl;
    try {
      std::rethrow_if_nested(e);
    }
    catch (...) {
      print_backtrace(++depth);
    }
  }

  // Not all nesting exceptions will be of a known type, but if they use the
  // mixin type std::nested_exception, then we can at least handle them enough to
  // get the nested exception:

  catch (const std::nested_exception & ne) {
    std::cerr << std::string(depth, ' ') << "Unknown nesting exception\n";

    try {
      ne.rethrow_nested();
    }
    catch (...) {
      print_backtrace(++depth);
    }
  }

  // Exception nesting works through inheritance, which means that if you
  // can't inherit from the type, then you can't 'mixin' std::nesting exception.
  // If you try something like std::throw_with_nested( int{10} ); Then you'll
  // hit this catch block when printing the backtrace.

  catch (...) {
    std::cerr << std::string(depth, ' ') << "Unknown exception\n";
  }
}

3. std::rethrow_exceptionstd::exception_ptr ,這是一種可用於傳輸任意異常的類型。 獲得該異常的唯一方法是使用正常的異常處理機制來catch異常,這意味着您必須能夠拋出該異常。 這就是rethrow_exception作用。 這可以用於將任意異常從一個線程傳輸到另一個線程(如std::future所做),或者將任意異常作為成員(如std::nested_exception ),或者將任意異常作為參數傳遞一個函數,它將嘗試打印一些異常描述。

void print_backtrace(std::exception_ptr e) {
  try {
    std::rethrow_exception(e);
  }

  catch (const std::exception & e) {
    // ...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM