【问题标题】:Obscure C++ operator overloading晦涩的 C++ 运算符重载
【发布时间】:2016-03-02 11:19:49
【问题描述】:

我有以下代码:

#include <iostream>

using namespace std;

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

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

不知何故,这是可行的——输出是“你好,你好”。编译器如何解释它?我不明白如何将函数插入流中。

【问题讨论】:

  • 有一个重载的operator&lt;&lt; 接受一个函数并调用它。它到底有多晦涩?
  • 这也是各种std::endlstd::flush 重载的工作方式。

标签: c++ operator-overloading


【解决方案1】:

std::ostream::operator&lt;&lt; 有一个接受函数作为参数的重载;并且该重载的主体是调用给定的函数。

这正是endl 实际上的工作原理。 endl其实是一个类似的函数:

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

【讨论】:

  • 我必须检查一下,但我认为不涉及任何模板(忽略ostreambasic_ostream 的实例化这一事实)。 AFAIR,对于采用 ostreamios_base 的函数,只有两个重载。
  • @UlrichEckhardt 好吧​​,模板参数是CharTTraits。将编辑澄清,因为正如您所指出的那样具有误导性。
【解决方案2】:

std::ostream 有一个 operator&lt;&lt; 重载,它接收一个指向函数的指针,该函数的签名如您编写的 (number 11 in this list):

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

它只是调用给定的函数,将自身作为参数传递。这个重载(以及其他几个类似的)允许您实现 流操纵器,即您在流中输出的内容带有 &lt;&lt; 并从那里更改流的状态。例如,我们的(不正确的)无处不在的std::endl 版本可能被实现为

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

然后可以完全用作“常规”std::endl:

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

(实际的实现是模板化的,而且有点复杂,因为它甚至必须使用宽流,但你明白了)

【讨论】:

    猜你喜欢
    • 2012-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-07
    • 1970-01-01
    相关资源
    最近更新 更多