c++ - 为什么仅仅调用一个对象会做某事?
问题描述
我刚刚完成了linkedin学习的c++基本培训,现在我有一个简单的问题。为什么 cout 会输出,我们只是在调用对象,但为什么仅仅调用对象会有所作为。我的猜测是 '<<' 重载运算符是做某事的运算符,但接下来是 '<< std::endl;' , endl 我们再次只是调用对象,但它创建了一个新行。谁能解释为什么会这样?
解决方案
std::cout 是一个ostream
可通过标准库获得的对象。当你调用
std::cout << 42;
它查找ostream& operator<<(ostream&, int)
或在本例中为对象 ( ) 的成员函数的重载ostream& operator<<(int)
,并将 cout 传递给此运算符(或 as this
)和整数。运算符的主体将整数值写入流并返回流对象,允许链接:
std::cout << 42 << std::endl;
实际上是将 42 插入到 ostream 中,返回 cout,然后“插入”endl
到流中,这会找到另一个重载运算符,该运算符写入换行符,然后刷新流。std::ostream (其中 std::cout 是其中之一)有一些内置的 operator<< 重载作为成员,但是对于普通的用户定义类型,您通常编写非成员 operator<< 重载或成员朋友过载。
这不是魔术,但有点微妙,因为在这种情况下,中缀运算符被转换为“正常”函数调用。因此对于具有重载 operator<< 的某些x
类型的对象:X
class X { /*impl stuff*/ };
std::ostream& operator<<(std::ostream&, X const&);
然后
std::cout << x << std::endl;
可以被认为是这样做的一种很好的方式:
(std::operator<<(std::cout, x)).operator<<(std::endl);
首先调用内部 operator<< ,重载 for x
,其返回值(即 cout )的成员函数 operator<< 以 std::endl 作为参数调用。出于好奇,std::endl 实际上是一个函数,我们将函数指针传递给operator<< 的重载,它是 std::cout 的成员:
// member overload of operator<< which is used with std::endl
basic_ostream& operator<<(
std::basic_ostream<CharT,Traits>& (*func(
std::basic_ostream<CharT,Traits>&)
);
这是流操纵器的正常工作方式。这看起来有点复杂,但它允许一个漂亮的 << 标记序列,而不必在表达式链中写出括号或“点”。它实际上会将一个函数插入到流中,operator<< 接收函数指针,调用该函数将流对象传递给它(即调用 std::endl(this)),然后 endl 像普通函数一样运行它在流中插入一个换行符并在其上调用flush(),然后返回流,它可以被下一个对operator<<的链式调用使用。)这是一个很少有人真正需要知道的细节级别(或关心)除非您正在编写操纵器,但恕我直言,这很有趣。
推荐阅读
- java - 编辑maven的设置文件
- ios - iOS - 如何 - startMonitoringSignificantLocationChanges 工作
- java - 带有 EditTexts 的 RecyclerView - 添加新行
- wpf - MemoryStream 抛出 System.ObjectDisposedException
- android - 当 BroadcastReceiver 向 IntentService 发送 Intent 时单元测试失败
- java - 查询外键时是否可以使用二级缓存
- java - 为单个开关提供三个结果的案例
- php - PHP,SQLite 在 Windows 上使用学说
- perl - 向 https 站点请求代理时出现 Perl 错误。任何事件状态 596
- mysql - 对大量数据使用像 JSON_EXTRACT 这样的 SQL 函数好不好