在 c++ 中,如果两个对象都重载运算符<<,会发生什么?a<<b

In c++ what happens, if both objects overload operator<<? a<<b

本文关键字:lt 什么 运算符 如果 c++ 对象 两个 重载      更新时间:2023-10-16

我认为在

cout << "Hello world" 

cout对象有一个运算符重载,因此我们可以将strings传递到cout对象成员函数中。

但是在一些示例代码中,我看到了一个类,其中定义了运算符重载。

class GenericPlayer : public Hand
{
    ..
    friend ostream& operator <<(ostream& os, const GenericPlayer& aGenericPlayer);
    ..
};
...
cout << aGenericPlayer << endl;
...

即使不是,如果coutaGenericPlayer都过载怎么办 operator<<

即使不是,如果 cout 和 aGenericPlayer 都重载运算符怎么办<<?

std::cout是一个std::ostream对象,因此任何std::ostream& operator<<(std::ostream, SomeType)都可以使用 std::cout 。但关键是算子的第二个参数不同,所以重载也不同。第一个"字符串"是这样的

std::ostream& operator<<(std::ostream&, const char*);

第二个

std::ostream& operator <<(std::ostream& os, const GenericPlayer& aGenericPlayer); 

因此,它们是不同的运算符重载,没有歧义。

首先,coutaGenericPlayer都不会重载什么。 它们是对象,重载基于类型(即使你通常不会说 X 型重载<<,而是存在超载<<可能需要键入 X 作为其第二个参数)。

其次,重载解决基于所有参数,不止一个。 大约有二十种不同的东西std::istream的重载<<(这是std::cout的类型),但没有(至少在标准中是这样库)将GenericPlayer作为第二个参数。 所以他们如果第二个操作数不是GenericPlayer则无法使用。同样,你可以有一个 operator<<( int, GenericPlayer const& ) ,除了你拥有的那个;它将被称为如果左侧有类型 int ,而右侧键入 GenericPlayer 。 (我想不出任何这种情况不会是运算符重载滥用,而是语言当然允许。

为了让cout接受GenericPlayer对象,您必须重载operator<<operator<<也称为插入运算符。因此,如果您在上下文中考虑这一点,则将自定义函数的输出插入到cout 。重载运算符返回对原始 ostream 对象的引用,这也意味着您可以组合插入。必须重载插入运算符才能识别左侧的ostream对象和右侧的GenericPlayer对象。另请参阅重载您自己的类的 <<运算符 。就cout而言,cout 是表示标准输出流的class ostream对象。它对应于cstdiostdout。因为cout是类 ostream 的对象,我们可以将字符作为格式化数据写入其中,例如使用插入运算符 (ostream::operator<<) 或使用 write 成员函数作为无格式数据,等等

如果 cout 和 aGenericPlayer 都重载运算符怎么办<<

它们都没有重载它,它是作为常规函数(不是成员)重载的。请注意示例中friend的使用;这允许函数访问类的内部结构,而无需成为成员。因此,可以避免这种情况。