不能重载运算符<<作为成员函数 [英] Can't Overload operator<< as member function

查看:157
本文介绍了不能重载运算符<<作为成员函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将operator<<作为成员函数重载.只需执行以下操作即可:

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

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

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

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

但是,如果我尝试取消friend并将其设为成员函数,则它会抱怨operator<<只能接受一个参数.为什么?

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

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

我在该问题中读到它不能成为成员函数,但不确定为什么?

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

推荐答案

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

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

因为这需要重载作为用作左操作数的类的一部分,所以对于普通的ostream此类无效.这将要求您的重载是ostream类的一部分,而不是您的类的一部分.由于不允许您修改ostream,因此不能这样做.剩下的只是全局过载.

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 ostream class, 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.

但是,有一种使用广泛的模式,您可以在全局范围内重载运算符,但是会调用成员函数:

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

当/如果您想要多态行为,这特别有用.您不能使重载的运算符本身具有多态性,但要使它调用virtual的成员函数,因此无论如何它都具有多态性.

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.

(希望)弄清情况,您可以通过几种不同的方法来做到这一点.第一个,也许是最显而易见的,就是公开我们的write成员,并让全球运营商来称呼它.由于它是公共的,因此我们不需要做任何特殊的事情就可以让操作员使用它:

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 write member 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:

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

第二种选择是将write设为私有,并声明operator<<为朋友以授予其访问权限:

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

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

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

This third case uses a rather strange (and little known) rule in C++ called "name injection". The compiler knows that a friend function 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 not a member function at all -- it's a global function.

这篇关于不能重载运算符&lt;&lt;作为成员函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆