相信能看到这里的人,应该都用过std::endl吧,没见过?
就是hello world后面那个。到底这个endl是个什么东西呢? 答案是:函数指针。
这是它的声明:
1
template<class _Elem,
2
class _Traits> inline
3
basic_ostream<_Elem, _Traits>&
4
endl(basic_ostream<_Elem, _Traits>& _Ostr)
当然endl只输入输出流,输入流没有endl。所以输出流需要一个类似

basic_
ostream& operator<<(basic_ostream&(*)(basic_ostream &))
函数来接受这个endl。
如果想写个类,比如一个log类,希望可以像标准流一样的输出,需要做什么呢?
1
class Log
2

{
3
public:
4
teamplate <typename T>
5
Log& operator<<(const T& t)
6
{
7
// write t to log file.
8
}
9
};
有了这个定义后,Log类就可以像标准输出流一样用了,比如:
1
Log log;
2
log<<123<<"ABC"<<132.32<<endl;
什么,编译出错,而且不止一个。上面说过,是endl引起的问题。
std::endl的定义本身就是个模板函数,用一个模板函数(编译时连参数都确定不下来)去推导模板参数,是极不现实的。
因为:endl有两个模板参数,_Elem 和 _Traits,其实_Traints 本身就是个以_Elem为参数的类模板,标准库里面有两个endl版本,
一个是 _Elem = char, 另一个是 _Elem = wchar.
所以编译器不能推导出Log类的operator<<的模板参数T,于是就错误了。
解决方案,之前也说过,需要一个接受函数指针的operator<<的重载版本。
1
Log& operator<<(basic_ostream<char, char_traits<char>>& (*_Pfn)(basic_ostream<char, char_traits<char>>&))
2
{
3
// write endl to log using _Pfn
4
}
有这个定义,就可以顺利使用 <<std::endl 了。
当然可以为wchar定义一个operator<<来使用宽字符,这都是函数重载惹的祸呀。因为char和wchar算是endl函数两个重载版本。
问题解决了,说一下,同样的函数还有:
ends,输入一个字符串结束符。
flush,刷新流。
当然这俩个不常用。
posted on 2009-04-18 19:42
尹东斐 阅读(4362)
评论(4) 编辑 收藏 引用