【问题标题】:Deriving std::ofstream and overloading operator<<派生 std::ofstream 和重载 operator<<
【发布时间】:2018-11-15 03:55:30
【问题描述】:

如何从 std::ofstream 类派生,在写入文件之前添加一些操作? 换句话说,替换代码就像

int main()
{
   std::ofstream file("file.txt");
   file << "something" << std::endl;
   return 0;
}

通过

class MyFile : public std::ofstream
{
   MyFile(std::string filename) : std::ofstream(filename) {}

   ??? operator<< ???   <-- HERE1
   {
      // 1. do some stuff with the input
      // 2. if wanted,
      // flush it to the base class operator<<
   }
};

class MyFileC
{
private:
   std::ofstream intern_os;
public:
   MyFileC(std::string filename) : intern_os(filename) {}

   MyFileC& operator<<( input ???   <-- HERE2  )
   {


          // 1. do some stuff with the input
          // e.g (a) IF the input is a std::string,
          // THEN, if it contains "signal",
          // OnSignal();
          // or (b) if file size is too big, clear it ...
          // 2. Flush it (for all possible types):

      intern_os << input;
   }
};

int main()
{
    MyFile file("file2.txt"); // (or with MyFileC)
    file << "something" << std::endl;
    return 0;
}

我们可以在其中例如在编写之前即时过滤等。

??? 行中添加什么来享受所有现有的 std::ofstream.operator

  • HERE1 : 更优雅,有继承方式; 或者如果不可能(在下面的 cmets 之后),
  • HERE2 :传递“可以传递给内部 std::ofstream 的任何内容”的类型(字符串、整数、...)

【问题讨论】:

  • 你不能,真的。 operator&lt;&lt; 未在基础中声明 virtual,因此任何通过 ofstream 的引用/指针使用您的 MyFile 的人都不会调用您的派生 operator&lt;&lt;。一般来说,“如何从std:: 类继承”的答案是“不要”。我的意思是,你可能可以做到,它甚至可能看起来足够接近工作 - iff 你总是将它用作MyFile - 但是你只会利用派生的@ 987654332@ 会隐藏基础operator&lt;&lt;,而不是覆盖它,这看起来很脆弱。
  • 不推荐从标准库流派生。通常的方法是在必要时用派生自std::streambuf 的类替换底层流缓冲区。也就是说,这看起来是一个很好的机会来练习 Composition over Inheritance 并用您自己的类和函数包装底层流。
  • @underscore_d Oh.. 然后必须使用组合,在 MyFile 等中嵌入 std::ofstream ?
  • 嗯,这取决于你想对operator &lt;&lt; 保留什么,以及输入的内容是什么。如果您只想处理std::stringsconst char *,那么在包含 std::ofstream 的类上定义自己的运算符可能是可行的方法。相反,如果您希望能够接受任何存在覆盖ostream&amp; operator &lt;&lt;(ostream&amp;, const T&amp;) 的类,则应在std::basic_ostream 的子类中使用自定义std::streambuf。您没有提供足够的详细信息以获得更准确的答案...

标签: c++ inheritance std


【解决方案1】:

operator&lt;&lt; 不打算被派生流类覆盖。相反,您应该覆盖 std::basic_streambuf::overflow 和/或 std::basic_streambuf::xsputn

overflow 尤其是在缓冲区溢出时在内部调用。如果您想提供自己的缓冲,您可以通过在覆盖的流类中通过std::basic_streambuf::setp 初始化流指针来实现。这些链接附带了如何执行此操作的示例。

这里只有一个外观问题:这些都是 buffer 方法。您想要覆盖std::fstream,它是一个stream 类,而不是buffer class。因此,您需要做两件事:

  1. 如上所述覆盖std::basic_filebuf
  2. 使用std::fstream::rdbuf 将文件流对象的关联缓冲区设置为覆盖的文件缓冲区类的实例。您可以在现有 std::fstream 的实例或该类型的自定义子类上执行此操作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-01
    • 2021-06-16
    • 2018-06-15
    • 1970-01-01
    • 1970-01-01
    • 2015-12-16
    • 2017-07-25
    相关资源
    最近更新 更多