美文网首页
成员函数重载运算符和友元函数重载运算符

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

作者: leon4ever | 来源:发表于2018-01-23 08:58 被阅读85次

    先上题:下列运算符都可以被友元函数重载的是:
    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))

    相关文章

      网友评论

          本文标题:成员函数重载运算符和友元函数重载运算符

          本文链接:https://www.haomeiwen.com/subject/ozvjaxtx.html