我想知道std::cout
如何能够使用<<
。
我的主要困惑在于std::cout
是否是某事物的一个例子。基本上,<<
是如何定义的?如果我为自定义类执行此操作,我需要某种类型的实例...
我可以看到将它实现为带有无效指针或其他东西的黑客攻击,但我希望看到它实际完成的方式。
这里有人知道吗? 感谢
答案 0 :(得分:46)
std::cout
是std::ostream
的一个实例。 std::cout << "something"
调用operator<<
重载之一,就像std::ostream
的任何实例一样。
它是“特殊的”,因为它引用了控制台,但它的行为与ofstream
或ostringstream
完全相同。
编辑:链接就像它适用于任何其他运营商一样。考虑:
class MyType
{
friend std::ostream& operator<<(std::ostream& target, const MyType& source);
int val;
public:
MyType()
: val(0)
{ }
MyType& Add(int toAdd)
{
val += toAdd;
return *this;
}
};
MyType& operator+(MyType& target, int toAdd)
{
return target.Add(toAdd);
}
std::ostream& operator<<(std::ostream& target, const MyType& source)
{
target << source.val;
return target; //Make chaining work
}
int main()
{
MyType value1;
value1 + 2 + 3 + 4;
std::cout << value1 << " and done!" << std::endl;
}
在这种情况下,MyType
上+ s的链接工作的原因与<<
在std::ostream
之上工作的原因相同。 +
和<<
都是左关联的,这意味着它们是从左到右进行评估的。对于重载运算符,运算符将替换为等效函数调用。
EDIT2 :更详细一点:
假设您是编译器并且正在解析
std::cout << value1 << " and done!" << std::endl;
首先,<<
是左关联的,所以你从左边开始。您评估第一个<<
并将其转换为函数调用:
operator<<(std::cout, value1) << " and done!" << std::endl;
然后您看到您再次拥有std::ostream
(调用operator<<
的结果)和char *
,您再次进入函数调用:< / p>
operator<<(operator<<(std::cout, value1)," and done!") << std::endl;
等等,直到你处理完整个陈述。