这与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;
}
std::cout.operator<<("hello2");
有效?从other answers开始,我希望编译器会抱怨,因为operator<<
意味着是一个自由函数,而不是cout
的成员。但是,在我的系统上,它会输出“0x10d54df31”。而且,更奇怪的是,以下行正确执行std::endl
。
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);
std::cout << "hello1" << std::endl;
形式写出第一个operator<<(...)
?如果前两个问题已得到解答,那么这可能已经涵盖了。这是学习练习的重点,所以明确地提出这个问题似乎是明智的。
答案 0 :(得分:3)
操作符可以以不同的方式实现,特别是左侧是您的类型的operator<<
可以实现为自由函数或左侧类型的成员函数。
虽然您必须将ostream& operator<<(ostream&, MyType const&)
实现为自由函数(因为MyType
不是左侧),但库实现可以选择 * 来实现{{1}对于一些基本类型insde operator<<
类型(这实际上是模板的特定实例,我试图忽略细节)。
编辑:使用标准检查后,这是不正确的:
这是您在代码中注意到的内容, < / p>
std::ostream
的重载是const char*
(ostream
)的成员。
将操纵器的重载实现为成员函数(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'都是一个显式的成员函数调用。