zoukankan      html  css  js  c++  java
  • 【C/C++学习】之十三、运算符重载

    所有一元运算符         建议重载为成员函数
    = () []  —>         只能重载为成员函数
    += -= /= *= |= ~= %= >>= <<=   建议重载为成员函数
    所有其他运算符         建议重载为全局函数
    . 操作符不能重载

    不能重载目前C++运算符集合中没有的符号   

     原因:1。难以理解   2.难以确定优先级

    对已经存在的运算符进行重载时,不能改变优先级规则,否则将引起混乱。

    运算符重载的一般形式如下:

    返回类型 operator 运算符符号(参数说明)
    {
    ....
    }

    函数重载的时候,只有一个参数的运算符叫做一元运算符,有两个参数的运算符叫做二元运算符。

    当你在类中重载运算符的时候,如果是一元运算符就不需要参数了,二元运算符只有一个右侧参数,因为对象自己就作为左侧参数。

    对于全局函数和成员函数:

    运算符

    建议

    所有的一元运算符 建议重载为成员函数                                 
    =、()、[]、-> 只能重载为成员函数
    +=、-=、/=、*=、&=、|=、~=、%=、>>=、<<= 建议重载为成员函数
    所有其他运算符 建议重载为全局函数

    下面看一下重载运算符的规则:

    1、只能重载语言自身已有定义的运算符。

    2、有5个运算符不能重载,分别是类属性运算符“."、成员指针运算符”*“、作用域分辨符"::"、”sizeof“运算符和三目运算符"?:'。  还有就是不能重载C++运算符集合中没有的符号,因为他们难以理解,难以确定优先级。

    3、不能改变运算符的操作个数。

    4、不能改变运算符的原有优先级。

    5、不能改变运算符原有的结合特性。

    6、不能改变运算符对预定义类型数据的操作方式。

    {优先级不变,结合性不变,操作数不变,语法结构不变}

    在类中,有成员函数和友元函数两种,我们可以使用友元函数重载运算符。也就是当操作符定义为非成员函数时,通常必须将他们设置为所操作类的友元。

    当我们使用友元函数重载运算符时,由于没有this执着呢,因此,函数的参数是引用类型:

    A operator +(const A &a1, const A &a2);

    当我们使用友元函数重载双目运算符时,两个操作数都要传递给运算符函数。

    当我们使用友元函数重载单目运算符时,需要一个显示的操作符。

    我们在实际开发中,单目运算符建议重载为成员函数,而双目运算符建议重载为友元函数,通常情况下双目运算符重载为友元函数比重载为成员函数更方便,但是有时双目运算符必须重载为成员函数:如:赋值运算符,  如果将该运算符重载为友元函数,将会出现与赋值予以不一致的地方。

    但是当我们用友元函数重载”++“和”--“运算符的时候又会怎样呢?

              运算符”++“和”--“都是对单值操作数产生影响的,因此使用成员函数重载这两个运算符的成员函数通常返回指针this。

              因为友元函数没有this指针,因此不能引用this指针作为指向的对象。使用友元函数重载这两个操作符时,应采用引用参数传递数据。

    如:

    a operator ++(a &op)
    {
        ++op.x;
        ++op.y;
         return op;
    }

    说到这里,我们就来看一下成员运算符函数和友元运算符函数的区别:

    1、格式不同

    友元函数:

    <类型说明符> operator <运算符>(<参数表>)
    {
    函数体
    }
    成员函数:

    <类型说明符> 类名::operator <运算符>(<参数表>)
    {
    函数体
    }

    2、参数表的结构不同

    在成员运算符函数的参数表中,如果运算符时单目的,则参数为空,此时当前对象作为运算符的一个操作数,通过this指针隐含地传递给函数;

    如果运算符时双目的,则参数表中有一个操作数,该操作数作为运算符的右操作参数,此时当前对象作为运算符的左操作数,它是由this指针隐含地传递给函数的。

    而和成员函数不同,友元运算符函数不属于任何类对象,其没有this指针。如果重载的是双目运算符,则参数表中有两个操作数;如果重载的是单目运算符,则参数表中只有一个操作数。

     


    下面来看一下重载NEW和DELETE运算符,数组下标运算符:

    1、NEW和DELETE运算符

    有两种方式重载:

    1、覆盖默认定义的全局方式    2、只针对一个类的局部方式。      在实际应用中,一般采用后一种方式。

    void* operator new(size_t size)
    {
    使用new运算符分配size大小的存储空间。
    }

    void* operator delete(void* pointer)
    {
    使用delete运算符释放指针pointer所指向的存储空间
    }

    上面是new和delete运算符的重载方式, 其中pointer指针指向一个待释放的内存空间,   我们调用delete()函数释放该指针所指向的内存空间。

    我们在类中重载的new和delete运算符只能用于动态生成各个对象,而不能用于生成对象数据、自动对象和静态对象等。

    重载全局的new和delete运算符需要在类的外部定义,定义格式与在类中定义的格式基本相同,只是不带类作用域。重载全局的new和delete运算符时需要谨慎,一旦定义为全局,在整个程序中只要是使用new和delete运算符的操作都将使用该重载的定义。


    2、数组下标运算符

    我们知道数组的大小是不能确保的,所以对数组元素进行存取范围的检查是不允许的,所以在操作数组动态赋值时经常会发生越界。所以我们在这里来说一种安全的方案定义重载的运算符"[]";

    我们在重载下标运算符的时候要注意:

    1、该函数只能带一个参数,不能带多个参数。

    2、得重载为友元函数,必须是非static类的成员函数。


    下面再来看一下重载输入输出操作符:

    ostream& operator<<(ostream& out, const A& s)
    {
        out  << s.a  <<.............
        return out;
    }
    
    
    instream& operator>>(istream& in, A& s)
    {
        double si;
        in >> s.a.....................
        if (in)
            ...
        else
            ...
        return in;
    }



    最后要注意的是不要滥用操作符重载。



    2012/10/11

    jofranks 于南昌

  • 相关阅读:
    Qt操作xml文件(增删改功能)
    Qt解析xml
    Qt中使用DOM解析XML文件或者字符串二(实例)
    Qt中使用DOM解析XML文件或者字符串(实例)
    QThread 实用技巧、误区----但文档中没有提到
    事件循环与线程 二
    事件循环与线程 一
    第一讲 递归
    Ubuntu 建立桌面快捷方式
    Codeforces554B:Ohana Cleans Up
  • 原文地址:https://www.cnblogs.com/java20130723/p/3211391.html
Copyright © 2011-2022 走看看