2016-07-13 17 views
0

我想用一个自定义的流操作符实现一个类,并从它继承,以便有一个基类和派生的不同的流。然后,我使用存储的ostream<<运营商超载。自定义ostream只打印`<<`链的最后一个字符串

这是代码的工作示例:

#include <string> 
#include <memory> 
#include <ostream> 
#include <iostream># 
#include <fstream> 

class Sink { 
public: 
    Sink() { 
     m_stream = std::unique_ptr<std::ostream>(new std::ostream(std::cout.rdbuf())); 
    }; 

    template<typename T> 
    std::ostream& operator<<(const T& obj) { 
     return *m_stream; 
    } 

protected: 

    std::unique_ptr<std::ostream> m_stream; 
}; 

class FileSink : public Sink { 
public: 

    FileSink() { 
     m_stream = std::unique_ptr<std::ostream>(new std::ofstream("file.txt")); 
    } 
}; 

int main() { 
    Sink s; 
    FileSink fs; 
    s << "First console string " << "second console string"; 
    fs << "First file string " << "second file string"; 
    return 0; 
} 

随着Sink class我写在控制台上,与FileSink上的文件。

问题是,使用此代码,我只打印每条指令的最后一个字符串。

在控制台中我看到以下的输出:

second console string 

,而在该文件中,我可以看到这样的输出:

second file string 

我做错了什么,我怎么能打印预期输出?

+0

一个滥用std :: unique_ptr的好例子(一个简单的指针就在这里) –

+0

@DieterLücking什么是原始指针优势? – ilotXXI

+0

@DieterLücking如果Sink类拥有指针,为什么不使用unique_ptr?否则,你需要有一个自定义的副本或移动构造函数,以及一个析构函数 –

回答

3

operator<<什么都不做,返回std::ostream&。然后,您将std::ostream::operator<<应用于该std::ostream&。期待的事情!

标准的方式做你想要什么:

template<typename T> 
Sink & Sink::operator<<(const T& obj) { 
    *m_stream << obj; 
    return *this; 
} 
template<typename T> 
FileSink & FileSink::operator<<(const T& obj) { 
    *m_stream << obj; 
    return *this; 
} 

为了避免重复代码,你可以使用继承。我想,它可能会复制std::stream继承方案。 :)

2
template<typename T> 
std::ostream& operator<<(const T& obj) { 
    *m_stream << obj; // you missed this 
    return *m_stream; 
} 

此外,您还可以定义操作< <为非成员函数。

template <typename T> 
Sink& operator<<(Sink &sink, const T &obj) { 
    *(sink.m_stream) << obj; 
    return sink; 
} 

,并使其散热器的朋友:

class Sink { 
    template <typename T> 
    friend Sink& operator<<(Sink &sink, const T &obj); 
    // other code. 
}