4

我正在尝试为我在学校的项目创建一个 Log 类。它需要能够根据传递的参数将信息写入标准输出或文件。我正在研究如何做到这一点,我偶然发现了一个带有类似问题的线程:从 std::cout 或 std::ofstream(file) 获取 std::ostream

该线程与我自己的线程之间的唯一区别是我想在课堂内进行。std::ostream out(buf)尽管他们使用buf 即时使用和构建 ostream,但正在查看解决方案。如何在我的 Log 类中正确声明它,以便只有在我进入 Log 构造函数后才能构造“out”对象?

我在下面快速尝试了一下,但我不确定它是否正确,或者我是否走在正确的轨道上。感谢任何帮助,谢谢。

out << "Some string" << endl;编辑:我希望在我让这个 Log 类正常工作后能够做。

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;
}
4

1 回答 1

3

您使用 创建tmp并将std::ostream tmp(buf);其地址存储在outthis->out = &tmp;。但是,tmp将在构造函数的末尾超出范围,并且指针将不再指向有效对象。

您应该做的不是outastd::ostream*而是简单地 a std::ostream

std::ostream out;

然后在你的构造函数中,一旦你buf准备好了,你可以out通过做out.rdbuf(buf);.


回复编辑:

std::ostream没有默认构造函数 - 它必须采用缓冲区指针。我的错。但是,修复很简单。使用构造函数的成员初始化列表传递空指针(nullptr在 C++110NULLC++03 中):

Log::Log(const char *file)
  : out(nullptr)
{
  // ...
}
于 2013-02-08T21:34:43.257 回答