运算符函数作为成员函数和非成员函数

Operator Functions as Member Functions and Nonmember Functions

本文关键字:函数 成员 运算符      更新时间:2023-10-16

我对将运算符重载作为成员和非成员函数的想法感到非常困惑。

当我们将运算符重载为非成员函数时,我们实际上是什么意思,

同样,当我们将运算符重载为成员函数时,我们是什么意思。虽然我知道非成员函数是友元函数。

如果将运算符重载为非成员函数,则需要在参数列表中指定要专门操作的对象。

如果将其重载为成员函数,则"this"指针将为您完成部分工作。

请考虑以下示例:

class Test {
   public:
   friend Test operator+(const Test &lhs, const Test &rhs); // Non-member function
   Test operator+(const Test &rhs); // Member function
};

两者之间的区别在于,非成员函数没有编译器在您谈论类的特定实例时方便地为您传递的this指针。

成员函数 1 推断出 lhs,因此您只需要提供 rhs。

请注意,"朋友"不是必需的,但如果您想访问Test的私人成员,则需要它。

编译器可以根据参数计数消除歧义。如果你想声明friend Test operator+(const Test &rhs),它会抱怨参数不足,因为+是一个二元运算符。成员函数运算符+的lhs是"this"。

示例

class Foo {
public:
  Foo operator+(Foo) // member variant
  // declared inside the function
}; // end of class
Foo operator+(Foo lhs, Foo rhs) // non-member variant
{ // declared outside the class
  // could be just a call to the member variant
  lhs.operator+(rhs);
  // I usually do this when implementing std::stream operators,
  // don't remember why just now.
}

非成员不需要加好友,但如果它需要访问内部状态,则可能需要加好友。如果我没记错的话,非成员在某些编译器上的模板化代码和命名空间方面有一些优势,在非成员变体中交朋友也可以记录类外有一个特定于此类的函数。它告诉我,如果我更改该类,我可能必须查看非成员运算符以确保我没有破坏任何东西。

一个小例子:(我还没有尝试编译这段代码,但我希望它能工作)

class MyClass
{
public:
    MyClass operator+(const MyClass& other) const; //member operator declaration
    friend MyClass operator-(const MyClass& first, const MyClass& second); //non-member operator friend declaration
private:
    int _a;
}
//member operator definition
MyClass MyClass::operator+(const MyClass& other) const
{
    MyClass result;
    result._a = _a + other._a;
    return result;
}
//non-member operator definition
MyClass MyClass::operator-(const MyClass& first, const MyClass& second)
{
    MyClass result;
    result._a = first._a - second._a;
    return result;
}

请注意差异:在成员运算符定义中,我没有在"="之后的第一个_a之前指定任何内容 - 假设 this->_a。

仅当类的实例是运算符的第一个参数时,才能使用成员运算符函数。例如,如果你想做类似 2 + myClassObject 的事情,你需要覆盖非成员运算符MyClass MyClass::operator+(int first, const MyClass& second)(或者使用您希望它具有的任何返回值)。

另请注意,我只需要友谊声明,我的非成员操作员才能访问私人_a字段。

大多数运算符应定义为成员。

class MyClass
{
...
public:
    const MyClass& operator+=(const MyClass&);
};

位 这在行为上与以下内容相同:

class MyClass {...};
const MyClass& operator+=(const MyClass&, const MyClass&);

第一个示例中的隐含this与第二个示例中的第一个参数相似。 如果第二个示例需要访问 MyClass 的内部状态,则需要对其进行friend编辑。

class MyClass
{
    friend const MyClass& operator+=(const MyClass&, const MyClass&);
};
const MyClass& operator+=(const MyClass&, const MyClass&);

典型的例外是operator<< std::ostream

std::ostream& operator<<(std::ostream&, const MyClass&);

这在逻辑上是MyClass的成员,但由于参数的顺序,它必须是两个类的非成员或std::ostream的成员。 由于无法将成员添加到 std::ostream ,因此必须将其定义为非成员。