以成员函数还是全局函数(友元函数)的形式重载运算符?

例子

//全局
friend Complex operator+(const Complex &c1, const Complex &c2);
//成员,记得加=号,“+=”
Complex & operator+=(const Complex &c);

对于全局函数形式的重载“+”

  1. 先来看b = a + 1.1;,实际上会被转换为b = operator+(a, 1.1);这样的形式进行调用;因为存在转换构造函数,并且第一个参数为 double,那么编译器就会将 1.1 转换为一个匿名 complex 对象complex(1.1),进而在运算符重载函数内部将它们两个的实部,虚部相加,然后返回一个匿名 complex 对象并赋值给 b;

  2. 而对于b = 2.2 + a;,也是一样的道理,被转换为b = operator+(2.2, a);这样的形式,然后又调用转换构造函数将 2.2 转换为一个匿名 complex 对象complex(2.2),后面的步骤同上;

对于成员函数形式的重载 “+”

  1. 对于b = a + 1.1;,被转换为b = a.operator+(1.1);,1.1 也是被转换为complex(1.1);
  2. 对于b = 2.2 + a;,被转换为b = (2.2).operator+(a);,这很显然是不正确的,进而编译报错;

为什么以全局函数方式重载运算符 “+”

理由
以全局函数的形式重载 +,是为了保证 + 运算符的操作数能够被对称的处理;换句话说,小数(double)在 + 左边和右边都是正确的;

为什么以成员函数方式重载运算符 “+=”,不是“+”

理由:
我们首先要明白,运算符重载的初衷是给类添加新的功能,方便类的运算,它作为类的成员函数是理所应当的,是首选的;不过,类的成员函数不能对称地处理数据,程序员必须在(参与运算的)所有类型的内部都重载当前的运算符;

总结

以上面的情况为例,我们必须在 Complex 和 double 内部都重载 + 运算符,这样做不但会增加运算符重载的数目,还要在许多地方修改代码,这显然不是我们所希望的,所以 C++ 进行了折中,允许以全局函数(友元函数)的形式重载运算符;

  1. 采用全局函数能使我们定义这样的运算符,它们的参数具有逻辑的对称性;
    与此相对应的,把运算符定义为成员函数能够保证在调用时对第一个(最左的)运算对象不出现类型转换,也就是上面提到的「C++ 不会对调用成员函数的对象进行类型转换」;

  2. 有一部分运算符重载既可以是成员函数也可以是全局函数,虽然没有一个必然的、不可抗拒的理由选择成员函数,但我们应该优先考虑成员函数,这样更符合运算符重载的初衷;

  3. 另外有一部分运算符重载必须是全局函数,这样能保证参数的对称性;除了 C++ 规定的几个特定的运算符外,暂时还没有发现必须以成员函数的形式重载的运算符;C++ 规定,箭头运算符->、下标运算符[]、函数调用运算符()、赋值运算符=只能以成员函数的形式重载;

发布了93 篇原创文章 · 获赞 65 · 访问量 5479

猜你喜欢

转载自blog.csdn.net/qq_44861675/article/details/105126559
今日推荐