我正在尝试为学校的项目创建一个Log类。它需要能够将信息写入stdout或文件,具体取决于传递的参数。我正在研究如何做到这一点,我偶然发现了一个类似问题的帖子:Obtain a std::ostream either from std::cout or std::ofstream(file)
这个帖子和我自己的唯一区别是我想在一个类里面做。查看解决方案虽然他们使用std::ostream out(buf)
并使用buf动态构建ostream。如何在我的Log类中正确声明这一点,以便只有在我进入Log构造函数后才能构造“out”对象?
我在下面快速刺了一下,但我不确定它是否正确或我是否在正确的轨道上。感谢任何帮助,谢谢。
编辑:我希望能够让这个Log类正常工作后能够out << "Some string" << endl;
。
EDIT2:我现在收到的错误是error : 'std::basic_ostream<_CharT, _Traits>::basic_ostream() [with _CharT = char, _Traits = std::char_traits<char>]' is protected
// log.h
#include <string>
#include <fstream>
#ifndef LOG_H_
#define LOG_H_
class Log
{
public:
enum Mode { STDOUT, FILE };
// Needed by default
Log(const char *file = NULL);
~Log();
// Writing methods
void write(char *);
void write(std::string);
private:
Mode mode;
std::streambuf *buf;
std::ofstream of;
std::ostream out;
};
#endif
// log.cpp
#include "log.h"
#include <iostream>
#include <stdlib.h>
#include <time.h>
Log::Log(const char *file)
{
if (file != NULL)
{
of.open(file);
buf = of.rdbuf();
mode = FILE;
}
else
{
buf = std::cout.rdbuf();
mode = STDOUT;
}
// Attach to out
out.rdbuf(buf);
}
Log::~Log()
{
if (mode == FILE)
of.close();
}
void Log::write(std::string s)
{
out << s << std::endl;
}
void Log::write(char *s)
{
out << s << std::endl;
}
答案 0 :(得分:3)
您使用tmp
创建std::ostream tmp(buf);
,并将out
的地址与this->out = &tmp;
一起存储。但是,tmp
将超出构造函数末尾的范围,并且指针将不再指向有效对象。
您应该做的是让out
而不是std::ostream*
,而只是std::ostream
:
std::ostream out;
然后在您的构造函数中,一旦准备好buf
,就可以通过out
将其提交给out.rdbuf(buf);
。
对编辑的回应:
std::ostream
没有默认构造函数 - 它必须带一个缓冲区指针。我的错。但是,修复很简单。使用构造函数的成员初始化列表在C ++ 11中传递空指针(nullptr
,在{+ C} 03中传递0
或NULL
}:
Log::Log(const char *file)
: out(nullptr)
{
// ...
}