Почему Cost STL iostreams не «дружественны к исключениям»? - PullRequest
44 голосов
/ 05 июля 2010

Я привык к Delphi VCL Framework, где TStreams генерирует исключения при ошибках (например, файл не найден, диск заполнен). Я портирую некоторый код, чтобы использовать вместо него C ++ STL, и iostreams обнаружил, что он не выдает исключения по умолчанию, а вместо этого устанавливает badbit / failbit flags .

Два вопроса ...

a: Почему это так - кажется странным дизайнерское решение для языка, созданного с исключениями в нем с первого дня?

б: Как лучше этого избежать? Я мог бы создавать классы шим, которые бросают, как я ожидал, но это похоже на изобретение колеса. Может быть, есть библиотека BOOST, которая делает это более разумно?

Ответы [ 4 ]

67 голосов
/ 05 июля 2010

a. C ++ не был создан за исключением первого дня. «C с классами» началось в 1979 году, а исключения были добавлены в 1989 году. Между тем, библиотека streams была написана еще в 1984 году (позднее становится iostreams в 1989 году (позже переиздана GNU в 1991 году)), просто не может используйте обработку исключений в начале.

Ref:

b. Вы можете включить исключения с помощью .exceptions метода .

// ios::exceptions
#include <iostream>
#include <fstream>
#include <string>

int main () {
  std::ifstream file;
  file.exceptions ( ifstream::failbit | ifstream::badbit );
  try {
    file.open ("test.txt");
    std::string buf;
    while (std::getline(file, buf))
      std::cout << "Read> " << buf << "\n";
  }
  catch (ifstream::failure e) {
    std::cout << "Exception opening/reading file\n";
  }
  std::cout.flush();

  file.close();

  return 0;
}
5 голосов
/ 05 июля 2010

Как говорит Кенни, вы можете включить исключения, если хотите. Но обычно ввод-вывод требует некоторого стиля возобновления программирования при возникновении ошибки, что нелегко поддерживать с помощью исключений - тестирование состояния потока после операции ввода намного проще. На самом деле я никогда не видел ни одного кода C ++, использующего исключения при вводе / выводе.

4 голосов
/ 05 июля 2010

ОК, пришло время "Ответить на мой вопрос" ...

Во-первых, спасибо KennyTM за историю.По его словам, C ++ был NOT , разработанный с исключениями с первого дня, поэтому неудивительно, что обработка исключений в iostreams была включена позже.

Во-вторых, как указывает Нейл B, имеющие исключенияошибки преобразования входного формата были бы серьезной болью.Это удивило меня, потому что я рассматривал iostreams как простой слой оболочки файловой системы, и я вообще не рассматривал этот случай.

В-третьих, кажется, что BOOST действительно что-то приносит на вечеринку: Boost.IOStreams .Если я правильно понимаю, они обрабатывают низкоуровневый ввод-вывод и аспект буферизации потоков, оставляя обычную библиотеку c ++ IOStreams для решения проблем преобразования.Boost.IOStreams использует исключения так, как я ожидал.Если я правильно понимаю, пример Кенни также может выглядеть следующим образом:

#include <ostream>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/stream.hpp>

int main () {
  boost::iostreams::stream_buffer <boost::iostreams::file_source> buf("test.txt");
  std::istream file(&buf);

  try {
    std::string buf;
    while (std::getline(file, buf))
      std::cout << "Read> " << buf << "\n";
  }
  catch (std::ios_base::failure::failure e) {
    std::cout << "Exception opening/reading file\n";
  }
  std::cout.flush();

  file.close();

  return 0;
}

Я думаю с этой версией такие вещи, как «файл не найден», должны выдавать, но ошибки «istream»будет сообщено по Badbit / Failbit.

3 голосов
/ 05 июля 2010
  1. Всякий раз, когда вы бросаете исключение, вы должны думать о безопасности исключения.Поэтому нет исключений, нет исключений, нет головной боли, связанной с безопасностью исключений.

  2. Iostreams также поддерживают исключения.Но бросать исключение необязательно.Вы можете включить исключение, установив exceptions (failbit | badbit | eofbit)

  3. Iostreams позволяет вам развить поведение как исключение, так и отсутствие ожидания.

...