可能重复:
Operator overloading
我正在期待已久的C ++回归,并且有一些基本符号在其他语言中似乎并不那么突出。
如果你看一下这行代码
cout << "firstvalue is " << firstvalue << endl;
我意识到这是什么。它将“firstvalue is x”写入控制台。 x是firstvalue的值。但是,我对“&lt;&lt;”不知道任何事情。或“&gt;&gt;”双角括号。我无法研究它们或它们做什么,因为我不知道它们的正式名称。
我的问题是,上述声明中实际发生了什么(一步一步)?什么是这些“&lt;&lt;”对于?我想我明白cout是用于写入控制台的标准库函数。但是我习惯于使用objective-c或点符号。我没有看到这个“cout”函数是什么对象。
我可以更轻松地理解printf,因为至少它为参数提供了大括号。例如printf(“你的字符串在这里”)。
答案 0 :(得分:16)
C ++允许运算符重载。这意味着用户定义的类型可以在内置运算符上定义自己的行为。在这种情况下,运算符称为:left shift
或right shift
运算符。这些运算符传统上一直用于位移,但标准库将它们重新用于表示流操作。
您可以在C and C++ here中找到可用运营商的列表。
在您的情况下,您将字符串文字和某种类型的值流式传输到std::cout,这是std::basic_ostream类型的对象。
循序渐进
在应用优先规则后,您的代码如下所示:
((cout << "foobar") << x) << endl;
编译器基本上将object << object
表达式转换为函数调用。
operator<<(operator<<(operator<<(cout, "foobar"), x), endl);
然后它会找出要调用的过载。 (这真的是
棘手。现在,仅仅相信它就足够了
查找具有匹配参数的operator<<
重载。)
答案 1 :(得分:4)
<<
运算符是C ++中的“算术左移”。例如:
3 << 2
评估为12.原因是3的二进制表示是
00000011
将它向左移动两次
00001100
,结果的数值为12。
输出有什么用呢?实际上没什么。但是在C ++中,由于重载,您可以重新定义运算符的含义。 C ++标准库决定将左移运算符的含义重新定义为“发送到流”。
那么会发生什么呢
std::cout << "whatever"
返回值std::cout
,但作为副作用,它输出字符串“whatever”。
选择运算符是因为它具有合理的优先级(重载不能更改优先级,并且您无法定义新运算符)并且形状使其看起来有点“自然”。但请注意,左移运算符只是一个普通运算符,例如,无法保证评估顺序:
std::cout << f() << g() << h();
此处的输出将是调用f()
的结果,后跟调用g()
的结果,然后是调用h()
的结果...但函数本身可能是以不同的顺序调用,例如可以先调用h()
!
所以从某种意义上说,运算符的“序列外观”是误导性的,因为它是关于输出的顺序,而不是关于评估的顺序。
答案 2 :(得分:2)
它们被称为流插入(或提取,在istream >>
的情况下),实际上是左移和右移运算符的语义重载。
所以,这个:
int x = 1 << 1;
有点转变,但是这个:
std::cout << x;
是一个流插入。您可以明确地将其写为:
operator <<(std::cout, x);
得到完全相同的结果。流插入操作符的常规格式(它们可以为用户定义的类型重载,因此编写自己的类型并不罕见)
std::ostream& operator <<(std::ostream&, T value);
输出流(通过引用)返回,因此您可以链接调用:您的示例转换为:
operator<< (
operator<< (
operator<<(std::cout, "firstvalue"),
firstvalue
),
std::endl
);
哦,而且...... std::cout
(和std::cerr
等)不是函数:它们是全局对象。这里的函数是重载的<<
运算符。将它们视为FILE *stdout, *stderr
等价物。
与printf
等相比,C ++ iostream有一些优势。人:
"%f"
打印整数并获取垃圾,因为重载决策会在编译时自动选择std::ostream& operator<<(std::ostream&, double)
函数cout
/ cerr
)和文件(std::ofstream
)和字符串(std::ostringstream
)。无需单独处理printf
/ fprintf
/ snprintf
。还有一些缺点:
printf
已经支持的原始类型,格式字符串更加简洁,更具表现力答案 3 :(得分:2)
<<
是运算符,+
是运算符,*
是运算符。以下是等效表达式的方式:
5 + 3 + 2
((5 + 3) + 2)
下两个也是如此:
std::cout << "Hello" << std::endl
((std::cout << "Hello") << std::endl)
它只是一个有两个操作数的运算符。对于基本类型,<<
和>>
运算符实际上称为左移位运算符和右移位运算符。它们执行按位移位。例如,5 << 1
会将5(0101
)中的所有位移到一个位置,得到10(1010
)。
但是,与大多数其他运算符一样,您可以重置shift运算符。在输入/输出库的情况下,移位运算符被重载以提供输入和输出到流的自然语法。这是因为<<
和>>
令牌的方向性看起来像某种方式正在流动。使用这些I / O类,这些运算符重载会返回对您正在执行运算符的流的引用,以便它们可以链接在一起。
您可以通过提供带有一个参数的成员函数operator<<
或operator>>
来重载特定类的移位运算符(操作符右侧的操作数)。或者,您可以提供具有两个参数的相同名称的非成员函数,分别是运算符的两个操作数。
答案 4 :(得分:1)
以下是语法糖:
// Let the function 'print' be a renaming of 'operator<<'
// with T being the type of the object you want to print.
std::ostream& print(std::ostream&, const T&);
// 1) Print "first value is" and then return the stream you
// to which to just printed (ie. cout). 2) Use the returned
// stream to chain function calls and print 'firstValue'.
print(print(std::cout, "first value is"), firstValue);