`cout<< x`和`cout.operator<<(x)`和`operator(std :: cout,x)`?

时间:2014-01-02 17:12:24

标签: c++ operator-overloading cout

这与difference-between-cout-x-and-cout-operator-x问题有关,但仍然有点不同......

#include <iostream>

int main(){
    std::cout << "hello" << std::endl;

    std::cout.operator<<("hello2");
    std::cout.operator<<(std::endl);

    operator<<(std::cout, "hello3");
//    operator<<(std::cout, std::endl);

    return 0;
}

Q1:为什么std::cout.operator<<("hello2");有效?

other answers开始,我希望编译器会抱怨,因为operator<<意味着是一个自由函数,而不是cout的成员。但是,在我的系统上,它会输出“0x10d54df31”。而且,更奇怪的是,以下行正确执行std::endl

Q2:为什么operator<<(std::cout, std::endl);不起作用?

我知道std::endl是一个函数,但是对我来说似乎很奇怪hello3输出有效,而`std :: endl'却没有。相反,编译器会抛出错误:

main.cpp:10:4: error: no matching function for call to 'operator<<'
    operator<<(std::cout, std::endl);

问题3:如何以std::cout << "hello1" << std::endl;形式写出第一个operator<<(...)

如果前两个问题已得到解答,那么这可能已经涵盖了。这是学习练习的重点,所以明确地提出这个问题似乎是明智的。

4 个答案:

答案 0 :(得分:3)

操作符可以以不同的方式实现,特别是左侧是您的类型的operator<<可以实现为自由函数或左侧类型的成员函数。

虽然您必须将ostream& operator<<(ostream&, MyType const&)实现为自由函数(因为MyType不是左侧),但库实现可以选择 * 来实现{{1}对于一些基本类型insde operator<<类型(这实际上是模板的特定实例,我试图忽略细节)。

编辑:使用标准检查后,这是不正确的:

这是您在代码中注意到的内容,std::ostream的重载是const char*ostream)的成员。 < / p>

将操纵器的重载实现为成员函数(Q2),并且存在从basic_ostream<char,char_traits<char>const char*的隐式转换,如果使用显式调用成员运算符的语法,将会选择该转换( Q1)。对于Q3,答案是:

const void*

* 实施实际上不是 free 可供选择,因为标准规定了签名。

答案 1 :(得分:1)

operator<<的某些重载是类成员,有些则不是。

在C ++ 03中,这创建了一些令人困惑的调用场景,因为对非const(not-member的参数)的引用不能绑定到rvalue,但至少在C ++ 11中通过引入rvalue引用参数重载来修复一个这样的问题。

因此,调用compile或不调用更多地取决于C ++标准版本,C ++ 03或C ++ 11。

答案 2 :(得分:1)

std::ostream中定义了许多成员输出运算符。回想起来,这可能是一个错误,但是当IOStreams首次创建时,我认为它实际上是必要的。这些成员运算符包含带有函数指针的重载,这意味着您需要使用成员表示法。使用C字符串的运算符是非成员重载,即,您需要使用非成员函数调用表示法来获取C字符串重载。当您使用char const*调用成员运算符时,char const*将转换为void const*,其中有成员输出运算符。

答案 3 :(得分:1)

您的问题可以分解为非成员函数的成员函数。

拥有13.5.2二元运算符

  

应实施二元运算符   通过具有一个参数的非静态成员函数(9.3)或通过   具有两个参数的非成员函数。因此,对任何二进制文件   operator @,x @ y可以解释为x.operator @(y)或   操作者@(X,Y)。如果两种形式的操作符功能都已存在   声明,13.3.1.2中的规则确定哪个(如果有的话)   使用解释。

省略13.3.1.2的引用,首选成员函数(运算符)。

第'std :: cout&lt;&lt;行“你好”&lt;&lt;的std :: ENDL;”涉及非成员职能。每个'std :: cout.operator'都是一个显式的成员函数调用。

  • Q1是成员运算符&lt;&lt;(const void *)
  • Q2没有会员参加活动
  • Q3不可能