【发布时间】:2015-02-04 19:55:16
【问题描述】:
我想要一个在 cout 上重定向的每行开头都有一个前缀的 ostream; 我试试这个:
#include <iostream>
#include <thread>
class parallel_cout : public std::ostream
{
public:
parallel_cout(std::ostream& o):out(o){}
template <typename T>
std::ostream& operator<< (const T& val)
{
out << "prefix " << val;
return *this;
}
std::ostream& out;
};
int main()
{
parallel_cout pc(std::cout);
pc<<"a\nb"<<"c\n";
}
但我有输出
prefix a
b
没有c。为什么会这样?
【问题讨论】:
-
一般来说,从 std::stream 派生不是一个好主意 - 它没有虚拟析构函数,您的代码显示输出操作如何在派生类上不起作用,因为您正在返回对基类的引用。我会尝试扩展为一个完整的答案,除非有人打败我:)
-
你的模板应该返回
parallel_cout&,而不是通用的ostream&。 -
@martin_pr
std::ostream有一个虚拟构造函数(继承自std::ios_base)。此外,std::fstream和std::stringstream也是派生类,但它们工作正常。您想要从 IOStreams 基类派生的主要原因是包装自定义std::streambuf,这是具体流类所做的。 -
@499602D2 很公平,我的错。
-
@volperossa:你真的应该不使用模板的方法!像
std::endl这样的操纵器的使用也不会是您问题的终结:当您将流传递给采用std::ostream&的函数时,它也不会做正确的事情。使用自定义流缓冲区将对操纵器以及在将流流传递给采用std::ostream&的函数时做正确的事情。也就是说:操纵器的问题在于它们是函数模板,std::ostream有一个合适的输出运算符,用于推断模板参数。