代码之家  ›  专栏  ›  技术社区  ›  Roddy

为什么C++ STL流不是“异常友好”?

  •  44
  • Roddy  · 技术社区  · 14 年前

    我习惯于DelphiVCL框架,在这个框架中,TStream在错误时抛出异常(例如,找不到文件,磁盘已满)。我正在移植一些代码来代替C++ STL,默认情况下,IOFFROSE已经被捕获,而不是在默认情况下抛出异常,但是设置 badbit/failbit flags 相反。

    两个问题…

    A:为什么呢?对于一种语言来说,这似乎是一个奇怪的设计决定,从第一天起就有例外了。

    B:如何最好地避免这种情况?我可以生成如我所期望的那样抛出的垫片类,但这感觉像是在重新设计轮子。也许有一个能以更理智的方式完成这个任务的Boost库?

    4 回复  |  直到 8 年前
        1
  •  67
  •   kennytm    11 年前

    a. C++不是从第一天就建立异常的。C类课程”始于1979年,1989年又增加了例外情况。与此同时, streams 图书馆早在1984年就开始编写(后来成为 iostreams 1989年(后来由GNU于1991年重新实施),它刚开始就不能使用异常处理。

    裁判:

    B. 可以 启用例外 the .exceptions method .

    // 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;
    }
    
        2
  •  5
  •   anon    14 年前

    正如肯尼所说,如果需要,可以启用异常。但通常情况下,当发生错误时,I/O需要某种类型的恢复式编程,这是使用异常不容易支持的——在输入操作之后测试流的状态要简单得多。我从未见过任何在I/O.上使用异常的C++代码。

        3
  •  4
  •   Roddy    14 年前

    好吧,现在是“回答我自己的问题”的时候……

    首先,感谢KennyTM的历史。正如他所说,C++是 不是 从第一天起就有例外设计,所以IOstreams的“例外”处理随后就被固定了,这不足为奇。

    其次,正如尼尔B所指出的,输入格式转换错误的异常情况将是一个巨大的痛苦。这让我吃惊,因为我把iostreams看作是一个简单的文件系统包装层,而我根本没有考虑过这种情况。

    第三,它似乎给聚会带来了一些东西: Boost.IOStreams . 如果我理解正确,这些处理流的低级I/O和缓冲方面,留下规则的C++ IOFScript库来处理转换问题。IP流 does use exceptions 以我所期望的方式。如果我理解正确,Kenny的例子也可以是这样的:

    #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报告。

        4
  •  3
  •   Jonathan Wakely    8 年前
    1. 每当抛出异常时,都需要考虑异常安全性。所以没有例外,没有例外,没有例外,安全性头痛。

    2. iostreams也支持异常。但是抛出异常是可选的。您可以通过设置启用异常 exceptions (failbit | badbit | eofbit)

    3. iostreams让您可以同时享受异常和无期望的行为。