C++ 不能重载运算符<<作为成员函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9814345/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 13:18:48  来源:igfitidea点击:

Can't Overload operator<< as member function

c++operator-overloading

提问by Jerry Coffin

I am trying to overload operator<<as a member function. It works if simply do this:

我正在尝试operator<<作为成员函数重载。如果只是这样做,它会起作用:

friend ostream& operator<<(ostream& os, const MyClass& myClass);in my header file and in my MyClass.cc file:

friend ostream& operator<<(ostream& os, const MyClass& myClass);在我的头文件和 MyClass.cc 文件中:

ostream& operator<<(ostream& os, const MyClass& myClass)
{
   return myClass.print(os);
}

However, if I try to take the friendoff and make it a member function, then it complains that operator<<can only take one argument. Why?

但是,如果我尝试friend取消并使其成为成员函数,那么它会抱怨operator<<只能采用一个参数。为什么?

ostream& MyClass::operator<<(ostream& os, const MyClass& myClass)
{
   return myClass.print(os);
}

I read at this questionthat it can't be a member function, but not sure why?

我在这个问题上读到它不能是成员函数,但不知道为什么?

回答by Jerry Coffin

When overloaded as a member function, a << bis interpreted as a.operator<<(b), so it only takes one explicit parameter (with thisas a hidden parameter).

当作为成员函数重载时,a << b被解释为a.operator<<(b),因此它只需要一个显式参数(this作为隐藏参数)。

Since this requires that the overload be part of the class used as the left-hand operand, it's not useful with normal ostreams and such. It would require that your overload be part of the ostreamclass, not part of your class. Since you're not allowed to modify ostream, you can't do that. That leaves only the global overload as an alternative.

由于这要求重载是用作左手操作数的类的一部分,因此它对普通ostreams 等没有用。这将要求您的重载是ostream班级的一部分,而不是您班级的一部分。由于您不允许修改ostream,因此您不能这样做。那只剩下全局过载作为替代方案。

There is, however, a fairly widely-used pattern where you overload the operator globally, but have that call a member function:

但是,有一种相当广泛使用的模式,您可以全局重载运算符,但要调用成员函数:

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);
}

This is particularly useful when/if you want polymorphic behavior. You can't make the overloaded operator polymorphic itself, but you make the member function it calls virtual, so it acts polymorphic anyway.

这在/如果您想要多态行为时特别有用。你不能让重载的操作符本身多态,但你可以让它调用的成员函数成为virtual多态的,所以无论如何它都是多态的。

Edit: to (I hope) clarify the situation, you can do this a few different ways. The first and probably most obvious is to just make our writemember public, and have the global operator call it. Since it is public, we don't have to do anything special to let the operator use it:

编辑:为了(我希望)澄清情况,您可以通过几种不同的方式来做到这一点。第一个也可能是最明显的就是让我们的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);
}

A second alternative is to make writeprivate, and declare operator<<a friend to give it access:

第二种选择是设为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);
}

There's a third possibility that's almost like the second:

还有第三种可能性,几乎和第二种一样:

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);
    }
};

This third case uses a rather strange (and little known) rule in C++ called "name injection". The compiler knows that a friendfunction can't be part of the class, so instead of defining a member function, this "injects" the name of that function into the surrounding scope (the global scope, in this case). Even though operator<<is defined inside the class definition, it's nota member function at all -- it's a global function.

这第三种情况在 C++ 中使用了一个相当奇怪(且鲜为人知)的规则,称为“名称注入”。编译器知道friend函数不能是类的一部分,因此不是定义成员函数,而是将该函数的名称“注入”到周围的作用域(在本例中为全局作用域)。即使operator<<在类定义中定义,它也根本不是成员函数——它是一个全局函数。

回答by Benjamin Lindley

You can overload operator<<as a member function. But you can't write a member operator<<that takes an ostream on the left side, and your class on the right side.

您可以重载operator<<作为成员函数。但是你不能写一个成员operator<<在左侧接受 ostream,而你的班级在右侧。

When you make something a (non-static) member function, there is an implied first argument, the calling object. operator<<is binary, so it only takes 2 arguments. If you make it a member function, you can only give it one paremeter, because it already has one(the calling object). And since that calling object is always the first argument, you can't possibly write the output operator as a (non-static) member (at least, not in the standard form for that particular function), because for that case, the ostream needs to be the first argument.

当您将某些东西设为(非静态)成员函数时,有一个隐含的第一个参数,即调用对象。 operator<<是二进制的,所以它只需要 2 个参数。如果你让它成为一个成员函数,你只能给它一个参数,因为它已经有了一个(调用对象)。并且由于该调用对象始终是第一个参数,因此您不可能将输出运算符编写为(非静态)成员(至少,不是该特定函数的标准形式),因为在这种情况下,ostream必须是第一个参数。

回答by gbjbaanb

Think of it like this: when you want to stream to ostream, you're calling the << operator on the stream object. And you're not allowed to directly modify the ostream's 'private' method. So you have to create an overloaded version, and make it a friend.

可以这样想:当您想流式传输到 ostream 时,您正在调用流对象上的<< 运算符。并且您不能直接修改 ostream 的“私有”方法。所以你必须创建一个重载版本,并让它成为朋友。

When you create your own operator<< method in your class, you're creating a << method that will operate on your class, not an ostream object. I guess you can hold an ostream internally to your class and stream to it, but you'll have difficulty writing chained statements like this: a << b << c.

当您在类中创建自己的 operator<< 方法时,您正在创建一个 << 方法,该方法将对您的类进行操作,而不是 ostream 对象。我想你可以在内部举行一个ostream到您的类和流它,但你有困难的写作链语句是这样的:a << b << c