标准C++day6——输入输出及运算符重载

一、输入输出运算符

运算符函数的格式:#表示运算符 O表示运算符对象  []代表返回值不确定

    在C++中 << >> 运算符不光是按位左移、按位右移,同时还是cout该类的输出运算符 cin该类的输入运算符

    输出运算符:

    cout << 10 << endl;

    Test t;

    cout << t << t2 << endl;

    由于 << 运算符的调用者是cout对象,我们是无法在该对象的类中去设计一个输出运算符的成员函数,所以只能实现 << 运算的全局函数

    ostream& operator<<(ostream& os,const O& t)

    {

        return os << t.x << t.y;

    }

    输入运算符:

    cin >> num;

    cin >> t1 >> t2;

    istream& operator>>(istream& is,O& t)

    {

        return is >> t.x >> t.y;

    }

    注意:

    1、由于输出、输入是可以连续进行的,所以返回值还应该是ostream、istream引用

    2、因为无法在ostream、istream中重载运算符成员函数,所以<< >>只能重载成全局函数

    3、如果在重载全局函数中使用到自己类中私有的成员变量,需要声明为友元函数

    4、输出运算符函数中,第二个参数一定要加const,而输入运算符函数中不能加

二、运算类的单目运算符

    单目:++/-- ! ~ - * & sizeof

    成员函数: ~ ! -

    const int num;

    ~0; ~num;   true

    ~num = 10;  false

    O O::operator~(void)const

    {

        return O(~x,~y);

    }

    注意:运算对象可以具备常属性,因此需要是常函数,运算结果只是一个临时值,并且是右值

    全局函数:

    O operator~(const O& a)

    {

        return O(~a.x,~a.y);

    }

三、自变运算符函数

    C++的前后自变左右值问题:

        能位于赋值运算符= 左边的就是左值,反之为右值

        有名称、可以获取到存储地址的称为左值,反之为右值  

        C++前自变:++num = 10;  //  成功 num=10

            直接修改原对象,在原对象基础上实现自变,然后将原对象的引用返回,所以操作和返回的一直是原对象,是左值

        C++后自变:num++ = 10;  //  报错

            先将原对象的数据存储到临时变量中,接着在原对象基础上自变,然后把临时变量以只读方式返回,并且该临时变量执行语句结束后立即销毁了,无法访问,因此结果是右值

       

        ++num++ // 后自变优先级更高,报错

        (++num)++   //  先前自变为左值,成功

        注意:C语言中,无论前后自变,结果都是右值

    前自变运算符: ++a/--a

    成员函数:

        O& O::operator++(void)

        {

            x++,y++;

            return *this;

        }

    全局函数:

        O& operator++(O& a)

        {

            a.x++,a.y++;

            return a;

        }

   

    后自变运算符:a++/a--

        哑元:在参数列表末尾增加一个不使用且无形参名的int哑元类型,唯一目的就是用于区分是前自变还是后自变

        成员函数:

        O O::operator++(int)

        {

            return O(x++,y++);

        }

        全局函数:

        O operator++(O& a,int)

        {

            return O(a.x++,a.y++);

        }

四、特殊的运算符重载函数

    * -> () [] new delete

    1、[]下标运算符

        想让一个类对象当成数组一样使用,可以考虑重载下标运算符,例如:vector等

        可以考虑在下标重载函数中做非法下标的判断,让下标的使用更安全

    2、()函数运算符

        重载此运算符可以让一个类对象当做函数一样使用

   

    注意:()\[] 均不能实现为全局运算符函数,只能实现成员函数(C++全局中已经有类似的函数实现,所以不让实现)

        = 赋值运算符函数也不能实现为全局函数,因为类内本身一定有一个=赋值运算符成员函数

   

    3、解引用* 和访问成员运算符 —>  

        重载这两个运算符可以让类对象像指针一样使用,智能指针就是通过重载这俩运算符从而像使用指针一样的类

    4、new/delete运算符重载

        void* operator new(size_t size)

        C++语法要求重载new运算符的参数必须为size_t,编译器会帮助计算出要申请的字节数并传递,返回值必须为void*,编译器会帮助转换成对应的类型指针返回

        void operator delete(void* ptr)

        C++语法要求重载delete的参数必须为void*,编译器帮助转换成void*传递

        注意: new、delete的成员函数、全局函数格式一样

        如果只是针对某个类想要重载它的new\delete时,则写为成员函数

        如果想要所有类型都执行重载版本,则实现为全局函数

        为什么要重载new\delete?

        1、可以在重载函数中记录每次分配、释放内存的地址、代码情况、次数情况等到日志中,从而方便检查是否出现内存泄漏,以及泄漏位置

        2、对于字节少、且频繁申请、释放的对象,可以在重载函数中给他多分配点内存从而减少产生碎片的可能

五、重载运算符的限制

    1、不能重载的运算符

        ::  域限定符

        .   直接访问成员的运算符

        ?:  三目运算符

        sizeof 计算字节数

        typeid 获取类型信息的运算符

    2、只能重载为全局函数的运算符

        <<  输出运算符

        >>  输入运算符

    3、只能重载为成员函数的运算符

        []  

        ()

        =

        —>  

    4、运算符重载可以自定义运算符执行过程,但是无法改变运算符的优先级

    5、运算符的操作数量也不能改变

    6、不能发明新的运算符

    建议:

        1、重载运算符要遵循一致性原则,不要随意改变运算符本身的含义

        2、不要忘记实现运算符重载函数的初衷,为了提高可读性,不要随意炫技

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值