我对友元函数的理解

My understanding of friend functions

有时,非成员函数可能需要访问它作为参数接收的私有成员。 friend 函数是一个非成员函数,它提供对它的好友 classes 的私有访问。

Class X{
    int number;
public:
    X& operator+=(const X& rhs);//a += b is a.operator(b)
    friend int& operator+=(int& addthis, const X& rhs);//add this += b is I don't know what lol
}
X& operator+=(const X& rhs){
    this->number = this->number + rhs.number;        
}
int& operator+=(int& addthis, const X& rhs){
     addthis = addthis + rhs.number;
     return *this;
}

我读到的是,如果我想对对象 object += int 执行 +=,只需重载 += 运算符,但如果 int 来了怎么办对象之前。说 int += object?比我不得不将它写成 friend 函数,这就是我有点迷路的地方。为什么我不能直接把 int& operator+=(int& addthis, const X& hrs); 写成成员函数呢?我假设 friend 函数可以与其他 classes 一起使用,因为它是一个非成员函数,所以它没有分配给任何特定的 class?

抱歉,我只是不明白为什么我会使用 friend 函数而不是将其设为成员函数。真的很感激任何反馈,谢谢。

您可以通过 class X:

中的用户定义转换为 int 和其他整数类型启用 operator+=
struct X{
    int number;
    operator int() const
    {
        return number;
    }
    //...
}

当然,这不会为您提供与 friend 方法完全相同的行为,因为其他函数也可以使用转换。不过,我想这就是您要查找的内容,否则您还需要定义 operator-=operator*= 等等。

据我所知,你不能有 operator*operator+operator+= 或任何 operator@,其中 @ 是一些数学在 class.

的定义中 return 不是 class 实例的运算符

在现实世界中,将一个整数与一个整数相加得到 一个苹果 是很奇怪的。这同样适用于 C++ 中的 classes。好吧,成员函数是 class 的 属性,一个表示可以对此 class 的对象执行的任何操作的函数。运营商是特殊的。它们表示无法简化的操作(您将使用什么来 使用 + 符号而不是运算符重载来编写加法运算符 ?它们代表非常基本的操作,因此应该 return 它们所属的 class 的一个实例。

运算符int += X之所以必须是自由函数,是因为编译器只在lhs类型中搜索适用的成员运算符,而不会在rhs类型中搜索。由于 int 不是可以扩展的类型,因此不能将此运算符定义为成员函数。

你差不多完成了,只是有一些错误:

class X;

int operator+=(int addthis, const X& rhs);

class X{
    int number;
public:
    X& operator+=(const X& rhs);//a += b is a.operator(b)
    friend int operator+=(int addthis, const X& rhs);//add this += b is I don't know what lol
};

X& X::operator+=(const X& rhs){
    this->number = this->number + rhs.number; 
    return *this;
}
int operator+=(int addthis, const X& rhs){
     addthis = addthis + rhs.number;
     return addthis;
}
  • 添加了一些前向声明
  • int 按值而不是按引用传递
  • class 声明后缺少分号
  • class 而不是 Class
  • return 更正

注意X += int是成员函数,而int += X是自由函数,声明了classX的friend

int += X 使用自由函数是唯一允许像往常一样使用运算符的解决方案,例如:

X x;
int i = 2;
i += x;

假设您将运算符重载实现为成员函数并执行类似 x += y 的操作,其中 xy 都是具有运算符 [=] 的 class 的对象13=] 过载。

编译器将 x += y 解析为 x.operator+=(y) 这很好,因为两个操作数 xy 都属于相同的 class,它具有运算符 += 过载。

现在考虑像 2 += y 这样的表达式(这可能很疯狂,但我正在尝试解释为什么使用友元函数重载运算符有时可能比使用成员函数重载运算符更有益)

因为表达式 2 += y 将被编译器解析为 2.operator+=(y),将引发错误。也许 2 可以使用构造函数转换为 class 的对象; (可以使用单参数构造函数进行转换)但这不是重点。

使用友元函数重载运算符将上述表达式 2 += y 调用为 operator+=(2, y),效果很好。

friend 修饰符只是为了公开 private 数据。通常,如果 friend 函数仅依赖于 class 的私有数据,则您不会将其定义为非成员函数,它可以定义为

的成员函数。

更好的例子是 ostream::operator<<istream::operator>>