赋值运算符重载函数

举报
芒果_Mango 发表于 2022/04/30 22:48:19 2022/04/30
【摘要】 大家好,我是芒果,一名非科班的在校大学生。对C/C++、数据结构、Linux及MySql、算法等领域感兴趣,喜欢将所学知识写成博客记录下来。 希望该文章对你有所帮助!如果有错误请大佬们指正!共同学习交流作者简介:CSDN C/C++领域新星创作者https://blog.csdn.net/chuxinchangcun?type=blog掘金LV3用户 https://juejin.cn/us...

大家好,我是芒果,一名非科班的在校大学生。对C/C++、数据结构、Linux及MySql、算法等领域感兴趣,喜欢将所学知识写成博客记录下来。 希望该文章对你有所帮助!如果有错误请大佬们指正!共同学习交流

作者简介:


5.赋值运算符重载

5.1 运算符重载

C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类 型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

函数名字为:关键字 operator 后面接需要重载的运算符符号。

函数原型:返回值类型 operator 操作符(参数列表) 注意:

  • 不能通过连接其他符号来创建新的操作符:比如operator@
  • 重载操作符必须有一个类类型或者枚举类型的操作数
  • 用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不 能改变其含义
  • 作为类成员的重载函数时,其形参看起来比操作数数目少一个,成员函数的 操作符有一个默认的形参this,限定为第一个形参
  • .*::(域限定符) 、sizeof?:(三目运算符) 、.(对象/结构体的访问里面的.) 注意以上5个运算符不能重载。这个经常在笔试选择题中出现
  • *可以重载,.*不能重载

image-20220117174053272


注意:cout<<d1> d2 << endl; 是错误的,因为<<的优先级比>高

应该写成: cout<< (d1>d2) << endl;


C++的函数必须写返回值类型,不写会报错!

class Date
{
public:
    //构造函数
    Date(int year = 0, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
    }
    //运算符重载函数
    //要注意隐藏的this指针
    //bool operator>(Date* const this,const Date& d)
    //若写成:bool operator>(const Date& d1,const Date& d2)是错误的,这样相当于有3个参数了!
    bool operator>(const Date& d)
    {   
        //相当于 this->_year > d._year
        if (_year > d._year)
        {
            return true;
        }
        else if (_year == d._year && _month > d._month)
        {
            return true;
        }
        else if (_year == d._year && _month == d._month && _day > d._day)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
private:
    int _month;
    int _year;
    int _day;
};

image-20220117175049955


class Date
{
public:
    Date(int year = 1900, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
    }
    // bool operator==(Date* this, const Date& d2)
    // 这里需要注意的是,左操作数是this指向的调用函数的对象
    bool operator==(const Date& d2)
    {
        return _year == d2._year;
        && _month == d2._month
            && _day == d2._day;
    }
private:
    int _year;
    int _month;
    int _day;
};
void Test ()
{
    Date d1(2018, 9, 26);
    Date d2(2018, 9, 27);
    cout<<(d1 == d2)<<endl;
}

注意:如果全局和类里面都写了运算符重载函数,能正常编译通过!不会出现重定义,但是调用时,用的是类里面的函数。编译器优先在类里面去找

类里面的函数不是全局的,而是属于类域里的


5.2 赋值运算符重载

一个已经存在的对象拷贝初始化一个马上创建实例化的对象 ->拷贝构造

两个已经存在的对象之间进行赋值拷贝 ->运算符重载

int main()
{
    Date d1;
    Date d2;
    //一个已经存在的对象拷贝初始化一个马上创建实例化的对象
    Date d3 = d1;//拷贝构造
    Date d4(d1);//拷贝构造
    //两个已经存在的对象之间进行赋值拷贝
    d2 = d1;//运算符重载  -> d2.operator=(d1);
}

image-20220117180350797

要返回的是左操作数的,所以返回的是*this,而不是this。由于出了作用域,*this还存在(*this == d1),所以可以使用传引用返回,减少拷贝!

如果使用的是传值返回,传值返回是一次拷贝构造

image-20220117181012616


优化

有可能为:d1 = d1; 相同的对象赋值,这样不会有什么问题,可以编译通过.但是可以优化一下

class Date
{
public :
    //构造函数
    Date(int year = 1900, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
    }
    //拷贝构造
    Date (const Date& d)
    {
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }
    //赋值运算符重载
    Date& operator=(const Date& d)
    {
        //极端情况下,自己给自己赋值就可以不进行处理
        //两个地址进行比较
        //d1 = d1,此时 this 就是d1的地址,d是d1的别名,&d也是d1的地址
        if(this != &d)
        {
            _year = d._year;
            _month = d._month;
            _day = d._day;
        }
        //若使用的是if(*this != d)->此处是两个对象进行比较了,需要调用运算符!=的重载函数
        return *this;
    }
private:
    int _year ;
    int _month ;
    int _day ;
};

赋值运算符主要有四点:

  1. 参数类型
  2. 返回值
  3. 检测是否自己给自己赋值
  4. 返回*this
  5. 一个类如果没有显式定义赋值运算符重载,编译器也会生成一个,完成对象按字节序的值拷贝。
class Date
{
public:
    Date(int year = 1900, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
    }
private:
    int _year;
    int _month;
    int _day;
};
int main()
{
    Date d1;
    Date d2(2018101);
    // 这里d1调用的编译器自己生成operator=完成拷贝,d2和d1的值也是一样的。
    d1 = d2;
    return 0;
}

image-20220117181545111

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。