Pourquoi les iStream C ++ STL ne sont-ils pas «exceptionnels»?

Je suis habitué à Delphi VCL Framework, où TStreams lance des exceptions sur les erreurs (par exemple, fichier introuvable, disque plein). Je porte du code pour utiliser C ++ STL à la place, et j’ai été surpris par les iostreams ne générant pas d’exceptions par défaut, mais en définissant plutôt des indicateurs badbit / failbit .

Deux questions…

a: Pourquoi est-ce – Cela semble être une décision de conception étrange pour un langage construit avec des exceptions dès le premier jour?

b: Comment éviter cela? Je pourrais produire des classes de cales qui lancent comme je l’espérais, mais cela donne l’impression de réinventer la roue. Peut-être y a-t-il une bibliothèque BOOST qui le fait de manière plus saine?

une. C ++ n’est pas construit avec des exceptions dès le premier jour. “C avec classes” a démarré en 1979, et des exceptions ont été ajoutées en 1989. La bibliothèque de streams a été écrite dès 1984 (elle deviendra plus tard iostreams en 1989 (réimplémentée par GNU en 1991)). le début.

Ref:

  • Bjarne Stroustrup, une histoire de C ++: 1979−1991
  • Bibliothèques C ++

b. Vous pouvez activer les exceptions avec la méthode .exceptions .

 // ios::exceptions #include  #include  #include  int main () { std::ifstream file; file.exceptions ( ifstream::failbit | ifstream::badbit ); try { file.open ("test.txt"); std::ssortingng 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; } 

Comme Kenny le dit, vous pouvez activer les exceptions si vous le souhaitez. Mais normalement, les E / S nécessitent une sorte de style de reprise de la programmation lorsqu’une erreur se produit, ce qui n’est pas facilement supporté par des exceptions – tester l’état du stream après une opération d’entrée est beaucoup plus simple. Je n’ai jamais vu de code C ++ utilisant des exceptions sur les E / S.

OK, c’est “Répondre à ma propre question” le temps …

Tout d’abord, merci à KennyTM pour l’histoire. Comme il le dit, C ++ n’a PAS été conçu avec des exceptions dès le premier jour, il n’est donc pas surprenant que la gestion des exceptions par iostreams ait été complétée par la suite.

Deuxièmement, comme le fait remarquer Neil B, le fait d’avoir des exceptions sur les erreurs de conversion du format d’entrée serait une douleur importante. Cela m’a surpris, parce que je considérais iostreams comme un simple wrapper de système de fichiers, et je n’avais pas envisagé cette possibilité.

Troisièmement, il semble que BOOST apporte quelque chose à la fête: Boost.IOStreams . Si je comprends bien, ceux-ci gèrent l’aspect E / S de bas niveau et la mise en mémoire tampon des stream, laissant la bibliothèque c ++ IOStreams standard pour gérer les problèmes de conversion. Boost.IOStreams utilise des exceptions de la manière prévue. Si je comprends bien, l’exemple de Kenny pourrait aussi ressembler à ceci:

 #include  #include  #include  int main () { boost::iostreams::stream_buffer  buf("test.txt"); std::istream file(&buf); try { std::ssortingng 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; } 

Je pense qu'avec cette version, des choses comme "fichier non trouvé" devraient être lancées, mais les erreurs "istream" seront signalées par badbit / failbit.

  1. Chaque fois que vous lancez une exception, vous devez penser à la sécurité des exceptions. Donc pas d’exception, pas d’exception, pas de maux de tête exceptionnels.

  2. Les stream Iostream prennent également en charge les exceptions. Mais lancer une exception est facultatif. Vous pouvez activer l’exception en définissant des exceptions (failbit | badbit | eofbit)

  3. Les stream Iostream vous permettent de gérer à la fois les comportements d’exception et les comportements sans expection.