试图写std:out并同时归档

时间:2012-12-02 00:05:26

标签: c++ iostream

我试图通过重载流来在c ++中同时写入文件和stdout

test.h

 #pragma once 

#include <iostream>

using  std::ofstream;

class OutputAndConsole:public ofstream
{
public:
    std::string fileName;        
    OutputAndConsole(const std::string& fileName):ofstream(fileName),fileName(fileName){
    };
    template <typename T>
    OutputAndConsole& operator<<(T var);
};


template <typename T>
OutputAndConsole& OutputAndConsole::operator<<(T var)
{
    std::cout << var;
    ofstream::operator << (var);
    return (*this);
};

TEST.CPP

  OutputAndConsole file("output.txt");
  file << "test" ;

文件中的输出是

01400930

但在控制台中是

test

我调试了它进入

的代码
_Myt& __CLR_OR_THIS_CALL operator<<(const void *_Val)

我做错了什么?

2 个答案:

答案 0 :(得分:8)

我不打算评论为什么你的方法不起作用,主要是因为它无法修补以正常工作。主要问题是你不能使用你的流将它传递给期望std::ostream&并且仍然写入两个流的东西。但是,有一个相对简单但不一定明显的方法来实现您真正想要的东西:您将派生一个新的流缓冲区,即派生自std::streambuf的类,并覆盖其overflow()和{ {1}}功能。以下是简单演示的完整代码:

sync()

显然,tee-stream的创建可以很好地打包,但这看起来完全不重要。重要的是,可以为IOStreams创建自定义目标(或源),并且它不涉及从#include <streambuf> struct teebuf : std::streambuf { std::streambuf* sb1_; std::streambuf* sb2_; teebuf(std::streambuf* sb1, std::streambuf* sb2) : sb1_(sb1), sb2_(sb2) { } int overflow(int c) { typedef std::streambuf::traits_type traits; bool rc(true); if (!traits::eq_int_type(traits::eof(), c)) { traits::eq_int_type(this->sb1_->sputc(c), traits::eof()) && (rc = false); traits::eq_int_type(this->sb2_->sputc(c), traits::eof()) && (rc = false); } return rc? traits::not_eof(c): traits::eof(); } int sync() { bool rc(true); this->sb1_->pubsync() != -1 || (rc = false); this->sb2_->pubsync() != -1 || (rc = false); return rc? 0: -1; } }; #include <fstream> #include <iostream> int main() { std::ofstream fout("tee.txt"); teebuf sbuf(fout.rdbuf(), std::cout.rdbuf()); std::ostream out(&sbuf); out << "hello, world!\n"; } 继承的任何尝试。从std::ostream(或std::ostream)继承的唯一原因是使用自定义流缓冲区初始化流更容易。

答案 1 :(得分:4)

问题

ofstream::operator << (var);

您使用ofstream::operator<<作为限定的函数调用。您要求函数查找找到ofstream的成员函数; &#39;成员的最佳匹配是void*的成员,而打印实际字符串内容的char*的特殊化是一个自由函数(即不是成员功能)。

如果您使用cout执行此操作,也会发现同样的问题:

std::cout.operator<<(var);

解决方案

这可能会这样做:

static_cast<ofstream&>(*this) << var;

因为您仍然使用普通的运算符语法(包含所需的所有重载决策),但使用ofstream作为LHS操作数。

但是,我还没有真正测试过它。

结论

顺便说一句,你的 operator<<也应该是一个免费的功能,以适应这个惯例。

所以:

struct OutputAndConsole : std::ofstream
{
    OutputAndConsole(const std::string& fileName)
       : std::ofstream(fileName)
       , fileName(fileName)
    {};

    const std::string fileName;
};

template <typename T>
OutputAndConsole& operator<<(OutputAndConsole& strm, const T& var)
{
    std::cout << var;
    static_cast<std::ofstream&>(strm) << var;
    return strm;
};

我还冒昧地做了一些小的语法调整。