成员函数重载运算符和友元函数重载运算符

先上题:下列运算符都可以被友元函数重载的是:
A) =,+,-,
B) [],+,(),new
C) ->,+,,>>
D) <<,>>,+,

正确答案为D

在运算符重载,友元函数运算符重载函数与成员运算符重载函数的区别是:友元函数没有this指针,而成员函数有,因此,在两个操作数的重载中友元函数有两个参数,而成员函数只有一个。

重载运算符的基本原则:

  1. 为了防止用户对标准类型进行运算符重载,C++规定重载后的运算符的操作对象必须至少有一个是用户定义的类型
    比如说现在有两个数:int number1,int number2,
    那么number1+number2 求的是两个数的和,
    但是如果你重载以后让着两个数相加为他们的乘积,这肯定是不合乎逻辑的。
    可能重载以后会有二义性,导致程序不知道该执行哪一个(是自带的的还是重载后的函数)
  2. 使用运算符不能违法运算符原来的句法规则。如不能将% 重载为一个操作数
  3. 不能修改运算符原先的优先级
  4. 不能创建一个新的运算符,例如不能定义operator** (···)来表示求幂
  5. 不能进行重载的运算符
    .:成员访问运算符
    ., ->:成员指针访问运算符
    :::域运算符
    sizeof:长度运算符
    ?::条件运算符
    #: 预处理符号

下面比较成员函数和非成员函数(友元函数)重载运算符

  1. 对双目运算符而言,成员函数重载运算符的函数参数表中只有一个参数,而用友元函数重载运算符函数参数表中含有两个参数。
    对单目运算符来说,成员函数重载运算符的函数参数表中没有参数,而用友元函数重载运算符函数参数表中含有一个函数。这个问题要搞清楚,有一个this指针的问题
  2. 双目运算符一般可以用友元函数重载和成员函数重载,但有一种情况只可以用友元函数重载。
    即:双目运算符左边的变量是一个常量,而不是对象!!!这点很重要的额。比如说string,左边是一个const char*
    string str = "test";
    string ok = "testtest" + str;
    //这样的运算符必须是友元,因为它的第一个参数是char* 类型,相当于调用 operator (char , string str)
    string oook = str + "testset"; //这个就必须是成员函数,因为第一个str+ 表示调用str的成员函数operator+(char
    )

所以说,单目运算符建议选择成员函数。

下面是重点

只能作为成员函数重载的四个操作符

=,(),[],->
原因很简单,会和编译器默认分配的运算符重载成员函数冲突,引发歧义。
我们知道友元函数不是类的成员函数,它只是类的“朋友“,具有访问把它声明为“朋友”的类的数据成员的权限而已。
那么当把赋值运算符重载为类的友员函数,在程序中执行类对象的赋值语句时,程序就会出现两种矛盾的选择。

  1. 因为它认为类中并没有重载赋值运算符的成员函数,所以它根据C++的规则,会去调用相应的构造函数。
  2. 但是在全局里,我们已经重载了参数类型为此类类型的赋值运算符函数,而这赋值语句刚好和这函数匹配上了,根据C++的规则,也会去调用这函数。

程序是不允许有矛盾不确定选择的,所以当赋值运算符重载为类的友元函数时,编译器就会提示错误。
对于剩下的3个运算符 ->, [], () 为什么不能重载为友元函数,也是跟上面一样的道理。即编译器发现当类中没有定义这3个运算符的重载成员函数时,就会自己加入默认的运算符重载成员函数。

那么下面这个题的答案也就很明显了:
将x+y*z中的“+”用成员函数重载,“*”用友元函数重载应该写为:?
答案为:x.operator+(operator*(y,z))

你可能感兴趣的:(成员函数重载运算符和友元函数重载运算符)