正确的方法来创建ostream文件或cout

时间:2013-02-08 21:25:47

标签: c++

我正在尝试为学校的项目创建一个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;
}

1 个答案:

答案 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中传递0NULL}:

Log::Log(const char *file)
  : out(nullptr)
{
  // ...
}