• C++中的赋值运算符重载和类的那点事


    1.引言

    在c++中我们有时可能需要对类对象,进行算术运算和逻辑运算等操作,但是对于自定义类型的对象来说默认情况C++是不支持使用运算符的,如下面的日期类Date中所存在的问题,此时C++中引入了运算符重载,来解决这一问题。

    class Date
    {
    public:
    	Date(int year = 0, int month = 1, int day = 1)
    	{
    		_year = year;
    		_month = month;
    		_day = day;
    	}
    
    private:
    	int _year;
    	int _month;
    	int _day;
    };
    int main()
    {
    	Date d1(2023,9,25);
    	Date d2(2022,9,25);
    	d1>d2;//此时这里会直接报错
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    2.语法规则

    • 函数名字为:关键字operator后面接需要重载的运算符符号。
    • 函数原型:返回值类型 operator操作符(参数列表)
    • 特点规则:
      1、不能通过连接其他符号来创建新的操作符:比如operator@
      2、重载操作符必须有一个类类型或者枚举类型的操作数
      3、用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不 能改变其含义
      4、作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数的
      操作符有一个默认的形参this,限定为第一个形参
      5、* 、:: 、sizeof 、?: 、. 注意以上5个运算符不能重载。
    • 使用运算符重载解决上面日期类Date中的问题
    class Date
    {
    public:
    	Date(int year = 0, int month = 1, int day = 1)
    	{
    		_year = year;
    		_month = month;
    		_day = day;
    	}
    	int _year;
    	int _month;
    	int _day;
    };
    
     函数名 operator操作符
     返回类型 看操作符运算后返回值是什么
     参数,操作符有几个操作数,他就有几个参数
    bool operator>(const Date& d1, const Date& d2)
    {
    	if (d1._year > d2._year)
    	{
    		return true;
    	}
    	else if (d1._year == d2._year && d1._month > d2._month)
    	{
    		return true;
    	}
    	else if (d1._year == d2._year && d1._month == d2._month && d1._day > d2._day)
    	{
    		return true;
    	}
    	else
    	{
    		return false;
    	}
    }
    
    int main()
    {
    	Date d1(2022, 1, 16);
    	Date d2(2022, 1, 31);
    	d1 > d2; // -》operator>(d1, d2)
    	cout << operator>(d1, d2) << endl;
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 上面的代码虽然解决了自定义类型的运算符问题,但是细心的同学可能会发现一些问题。对于这个重载运算符函数是写在类的外面的,为了能访问到类里的对象,我这里不得以把成员变量定义成了public,当然你也可以采用一些接口提供。但是这些方法都使问题变得复杂,并且失去了原有的类的封装的特性。哪还有什么别的解决方法吗?那就是在类中进行运算符的重载!!!

    3.在类中进行运算符重载时的语法

    话不多说,以下面一段代码为例。

    class Date
    {
    public:
    	Date(int year = 0, int month = 1, int day = 1)
    	{
    		_year = year;
    		_month = month;
    		_day = day;
    	}
    	bool operator>(const Date& d) 
    // bool operator>(Date* const this, const Date& d)
    	{
    		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 _year;
    	int _month;
    	int _day;
    };
    int main()
    {
    	Date d1(2022, 1, 16);
    	Date d2(2022, 1, 31);
    	d1 > d2; // d1.operator>(d2);
    	d1.operator>(d2);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    有些同学一定会问类中的bool operator>(const Date& d) 怎么只有一个参数了,以前不是有两个参数吗?大家是否还记得我写过的详谈C++this指针一文,在类中是有一个隐藏的指针的,这里你看到的函数只有一个参数,但实际上是有两个参数的,隐藏的this指针和const Date& d。可以把类中的bool operator>(const Date& d)方法翻译成如下代码,来加深大家的理解。

     
     	bool operator>(Date* const this, const Date& d)
    	{
    		if (this->_year > d._year)
    		{
    			return true;
    		}
    		else if (this->_year == d._year && this->_month > d._month)
    		{
    			return true;
    		}
    //看到这里想必大家恍然大悟了吧!!!
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4.赋值运算符重载!!!

    4.1认识赋值运算符重载

    请问下面的两种赋值运算符重载的方法A,B。你认为哪一种更好。

    class Date
    { 
    public :
     Date(int year = 1900, int month = 1, int day = 1)
     {
     _year = year;
     _month = month;
     _day = day;
     }
     //A
     Date (const Date& d)
     {
     	_year = d._year;
     	_month = d._month;
     	_day = d._day;
     	return *this;
     }
     //B
     Date& operator=(const Date& d)
     {
     	//防止进行自身赋值。如d1=d1这个情况
     	if(this != &d)
     	{
     		_year = d._year;
     		_month = d._month;
     		_day = d._day;
    	}
    	return *this;
     }
    private:
     int _year ;
     int _month ;
     int _day ;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    答案是B的写法更好,两种方法虽然都可以完成赋值运算符重载,但是在A中的写法在返回值的时候会调用拷贝构造,频繁的调用拷贝构造是存在效率问题的。

    4.2赋值运算符重载的特点

    1. 参数类型
    2. 返回值(一般是返回引用)
    3. 检测是否自己给自己赋值
    4. 返回*this
    5. 一个类如果没有显式定义赋值运算符重载,编译器也会生成一个,完成对象按字节序的值拷贝。
    6. 编译器默认生成赋值重载的特点:内置类型成员,会完成字节序值拷贝–浅拷贝。自定义类型的成员变量,会表用它本身的operator=。
  • 相关阅读:
    OpenEuler22.03安装PostgreSQL15.5并配置一主二从
    MBps与Mbps区别
    使用PCA9685控制多个舵机
    python爬取网站数据,作为后端数据
    微信小程序实现美食检索功能
    [C语言、C++]数据结构作业:用递归实现走迷宫(打印正确通路即可)
    vue 树状结构数据渲染 (java 处理 list ->树状)
    Nodejs核心模块之Events
    如何处理Flutter应用在iOS平台上的兼容性问题
    ROS学习ROS基础
  • 原文地址:https://blog.csdn.net/weixin_51692487/article/details/133279519