如果您将
operator<<
定义为成员函数,则其分解语法与使用非成员
operator<<
不同。非成员
operator<<
是二元运算符,而成员
operator<<
是一元运算符。
struct MyObj;
std::ostream& operator<<(std::ostream& os, const MyObj& myObj);
struct MyObj
{
MyObj& operator<<(std::ostream& os) { os << *this; return *this; }
int value = 8;
};
std::ostream& operator<<(std::ostream& os, const MyObj& myObj)
{
return os << myObj.value;
}
那么……你真的怎样称呼它们呢?某些方面运算符很奇怪,我向你发起挑战,在你脑海中编写operator<<(...)
语法以使事情变得合理。
MyObj mo;
mo << std::cout;
mo.operator<<(std::cout);
或者你可以尝试调用非成员二元运算符:
MyObj mo;
std::cout << mo;
operator<<(std::cout, mo);
当你将这些运算符变成成员函数时,你没有义务使它们的行为具有直观性,如果你想要的话,你可以定义operator<<(int)
来左移一些成员变量,但要明白,无论你写了多少注释,人们可能会有点措手不及。
最后,可能会出现运算符调用的两个分解都有效的情况,这时你可能会遇到麻烦,我们将推迟讨论这个问题。
最后,请注意,编写一个看起来像二元运算符的一元成员运算符可能会很奇怪(因为你可以使成员运算符虚拟......也尝试不要陷入这条路......)
struct MyObj
{
std::ostream& operator<<(std::ostream& os) { os << *this; return os; }
int value = 8;
};
这种语法现在会让很多程序员感到烦恼....
MyObj mo;
mo << std::cout << "Words words words";
mo.operator<<(std::cout) << "Words words words";
operator<<(mo.operator<<(std::cout), "Words words words");
注意这里的
cout
是链中的第二个参数...很奇怪,对吧?
operator<<
实现为类A中的友元函数。因此,在这种情况下,就像@asaelr提到的那样,当定义友元函数时,您不使用类的名称来限定友元函数的名称。 - Rishit Chaudharyfriend
函数是一个自由函数,属于封闭命名空间的成员,而不是类的非静态成员函数。所以a)是错误的。我也不明白b)试图表达什么意思。问题中唯一错误的地方是定义中的logic::
部分。 - user17732522