• 标准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、不要忘记实现运算符重载函数的初衷,为了提高可读性,不要随意炫技

  • 相关阅读:
    通讯录管理系统JAVA版本
    Hive (七) --------- 分区表和分桶表
    二、Prometheus常用exporter安装详解
    .NET 7 AOT 的使用以及 .NET 与 Go 互相调用
    还在用 SimpleDateFormat 做时间格式化?小心项目崩掉!
    【Linux】vim 使用
    在线存储系统源码 网盘网站源码 云盘系统源码
    不要轻易更换zotero同步的官网账号
    六、python Django REST framework数据处理[序列化]
    JavaScript 练手小技巧:十几行代码搞定点击复制指定标签内容
  • 原文地址:https://blog.csdn.net/weixin_51479108/article/details/132888499