正确的方式创建ostream到文件或cout [英] Proper way to create ostream to file or cout

查看:554
本文介绍了正确的方式创建ostream到文件或cout的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



这个线程和我自己的是,我想在一个类里面做。看看解决方案,虽然他们使用 std :: ostream out(buf)并使用buf即时构建ostream。我如何在我的日志类中正确声明这一点,只有一旦我进入我的日志构造函数,才能构造out对象?



我快速刺了一下但我不知道如果它是正确的,或者如果我在正确的轨道。感谢任何帮助,谢谢。



编辑:我想要能够 out< 一些字符串<<



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_

类Log
{
public:
枚举模式{STDOUT,FILE} ;

//默认需要
Log(const char * file = NULL);
〜Log();

//写方法
void write(char *);
void write(std :: string);
private:
模式模式;
std :: streambuf * buf;
std :: ofstream of;
std :: ostream out;
};

#endif


// log.cpp
#includelog.h
#include< iostream>
#include< stdlib.h>
#include< time.h>

Log :: Log(const char * file)
{
if(file!= NULL)
{
of.open
buf = of.rdbuf();
mode = FILE;
}
else
{
buf = std :: cout.rdbuf();
mode = STDOUT;
}

//附加到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;
}


解决方案

c> tmp std :: ostream tmp(buf); 并将其地址存储在 out this-> out =& tmp; 。但是, tmp 将在构造函数结束时超出范围,指针将不再指向有效对象。



你应该做的是make out 而不是 std :: ostream * code> std :: ostream :

  std :: ostream out; 

然后在你的构造函数中,一旦你有 buf 准备好了,你可以给它 out p>




回应编辑:



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

  Log :: Log文件)
:out(nullptr)
{
// ...
}


I am trying to create a Log class for my project at school. It needs to either be able to write information to the stdout or to a file depending on the parameters it is passed. I was looking into how to do this and I stumbled upon a thread with a similar question here: Obtain a std::ostream either from std::cout or std::ofstream(file)

The only difference between this thread and my own is that I want to do it inside of a class. Looking at the solution though they use std::ostream out(buf) and construct the ostream on the fly with buf. How can i declare this properly in my Log class to be able to construct the "out" object only once i enter my Log constructor?

I took a quick stab at it below but I am not sure if it is correct or if I am on the right track. Appreciate any help, thanks.

EDIT: I want to be able to do out << "Some string" << endl; after i get this Log class working properly.

EDIT2: An error I am now receiving with the new code below 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;
}

解决方案

You create tmp with std::ostream tmp(buf); and store the address of it in out with this->out = &tmp;. However, tmp will go out of scope at the end of the constructor and the pointer will no longer be pointing at a valid object.

What you should do instead is make out not a std::ostream* but simply a std::ostream:

std::ostream out;

Then in your constructor, once you've got the buf ready, you can give it to out by doing out.rdbuf(buf);.


Response to edit:

The std::ostream doesn't have a default constructor - it has to take a buffer pointer. My mistake. However, the fix is simple. Use your constructor's member initialization list to pass a null pointer (nullptr in C++11, 0 or NULL in C++03):

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

这篇关于正确的方式创建ostream到文件或cout的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆