文件处理类的重载运算符<<困难

Difficulty overloading operator<< for file handling class

本文关键字:lt 困难 运算符 重载 处理 文件      更新时间:2023-10-16

我必须:

使用构造函数定义一个 File_handle 类,该构造函数采用字符串参数(文件名),在构造函数中打开文件,然后在析构函数中关闭该文件。

据我了解,这个类用于提供 RAII,我正在尝试使用 FILE* 作为基本数据结构来实现该类,我的目标基本上是使FILE*成为一个智能指针:

fileHandler.h

// Class CFile_handler based on FILE*
class CFile_handler {
public:
    CFile_handler();                                           // default constructor   
    CFile_handler(const std::string& fileName,                 // constructor
                  const std::string& mode);     
    ~CFile_handler ();                                          // destructor
    // modifying member function
    void open_file(const std::string& fileName, 
                   const std::string& mode);
protected:
    typedef FILE* ptr;
private:
    CFile_handler(const CFile_handler&);                        // prevent copy creation
    CFile_handler& operator= (const CFile_handler&);            // prevent copy assignment
    ptr c_style_stream;                                         // data member
};

fileHandler.cpp

// Class CFile_handler member implementations
// default constuctor
CFile_handler::CFile_handler() {
}
// constructor
CFile_handler::CFile_handler(const std::string& fileName, const std::string& mode = "r")
    : c_style_stream( fopen( fileName.c_str(), mode.c_str() ) ) 
{
}
// destructor
CFile_handler::~CFile_handler() {
    if (c_style_stream) fclose(c_style_stream);
}
// Modifying member functions
void CFile_handler::open_file(const std::string& fileName, const std::string& mode) {
    c_style_stream = ( fopen( fileName.c_str(), mode.c_str() ) );
}

但是,我在重载I/O operators<</>>方面遇到困难,因为我无法弄清楚如何实现它们中的任何一个。

如何重载operator<<以使类与iostream对象一起工作?

编辑:

正如@LokiAstari所提出的那样,从istream继承并定义自己的streambuf会是更好的策略。

有人可以举例或指导如何处理FILE*streambuf吗?


我想提供的是:

CFile_handler fh("filename.txt", "r");
std::string file_text;
fh >> file_text;

或:

CFile_handler fh("filename.txt", "w");
fh << "write this to file";

您可以使用 std::streambuf 派生 std::streams 的类型来处理 FILE*

#include <iostream>
#include <stdio.h>
class OutputFilePointerStream: public std::ostream
{
    class OutputFilePointerStreamBuf: public std::streambuf
    {
        FILE*   buffer;
        public:
            OutputFilePointerStreamBuf(std::string const& fileName)
            {
                buffer  = fopen(fileName.c_str(), "w");
            }
            ~OutputFilePointerStreamBuf()
            {
                fclose(buffer);
            }
            virtual std::streamsize xsputn(const char* s, std::streamsize n) override
            {
                static char format[30];
                sprintf(format, "%%.%lds", n);
                fprintf(buffer, format, s);
                return n;
            }
    };
    OutputFilePointerStreamBuf       buffer;
    public:
        OutputFilePointerStream(std::string const& fileName)
            : std::ostream(nullptr)
            , buffer(fileName)
        {
            rdbuf(&buffer);
        }
};
int main()
{
    OutputFilePointerStream      fileStream("Test");
    fileStream << "Testing: " << 5 << "><n";
    fileStream << "Line Againn";
}

您的operator<<函数是将CFile_handler对象输出到C++输出流,而不是输出CFile_handler对象。

要输出到CFile_handler对象,您有两种选择:

  1. 作为成员函数

    CFile_handler& CFile_handler::operator<<(int value)
    {
        // Output an integer to the contained file
        return *this;
    }
    
  2. 或者作为非成员函数,将CFile_handler引用作为第一个参数:

    CFile_handler& operator<<(CFile_handler& file, int value)
    {
        // Output an integer to the file contained in `file`
        return file;
    }
    

对于上述两种变体,您可以执行例如

CFile_handler my_file(...);
my_file << 1234;