我试图operator<<作为成员函数重载.如果只是这样做它的工作原理:
friend ostream& operator<<(ostream& os, const MyClass& myClass); 在我的头文件和我的MyClass.cc文件中:
ostream& operator<<(ostream& os, const MyClass& myClass)
{
return myClass.print(os);
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试friend取消并使其成为成员函数,那么它抱怨operator<<只能采用一个参数.为什么?
ostream& MyClass::operator<<(ostream& os, const MyClass& myClass)
{
return myClass.print(os);
}
Run Code Online (Sandbox Code Playgroud)
我在这个问题上读到它不能成为一个成员函数,但不确定为什么?
Jer*_*fin 47
当作为成员函数重载时,a << b被解释为a.operator<<(b),因此它只需要一个显式参数(this作为隐藏参数).
因为这要求重载是用作左操作数的类的一部分,所以它对普通的ostreams等没有用.这需要你的重载成为ostream类的一部分,而不是你的类的一部分.由于您不允许修改ostream,因此您无法执行此操作.这只留下全球超载作为替代.
但是,有一个相当广泛使用的模式,你在全局范围内重载运算符,但是调用成员函数:
class whatever {
// make this public, or the global overload a friend.
std::ostream &write(std::ostream &dest) const {
// write self to dest
}
};
std::ostream &operator<<(std::ostream &os, whatever const &w) {
return w.write(os);
}
Run Code Online (Sandbox Code Playgroud)
当/如果您想要多态行为时,这尤其有用.你不能让重载的运算符本身变成多态,但是你调用了virtual它的成员函数,所以无论如何它都是多态的.
编辑:以(我希望)澄清情况,你可以通过几种不同的方式做到这一点.第一个也可能是最明显的是让我们的write成员公开,并让全局运营商调用它.由于它是公开的,我们不需要做任何特殊的事情让操作员使用它:
class myClass {
public:
std::ostream &write(std::ostream &os) const {
// write stuff to stream
return os;
}
};
std::ostream &operator<<(std::ostream &os, myClas const &m) {
// since `write` is public, we can call it without any problem.
return m.write(os);
}
Run Code Online (Sandbox Code Playgroud)
第二种方法是write私有,并声明operator<<朋友给它访问:
class myClass {
// Note this is private:
std::ostream &write(std::ostream &os) const {
// write stuff to stream
return os;
}
// since `write` is private, we declare `operator<<` a friend to give it access:
friend std::ostream &operator<<(std::ostream &, myClass const &);
};
std::ostream &operator<<(std::ostream &os, myClas const &m) {
return m.write(os);
}
Run Code Online (Sandbox Code Playgroud)
第三种可能性几乎与第二种可能性相似:
class myClass {
// Note this is private:
std::ostream &write(std::ostream &os) const {
// write stuff to stream
return os;
}
// since `write` is private, we declare `operator<<` a friend to give it access.
// We also implement it right here inside the class definition though:
friend std::ostream &operator<<(std::ostream &os, myClas const &m) {
return m.write(os);
}
};
Run Code Online (Sandbox Code Playgroud)
第三种情况在C++中使用了一个名为"名称注入"的相当奇怪(并且鲜为人知)的规则.编译器知道friend函数不能成为类的一部分,因此不是定义成员函数,而是将该函数的名称"注入"到周围的作用域(在本例中为全局作用域).即使operator<<在类定义中定义,它根本不是成员函数 - 它是一个全局函数.
Ben*_*ley 10
您可以operator<<作为成员函数重载.但是你不能写一个operator<<在左侧带有ostream 的成员,而你的班级在右侧.
当你创建一个(非静态)成员函数时,有一个隐含的第一个参数,即调用对象. operator<<是二进制的,所以它只需要2个参数.如果你把它作为一个成员函数,你只能给它一个paremeter,因为它已经有一个(调用对象).由于该调用对象始终是第一个参数,因此您不可能将输出运算符编写为(非静态)成员(至少不是该特定函数的标准形式),因为对于这种情况,ostream需要成为第一个论点.