C++运算符重载难以理解

26

我有以下代码:

#include <iostream>

using namespace std;

ostream& f(ostream& os) {
    return os << "hi";
}

int main() {
    cout << "hello " << f << endl;
    return 0;
}

以某种方式运作 - 输出是“hello hi”。这是如何被编译器解释的?我不理解一个函数如何被插入到一个流中。


5
有一个过载的 operator<< 可以接受一个函数并调用它。它究竟有多难理解? - n. m.
6
各种 std::endlstd::flush 重载的工作方式也是如此。 - Ulrich Eckhardt
2个回答

30

std::ostream 有一个 operator<< 重载,它接收一个函数指针,该函数的签名与您编写的函数相似(参见此列表中的第11项):

basic_ostream& operator<<(
    std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&) );

这个重载的作用是调用给定的函数并将自身作为参数传递。这个重载(以及其他几个类似的重载)旨在让您实现流操作符(stream manipulators),即通过 << 输出到流中并从那里更改流状态的内容。例如,我们版本的(不正确的)普遍使用的 std::endl 可以这样实现:

std::ostream &myendl(std::ostream &s) {
    s<<'\n';
    s.flush();
    return s;
}

这样就可以完全像“常规”的std :: endl一样使用:

std::cout<<"Hello, World!"<<myendl;

(实际实现是模板化的,稍微复杂一些,因为它必须能够使用宽流来工作,但你已经明白了)


8

std::ostream::operator<<有一个重载,它接受一个函数作为参数;该重载的主体是调用给定的函数。

实际上,这正是 endl 的工作方式。事实上,endl 实际上类似于以下函数:

ostream &endl(ostream &os)
{
    os << '\n'; 
    os.flush(); 
    return os;
}

我需要检查一下,但我认为没有任何模板涉及其中(忽略 ostreambasic_ostream 的实例化这一事实)。据我所知,只有两个重载函数使用 ostreamios_base - Ulrich Eckhardt
@UlrichEckhardt 好的,模板参数是 CharTTraits。会进行编辑以澄清,因为你指出这一点有误导性。 - M.M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接