繁体   English   中英

为 iostream 和 fstream 重载 <<

[英]Overloading << for both iostream and fstream

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

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

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

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

然而,在

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;
}

我有用于在我的 function 中引导用户的文本,它使我的文件中的 cout 过载。

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

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

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

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

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;
}

如果缓冲区是 null 指针,则写入o将不起作用。 这将允许您为用户编写控制台 output 指南,而无需分离两种实现。

如果您仍想拆分实现,请创建两个函数并在上述 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);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM