【问题标题】:Simple C++ logging class - ostream reference initialization简单的 C++ 日志记录类 - ostream 引用初始化
【发布时间】:2013-09-04 08:08:22
【问题描述】:

我在这里阅读了几个已经回答的类似问题,但我还不明白,所以在关闭之前请记住这一点:)。我想要一个带有 Print() 方法的简单 Log 对象。如果 Log 是不带参数构造的,则 logging 是 cout。否则,参数描述一个记录日志的文件。

(我怀疑部分问题在于理解所有stream 类之间的关系。)

编译时,错误为:

Log.cpp:11:23: error: invalid initialization of reference of type ‘std::ofstream& {aka std::basic_ofstream<char>&}’ from expression of type ‘std::ostream {aka std::basic_ostream<char>}’

Log.h:

#ifndef LOG_H
#define LOG_H
#include <string>
#include <fstream>

class Log {

public:
    Log();
    Log(const char*, const char*);

    void Print(const char*  msg,...);

private:
    // instance contains a reference to ostream
    std::ofstream&  output_stream;
};

#endif

Log.cpp:

#include "Log.h"
#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;
#include <fstream>

// Constructor w/no parms = log to cout
Log::Log() :
    output_stream(cout)
{}

// Constructor w/parms = log to file
Log::Log(const char* dir, const char* file) {
    string output_file_name = string(dir) + "/" + string(file);
    output_stream.open(output_file_name.c_str(), std::ofstream::out);
}

// Print() sends output to the stream (we'll do printf semantics later)
void
Log::Print(const char* msg,...) {
    output_stream << msg << endl;
}

【问题讨论】:

    标签: c++ logging reference cout ostream


    【解决方案1】:

    cout 不是ofstream 类型,因此您不能将ofstream 引用绑定到它。 output_stream 应该是 ostream&amp; 类型,这将允许它引用 cout 和文件流,因为 ofstreamostream 的子类。

    另外,在用户提供文件名的情况下,你仍然需要一些东西供参考参考,你不能就这样使用它。我建议您存储一个实际的ofstream 对象(或unique_ptr&lt;ofstream&gt;),并让output_stream 引用它。确保在您的类定义中声明ofstream 对象之前 ostream 引用,否则当您尝试在初始化列表中绑定引用时,您将有未定义的行为。或者你可以把它变成一个指针,而不是一个引用,然后在构造函数的主体中赋值。

    【讨论】:

    • +1 关于成员顺序和初始化列表的重要性的出色说明。为了 OP 的利益,see this snippet.
    • 这个解释让我找到了解决方案。一个问题:当我声明 [或它是否已定义?] Log logger("/path/to", "logfile"); 时,它起作用了。当我写Log logger(); 时,编译器抱怨request for member ‘Print’ in ‘logger’, which is of non-class type ‘Log()’。当我写Log logger; 时,它起作用了。 Log logger() 在说什么?
    • @Chap: Log logger(); 被解析为一个名为“logger”的函数的声明,它不接受任何参数并返回一个Log 对象。
    【解决方案2】:

    我建议改组filebufs 或其他streambufs。

    #include <string>
    #include <ostream>
    #include <fstream>
    
    class Log {
    
    public:
        Log();
        Log(const char*, const char*);
    
        void Print(const char*  msg,...);
    
    private:
        // instance contains a reference to ostream
        std::ostream  output_stream;
        std::ofstream _file;
    };
    

    还有cpp

    #include <iostream>
    #include <string>
    #include <fstream>
    
    // Constructor w/no parms = log to cout
    Log::Log()
        : output_stream(std::cout.rdbuf())
    {}
    
    // Constructor w/parms = log to file
    Log::Log(const char* dir, const char* file) 
        : output_stream(nullptr)
    {
        std::string output_file_name = std::string(dir) + "/" + std::string(file);
        _file.open(output_file_name.c_str(), std::ofstream::out);
        output_stream.rdbuf(_file.rdbuf());
    }
    
    // Print() sends output to the stream (we'll do printf semantics later)
    void Log::Print(const char* msg,...) {
        output_stream << msg << std::endl;
    }
    

    【讨论】:

      猜你喜欢
      • 2016-04-22
      • 2011-01-29
      • 2017-10-05
      • 2021-02-12
      • 1970-01-01
      • 2022-01-25
      • 2020-08-31
      • 2021-05-31
      • 2011-12-29
      相关资源
      最近更新 更多