我已经习惯了Delphi VCL框架,其中TStreams会在错误上抛出异常(例如找不到文件,磁盘已满)。我正在移植一些代码以使用C ++ STL,并且已被iostream捕获而不是默认情况下抛出异常,而是设置badbit/failbit flags。
两个问题......
a:为什么这样 - 从第一天起,对于使用异常构建的语言,这似乎是一个奇怪的设计决定?
b:如何最好地避免这种情况?我可以按照我的预期生产可以抛出的垫片类,但这就像重新发明轮子一样。也许有一个BOOST库以更加健全的方式做到这一点?
答案 0 :(得分:67)
a。从第一天开始,C ++就不会构建异常。 “C with classes”始于1979年,并且在1989年增加了例外。同时,streams
库早在1984年(后来在1989年成为iostreams
(后来在1991年由GNU重新实现)中编写) ,它只是不能在开始时使用异常处理。
价:
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;
}
答案 1 :(得分:5)
正如Kenny所说,如果需要,您可以启用例外。但是通常I / O在发生错误时需要某种恢复类型的编程,使用异常不容易支持 - 在输入操作更简单之后测试流的状态。我从来没有真正看到任何在I / O上使用异常的C ++代码。
答案 2 :(得分:4)
好的,这是“回答我自己的问题”时间......
首先,感谢KennyTM的历史。正如他所说,C ++从第一天起就设计了 NOT 例外,所以毫无疑问,iostreams'异常'处理在之后被拴上了。
其次,正如Neil B指出的那样,输入格式转换错误的例外将是一个重大的痛苦。这让我感到惊讶,因为我认为iostreams是一个简单的文件系统包装层,我根本没有考虑过这个案例。
第三,似乎BOOST确实为聚会带来了一些东西:Boost.IOStreams。如果我理解正确,它们处理流的低级I / O和缓冲方面,留下常规的c ++ IOStreams库来处理转换问题。以我期望的方式Boost.IOStreams 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;
}
我认为使用此版本,“找不到文件”之类的内容应该抛出,但badbit / failbit会报告“istream”错误。
答案 3 :(得分:3)
每当您抛出异常时,您都需要考虑异常安全性。所以没有例外,没有例外,没有例外 - 安全问题。
Iostreams也支持异常。但抛出异常是可选的。您可以通过设置exceptions (failbit | badbit | eofbit)
Iostreams可让您接受例外和无行为的行为。