2014-02-20 46 views
2

使用流操作符的C++代码失败。我无法弄清楚,为什么第二次打印“DEF”不工作::为什么第二条语句是打印十六进制值

#include <iostream> 
#include <sstream> 
struct logger :public std::ostringstream {}; 

struct logger_flush {}; 

logger_flush endl; 

std::ostream& operator << (std::ostream& os, const logger_flush& lf) { 
    logger& oss = dynamic_cast<logger&>(os); 
    std::cout << oss.str() << std::endl; 
} 

int main() 
{ 
    logger() << 100 << "ABC?" << endl; 
    logger() << "DEF" << endl; 
} 

输出是:

100ABC?

0x40168d

+0

似乎与gcc一起工作。 http://ideone.com/XylUCx – mkaes

+1

甚至不为我编译。您在运营商<<功能中没有返回任何内容。 – user1052842

+1

@ user1052842 - 我认为这应该是一个警告。 –

回答

3

logger()是一个右值,这就是为什么叫::operator<<(logger(), "DEF")你想不起作用:的operator<<是重载接受左值的参考参数,右值不能绑定到非const左值引用。

但是,右值类允许调用方法,因此过载logger().operator<<((void*)"DEF")可用,并且它成为logger() << "DEF"的最佳匹配。

它适用于logger() << 100 << "ABC?" << endl;,因为logger() << 100返回一个左值引用,并且该左值引用是::operator<<的有效参数。

3

这应该在C++ 11中工作,因为ostream& operator<<(ostream&& os, const T& value)重载,它允许您使用流作为右值。

在C++中03,因为void*过载是一个构件(它可以在右值被称为),而char const*超载是非构件将打印的地址,和第一个参数是一个ostream&,它不能绑定到rvalues。

+0

在我的电脑上无法使用3.3版本。在重载的'operator <<'中缺少返回语句是未定义的行为,并且这个UB最终导致信号EXC_BAD_INSTRUCTION被引发。幸运的是,对这个UB的响应没有调用'erase_hard_drive()'函数。 –

+0

@DavidHammen禁止未定义的行为,它将工作。我的答案主要是关于为什么'void *'重载选择在'char const *'之上。 – Simple

+0

修复了UB问题之后,我使用了clang ++(clang版本3.3),为-std = C++ 03和-std = C++ 11获得了相同的输出。 –

相关问题