我在这里已经阅读了几个类似的问题已经得到了解答,但我还没有理解,所以请在关闭之前牢记这一点:)。我想要一个带有Print()方法的简单Log对象。如果构造的Log没有参数,则记录为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;
}
答案 0 :(得分:2)
cout
不属于ofstream
类型,因此您无法绑定ofstream
引用。 output_stream
应该是ostream&
类型,这将允许它引用cout
和文件流,因为ofstream
是ostream
的子类。< / p>
此外,在用户提供文件名的情况下,您仍需要参考引用的内容,您不能只是按原样使用它。我建议您存储实际的ofstream
对象(或unique_ptr<ofstream>
),然后让output_stream
引用它。确保在类定义中 ofstream
引用之前声明ostream
对象,否则当您尝试在初始化列表中绑定引用时,将会有未定义的行为。或者你可以把它作为指针,而不是引用,并将它分配给构造函数的主体。
答案 1 :(得分:0)
我建议改组filebuf
s或其他streambuf
s。
#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;
}