当前位置:   article > 正文

C++ ─── 操作符重载和赋值重载

C++ ─── 操作符重载和赋值重载

目录

赋值运算符重载

 运算符重载

赋值运算符重载(赋值重载operator=)

前置++和后置++重载


赋值运算符重载

 运算符重载

        C++为了增强代码的可读性引入了运算符重载 运算符重载是具有特殊函数名的函数 ,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名字为:关键字 operator 后面接需要重载的运算符符号
函数原型: 返回值类型  operator 操作符 ( 参数列表 )
注意:
        不能通过连接其他符号来创建新的操作符:比如operator@
        重载操作符必须有一个类类型参数
        用于内置类型的运算符,其含义不能改变,例如:内置的整型+ ,不 能改变其含义
        作为类成员函数重载时,其形参看起来比操作数数目少1 ,因为成员函数的第一个参数为隐
藏的 this指针。
         .*    ::    sizeof    ?:    . 注意以上 5 个运算符不能重载。这个经常在笔试选择题中出现
  1. // 全局的operator==
  2. class Date
  3. {
  4. public:
  5. Date(int year = 1900, int month = 1, int day = 1)
  6.   {
  7.        _year = year;
  8.        _month = month;
  9.        _day = day;
  10.   }    
  11. //private:
  12. int _year;
  13. int _month;
  14. int _day;
  15. };
  16. // 这里会发现运算符重载成全局的就需要成员变量是公有的,那么问题来了,封装性如何保证?
  17. // 这里其实可以用我们后面学习的友元解决,或者干脆重载成成员函数。
  18. bool operator==(const Date& d1, const Date& d2)
  19. {
  20.    return d1._year == d2._year
  21.   && d1._month == d2._month
  22.        && d1._day == d2._day;
  23. }
  24. void Test ()
  25. {
  26.    Date d1(2018, 9, 26);
  27.    Date d2(2018, 9, 27);
  28.    cout<<(d1 == d2)<<endl;
  29. }
  1. class Date
  2. {
  3. public:
  4. Date(int year = 1900, int month = 1, int day = 1)
  5.   {
  6.        _year = year;
  7.        _month = month;
  8.        _day = day;
  9.   }
  10.    
  11.    // bool operator==(Date* this, const Date& d2)
  12.    // 这里需要注意的是,左操作数是this,指向调用函数的对象
  13.    bool operator==(const Date& d2)
  14. {
  15.        return _year == d2._year;
  16.            && _month == d2._month
  17.            && _day == d2._day;
  18. }
  19. private:
  20. int _year;
  21. int _month;
  22. int _day;
  23. };

赋值运算符重载(赋值重载operator=)

        1. 赋值运算符重载格式
                参数类型:const &T ,传递引用可以提高传参效率
                返回值类型:T& ,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值
                检测是否自己给自己赋值
                返回*this :要复合连续赋值的含义
  1. class Date
  2. {
  3. public :
  4. //构造函数
  5. Date(int year = 1900, int month = 1, int day = 1)
  6.   {
  7.        _year = year;
  8.        _month = month;
  9.        _day = day;
  10.   }
  11. //拷贝构造函数
  12. Date (const Date& d)
  13.   {
  14.        _year = d._year;
  15.        _month = d._month;
  16.        _day = d._day;
  17.   }
  18. //赋值重载函数
  19. Date& operator=(const Date& d)//引用
  20. {
  21. if(this != &d)//取地址判断是否是自己给自己赋值
  22.       {
  23.            _year = d._year;
  24.            _month = d._month;
  25.            _day = d._day;
  26.       }
  27.        
  28.        return *this;
  29. }
  30. private:
  31. int _year ;
  32. int _month ;
  33. int _day ;
  34. };

        2. 赋值运算符只能重载成类的成员函数不能重载成全局函数

  1. class Date
  2. {
  3. public:
  4. Date(int year = 1900, int month = 1, int day = 1)
  5. {
  6. _year = year;
  7. _month = month;
  8. _day = day;
  9. }
  10. int _year;
  11. int _month;
  12. int _day;
  13. };
  14. // 赋值运算符重载成全局函数,注意重载成全局函数时没有this指针了,需要给两个参数
  15. Date& operator=(Date& left, const Date& right)
  16. {
  17. if (&left != &right)
  18. {
  19. left._year = right._year;
  20. left._month = right._month;
  21. left._day = right._day;
  22. }
  23. return left;
  24. }
  25. // 编译失败:
  26. // error C2801: “operator =”必须是非静态成员
        原因:赋值运算符如果不显式实现(写出来),编译器会生成一个默认的。此时用户再在类外自己实现
一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,故 赋值运算符重载只能是类的成员函数。
        3. 用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。(浅拷贝)
        注意:内置类型成员变量(int ,char)是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符 重载完成赋值。
  1. class Time
  2. {
  3. public:
  4. Time()
  5. {
  6. _hour = 1;
  7. _minute = 1;
  8. _second = 1;
  9. }
  10. Time& operator=(const Time& t)
  11. {
  12. if (this != &t)
  13. {
  14. _hour = t._hour;
  15. _minute = t._minute;
  16. _second = t._second;
  17. }
  18. return *this;
  19. }
  20. private:
  21. int _hour;
  22. int _minute;
  23. int _second;
  24. };
  25. class Date
  26. {
  27. private:
  28. // 基本类型(内置类型)
  29. int _year = 1970;
  30. int _month = 1;
  31. int _day = 1;
  32. // 自定义类型
  33. Time _t;
  34. };
  35. int main()
  36. {
  37. Date d1;
  38. Date d2;
  39. d1 = d2;
  40. return 0;
  41. }

        既然编译器生成的默认赋值运算符重载函数已经可以完成字节序的值拷贝了 ,还需要自己实
现吗?当然像日期类这样的类是没必要的。
        注意: 如果类中未涉及到资源管理,赋值运算符是否实现都可以;一旦涉及到资源管理则必
须要实现。

前置++和后置++重载

  1. class Date
  2. {
  3. public:
  4. Date(int year = 1900, int month = 1, int day = 1)
  5. {
  6. _year = year;
  7. _month = month;
  8. _day = day;
  9. }
  10. // 前置++:返回+1之后的结果
  11. // 注意:this指向的对象函数结束后不会销毁,故以引用方式返回提高效率
  12. Date& operator++()
  13. {
  14. _day += 1;
  15. return *this;
  16. }
  17. // 后置++:
  18. // 前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载
  19. // C++规定:后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器自动传递
  20. // 注意:后置++是先使用后+1,因此需要返回+1之前的旧值,故需在实现时需要先将this保存一份,然后给this+1
  21. //而temp是临时对象,因此只能以值的方式返回,不能返回引用
  22. Date operator++(int)
  23. {
  24. Date temp(*this);
  25. _day += 1;
  26. return temp;
  27. }
  28. private:
  29. int _year;
  30. int _month;
  31. int _day;
  32. };
  33. int main()
  34. {
  35. Date d;
  36. Date d1(2022, 1, 13);
  37. d = d1++;    // d: 2022,1,13   d1:2022,1,14
  38. d = ++d1;    // d: 2022,1,15   d1:2022,1,15
  39. return 0;
  40. }

这个博客如果对你有帮助,给博主一个免费的点赞就是最大的帮助

欢迎各位点赞,收藏和关注哦

如果有疑问或有不同见解,欢迎在评论区留言哦

后续我会一直分享双一流211西北大学软件(C,数据结构,C++,Linux,MySQL)的学习干货以及重要代码的分享

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/577863
推荐阅读
相关标签
  

闽ICP备14008679号