安全地重载流运算符>>

时间:2009-08-15 01:01:22

标签: c++ operator-overloading stream

有大量关于重载operator<<的信息,以模仿将toString() - 样式方法转换为字符串的方法。我对实现逆,operator>>以将字符串反序列化为对象感兴趣。

通过检查STL来源,我收集到了:

istream &operator>>(istream &, Object &);

将是用于反序列化Object类型对象的正确函数签名。不幸的是,我对如何正确实现这一点感到茫然 - 特别是如何处理错误:

  1. 如何在流中指示无效数据?抛出异常?
  2. 如果流中的 格式错误的数据,流应处于什么状态?
  3. 在返回运算符链接的引用之前是否应重置任何标志?

3 个答案:

答案 0 :(得分:18)

  1. 如何在流中指示无效数据?抛出异常?
  2. 您应该设置fail位。如果流的用户想要抛出异常,他可以配置流(使用istream::exceptions),并且流将相应地抛出。我会这样做,然后

    stream.setstate(ios_base::failbit);
    
    1. 如果流中存在格式错误的数据,流应处于什么状态?
    2. 对于不符合您要阅读的格式的格式错误的数据,通常应设置fail位。对于内部流特定错误,使用bad位(例如,如果没有连接到流的缓冲区)。

      1. 在返回运算符链接的引用之前是否应重置任何标志?
      2. 我没有听说过这样的事情。


        要检查流是否处于良好状态,可以使用istream::sentry类。创建一个对象,传递流和true(告诉它不要立即跳过空格)。如果设置了falseeoffail位,则哨兵将评估为bad

        istream::sentry s(stream, true);
        if(!s) return stream;
        // now, go on extracting data...
        

答案 1 :(得分:2)

一些补充说明:

  • 在实现运算符&gt;&gt;时,您可能应该考虑使用 bufstream而不是运营商的其他重载&gt;&gt ;;

  • 操作期间发生的异常应该转换为 failbit或badbit(streambuf的成员可能会抛出,取决于 使用的类);

  • 设置状态可能会抛出;如果你在捕获后设置状态 例外,您应该传播原始异常而不是传播异常 被setstate抛出;

  • 宽度是您应该注意的字段。如果你是 考虑到这一点,你应该将其重置为0.如果你正在使用其他 运营商GT;&GT;要做基本的工作,你必须计算你传递的宽度 从你收到的那个;

  • 考虑考虑区域设置。

Lange和Kreft(标准C ++ IOStreams和Locales )甚至将它融合在一起 更多细节。他们为错误处理提供了一个模板代码 大约一页。

答案 2 :(得分:0)

至于旗帜,我不知道某处是否有任何标准,但重置它们是个好主意。

Boost有完整的raii包装:IO State Savers