【问题标题】:Overloading << for both iostream and fstream为 iostream 和 fstream 重载 <<
【发布时间】:2019-11-04 03:21:20
【问题描述】:

我正在尝试重载来自 iostream 的 cout 和来自 fstream 的 fout

ostream& operator<<(ostream& cout, const Object& obj);

ofstream& operator<<(ofstream& fout, const Object& obj);

我希望第一个函数与控制台一起使用,以便为用户提供文本,而我希望第二个函数仅将变量的值输出到文件中。

然而,在

void save_data(const Object& obj)
{
    fstream fout("DataBase.txt", ios::out);

    if (fout.is_open())
    {
        fout << obj;
        fout.close();
    }

    else
        cout << "DataBase.txt could not be saved!" << endl;
}

我有一些文本用于指导用户在我的函数中重载文件中的 cout。

【问题讨论】:

    标签: c++


    【解决方案1】:

    std::fstream 继承自 std::iostream,而 std::iostream 又继承自 std::ostream。该链中没有std::ofstream,这使得该超载成为不合适的候选人。

    解决此问题的一种方法是在调用点使用std::ofstream 而不是std::fstream。您还可以为std::fstream 添加重载。但是,请注意std::ostream 不一定是控制台;这是您必须从其余代码中提供自己的保证。例如,std::ofstream 可以向上转换为std::ostream,然后用于打印Object,并且您的重载集将假定此流用于控制台。可能很难确保您的其余代码提供该保证。此外,控制台的稳健检测将依赖于平台,并在网站的其他地方有自己的答案(例如,for Windows)。

    现有程序处理此要求的一种方法是在命令行上有一个明确的“交互式”选项。例如,git 命令为此使用--interactive,有时使用-i。这样,用户就可以要求额外的引导输出,并且不需要巧妙的检测技巧。

    【讨论】:

    • 他不能只使用一个std::ostream 过载吗?
    • @0x499602D2,据我了解要求,这些重载有不同的输出。如果将策略更改为在不依赖流的静态类型的情况下选择控制台与文件的策略,那么一个重载应该就可以了,尽管它仍然会在内部分支以覆盖两个输出目标。
    • 在这两个重载中,它们都在写入流对象,并且仅此而已,对吗?那么应该只有一个重载。
    • @0x499602D2,不,OP 在发送到控制台时需要额外的输出。 “我希望第一个函数与控制台一起使用,以便为用户提供文本,而我希望第二个函数仅将变量的值输出到文件中。”这是我的解释,问题后面的“引导用户”支持。
    【解决方案2】:

    感谢@chris 的帮助,我能够弄清楚真正的问题是什么。通常不需要基于基本和派生的 I/O 流类型进行重载。通常有一种多态的方式来做你想做的事。在这种情况下,您可以检查正在写入的流是否为std::cout,并构造一个带有缓冲区的新流以写入它。

    std::ostream& operator<<(std::ostream& os, Obj const& obj) {
      std::ostream o(nullptr);
      if (&os == &std::cout) {
        o.rdbuf(std::cout.rdbuf());
      }
      o << "hello\n";
      return os;
    }
    

    如果缓冲区是空指针,写入o 将不会执行任何操作。这将允许您为用户编写控制台输出指南,而无需分离两种实现。

    如果您仍想拆分实现,请创建两个函数,并在上述 if 条件为真和假时调用适当的函数。

    std::ostream& write_with_console_o(std::ostream&);
    std::ostream& write_with_file_o(std::ostream&);
    
    std::ostream& operator<<(std::ostream& os, Obj const& obj) {
      if (&os == &std::cout) {
        return write_with_console_o(os);
      }
      return write_with_file_o(os);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-27
      • 1970-01-01
      • 2010-11-23
      相关资源
      最近更新 更多