【C++】详解运算符重载,赋值运算符重载,++运算符重载

这篇具有很好参考价值的文章主要介绍了【C++】详解运算符重载,赋值运算符重载,++运算符重载。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

前言

运算符重载

概念

目的

写法

调用

注意事项

详解注意事项

运算符重载成全局性的弊端

类中隐含的this指针

赋值运算符重载

赋值运算符重载格式

注意点

明晰赋值运算符重载函数的调用

连续赋值

传引用与传值返回

默认赋值运算符重载

前置++和后置++重载


前言

先梳理一下本篇的脉络,首先会讲解运算符重载的概念,这是本篇的基本概念。其次会讲解赋值运算符的重载,这是本篇的重点,最后是++运算符重载,只需明晰规则即可。此外,希望这篇文章能让大家有所收获,如有不足之处,还请指正,小编会虚心接受并改进质量。


运算符重载

概念

C++引入了运算符重载。它和函数重载的概念类似,可以让一个符号有不同的功能而具体的功能是由自己实现的。

目的

是为了增强代码的可读性。C++中有这个概念。“  + ” 这个符号可以实现两个整形或浮点型相加,因为这两个类型是语言自己定义的。但它能实现两个的相加吗?显然不行,因为这个类型是自己设计的,相加要实现怎样的效果只有自己知道。

写法

运算符重载也是函数的一种,只不过函数名比较特殊,其返回值和参数列表和普通函数一样。参数的数量和操作数的数量一致,参数的顺序和操作数的顺序一致

函数名字为:关键字 operator 后面接需要重载的运算符符号
函数原型: 返回值类型 operator操作符(参数列表)
示例(判断两个日期类是否相等) 【C++】详解运算符重载,赋值运算符重载,++运算符重载,C++,前端,javascript,c++,开发语言,c语言

调用

分为显式调用(加关键字)和隐式调用(不加关键字),如下代码

operator==(d1, d2)//显式调用
==(d1, d2) //隐式调用

注意事项

运算符重载的注意事项
1.
不能通过连接其他符号来创建新的操作符:比如operator@
2.
重载操作符必须有一个类类型参数
3.
用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其含义
4.
作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
5.
.*   ::   sizeof   ?:   . 注意以上5个运算符不能重载。

详解注意事项

1.想要重载一个符号,必须复用语言定义过的符号,不能凭空捏造。如下代码就会报错。


bool operator@(const Date& d1, const Date& d2)

【C++】详解运算符重载,赋值运算符重载,++运算符重载,C++,前端,javascript,c++,开发语言,c语言

2.假如要把“  ”这个符号重载成整形和字符型的相加,这毫无意义并且会破坏语言原有的运算规则,此时编译器会强制报错。【C++】详解运算符重载,赋值运算符重载,++运算符重载,C++,前端,javascript,c++,开发语言,c语言

3.如果要把加“  ”这个符号重载两个相加,那具体实现的逻辑就必须是加的逻辑,但这一点没有强制性,因为这不是语法的错误,编译器不会强行报错。需要自行规范。

4.这一点会在下面提到。

5. .*   ::   sizeof   ?:   .  这五个运算符强制不能重载,大家可能对于 .* 运算符比较陌生, .* 运算符并不是本篇章的重点,但为了大家能够记住这个运算符,小编写了一段代码并且配上了详细的注释让大家感受一下 .* 运算符的作用。提醒:对 .* 运算符不感兴趣的可以跳过,不会对后面内容的理解有任何影响

class Date //日期类
{
public:
	Date(int year = 1, int month = 1, int day = 1) //构造函数
	{
		_year = year;
		_month = month;
		_day = day;
	}

	void DatePrintf() //打印函数
	{
		cout << _year << _month << _day << endl;
	}

private:

	int _year; //年
	int _month; //月
	int _day; //日

};

typedef void(Date::* DP)();  //这里是给一个函数类型取了一个别名,别名是 DP ,类型是 void ()  日期类中的打印函数也是这个类型

int main()
{
	DP dp = &Date::DatePrintf; //把成员函数中打印函数的指针给  dp , 一般来说函数名就代表该函数的地址,但成员函数规定要加上取地址符号

	Date d; //实例化一个类 , 对象名为d

	(d .* dp)();  //调用d对象的打印函数

	return 0;
}

上述代码中提到了构造函数,小编专门写了一篇构造函数的文章   对构造函数不是很理解的可以看一下,上述代码运行的结果是打印三个一,如下图:【C++】详解运算符重载,赋值运算符重载,++运算符重载,C++,前端,javascript,c++,开发语言,c语言

运算符重载成全局性的弊端

的数据一般是私有的,运算符重载是函数的一种,而全局性的函数是不可以访问类的私有数据的。如下图:【C++】详解运算符重载,赋值运算符重载,++运算符重载,C++,前端,javascript,c++,开发语言,c语言

难道我们要为了运算符重载要把中的数据设为共有吗,那的封装性如何保证呢?本篇给出的解决方案是把运算符重载函数定义为成员函数,意思是直接定义在类中。如下代码

class Date //日期类
{
public:
	Date(int year = 1, int month = 1, int day = 1) //构造函数
	{
		_year = year;
		_month = month;
		_day = day;
	}

	bool operator==(const Date& d2)  //运算符重载函数,一个参数是this ,一个是 const Date&
	{
		return _year == d2._year

			&& _month == d2._month 

			&& _day == d2._day;
	}
private:

	int _year; //年
	int _month; //月
	int _day; //日

};

中隐含的this指针

如果把运算符重载函数定义成员函数会少定义一个参数,但并没有真的少了一个参数,有一个隐含的this指针作为了该函数的第一个参数。如下图:

【C++】详解运算符重载,赋值运算符重载,++运算符重载,C++,前端,javascript,c++,开发语言,c语言

this是类型的隐含参数,如果运算符重载函数定义再了里面,这个参数就可以省去不写。



赋值运算符重载

下面的内容涉及到拷贝构造函数,对拷贝构造函数的理解比较模糊的可以参考一下小编写的详解拷贝构造一文     。

赋值运算符重载格式

参数类型:类类型的引用

返回值:可传值返回,可传引用返回,传引用返回比传值返回效率要高,后面会细讲。

代码示例

Date& operator=(const Date& d) //日期类的赋值运算符的重载的定义
 {
            _year = d._year;
            _month = d._month;
            _day = d._day;
       }


在这里先定义一个日期类,下面讨论的知识点都会用到这个日期类,大家先看一下代码

class Date  //日期类
{
public:
	Date(int year = 1, 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;
	}

	void operator=(const Date& d)  //赋值运算符重载
	{
			_year = d._year;
			_month = d._month;
			_day = d._day;

	}
private:
		int _year;
	int _month;
	int _day;
};

注意点

赋值运算符能再类中重载。因为赋值运算符重载函数是类的默认成员函数,如果重载成全局函数,编译器会为类自动生成默认赋值运算符重载函数,此时就会和全局的冲突。

明晰赋值运算符重载函数的调用

大家能分清下面的调用吗

int main()
{
	Date d; //实例化d

	Date d1(d);  //示例化d1,并把d的值拷贝给d1

	Date d2 = d;  //示例化d2,并把d的值拷贝给d2

	Date d3;  //实例化d3

	d3 = d;  //把d的值赋值给d3


}

画图演示其调用

【C++】详解运算符重载,赋值运算符重载,++运算符重载,C++,前端,javascript,c++,开发语言,c语言

连续赋值

上述代码中的赋值重载函数随是否能实现连续赋值呢?答案是不能。因为该函数只能完成赋值工作,并不会再把类的数据返回。代码改进

Date operator=(const Date& d)  //赋值运算符重载
{

		_year = d._year;
		_month = d._month;
		_day = d._day;
	
	return *this;  //返回被赋值的形参的数据
}

传引用与传值返回

上述代码中传的是的值,由于中封装了许多数据,想要把的数据传回去,需要调用该的拷贝构造函数,我们可以打印一下拷贝构造函数来观察一下,如下图【C++】详解运算符重载,赋值运算符重载,++运算符重载,C++,前端,javascript,c++,开发语言,c语言

调用拷贝构造函数拷贝数据的消耗是很大的,如果传引用返回能不能减少拷贝呢,如下图【C++】详解运算符重载,赋值运算符重载,++运算符重载,C++,前端,javascript,c++,开发语言,c语言

结果很明确,传引用返回并没有调用拷贝构造函数,这说明传引用返回比传值返回效率更高,只要该类出了作用域不会销毁,都可以传引用返回

如果我要自己给自己赋值会怎么样呢,这是没必要的,可以再改进一下代码

Date& operator=(const Date& d)  //赋值运算符重载
{
	if (this != &d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

	return *this;
}

默认赋值运算符重载

用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。内置类型成员变量是直接赋值的,而自定义类型成员变量需要 调用对应类的赋值运算符重载完成赋值。
我将用如下代码为大家讲解默认运算符重载函数的浅拷贝的弊端
class Date //日期类
{
public:

	Date() //构造函数
	{
		_year = 1;
		_month = 1;
		_day = 1;

		_a = (int*)malloc(sizeof(int) * 7); //为a开辟空间
		for (int i = 0; i < 7; i++)
		{
			_a[i] = 0;
		}
	}


private:
	int _year; //年
	int _month; //月
	int _day;  //日
	int* _a;  //指向一块空间
};
int main()
{
	Date d; //实例化对象d
	Date d1; //实例化对象d1

	d = d1; //把对象d1的数据赋值给对象d
}

下面是代码调试示意图【C++】详解运算符重载,赋值运算符重载,++运算符重载,C++,前端,javascript,c++,开发语言,c语言

下面是逻辑示意图 【C++】详解运算符重载,赋值运算符重载,++运算符重载,C++,前端,javascript,c++,开发语言,c语言
对象d的_a不再指向原有空间,使原有空间丢失,造成内存泄漏。 如果类中未涉及到资源管理,赋值运算符是否实现都可以;一旦涉及到资源管理则必 须要实现


前置++和后置++重载

Date& operator++() //日期的前置++
{
	_day += 1;
	return *this;
}

	Date operator++(int) //日期类的后置++
{
	Date temp(*this);
	_day += 1;
	return temp;
}
 C++规定:  前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载,后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器
自动传递。


想为大家推荐 aMereNobody 大佬写的文章    

本篇的内容到此结束啦文章来源地址https://www.toymoban.com/news/detail-857240.html

到了这里,关于【C++】详解运算符重载,赋值运算符重载,++运算符重载的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++拷贝构造函数与赋值运算符重载

    顾得泉: 个人主页 个人专栏: 《Linux操作系统》 《C++从入门到精通》  《LeedCode刷题》 键盘敲烂,年薪百万!        在现实生活中,可能存在一个与你一样的自己,我们称其为双胞胎。        那在创建对象时,可否创建一个与已存在对象一某一样的新对象呢?  

    2024年02月22日
    浏览(22)
  • C++修炼之筑基期第四层 ——透过日期类看运算符重载 | 赋值运算符重载 | 取地址操作符重载

    🌸作者简介: 花想云 ,在读本科生一枚,致力于 C/C++、Linux 学习。 🌸 本文收录于 C++系列 ,本专栏主要内容为 C++ 初阶、C++ 进阶、STL 详解等,专为大学生打造全套 C++ 学习教程,持续更新! 🌸 相关专栏推荐: C语言初阶系列 、 C语言进阶系列 、 数据结构与算法 本章主要

    2023年04月09日
    浏览(53)
  • 【C++】类和对象(中)---拷贝构造函数、赋值运算符重载

    个人主页:平行线也会相交💪 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创 收录于专栏【C++之路】💌 本专栏旨在记录C++的学习路线,望对大家有所帮助🙇‍ 希望我们一起努力、成长,共同进步。🍓 拷贝构造函数,又称复制构造函数,是一种特殊的

    2024年02月05日
    浏览(17)
  • 【C++】:类和对象(中)之拷贝构造函数+赋值运算符重载

    在现实生活中,可能存在一个与你一样的自己,我们称其为双胞胎 那在创建对象时,可否创建一个与已存在对象一某一样的新对象呢? 拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调

    2024年02月06日
    浏览(19)
  • C++ -3- 类和对象 (中) | 拷贝构造函数 & 赋值运算符重载

    示例: 拷贝初始化构造函数的作用是将一个已知对象的数据成员值拷贝给正在创建的另一个同类的对象 无穷递归 ? Date(Date d){……} 首先,分析 传值传参的过程 传引用传参 : 没有拷贝 的过程,直接传 传值传参: 内置类型 编译器可以直接拷贝(浅拷贝/值拷贝——一个字节

    2023年04月19日
    浏览(54)
  • c++类与对象(二)——赋值运算符重载与取地址操作符重载

    前言: 本章将通过 日期类 的实现,深入学习 运算符重载 的实现方法。本章将完成6个默认成员函数中剩余3个—— 赋值运算符重载 与 取地址操作符重载 的学习。 C++ 为了增强代码的可读性引入了 运算符重载 ,运算符重载是具有 特殊函数名 的函数,也具有其返回值类型,

    2024年02月03日
    浏览(17)
  • 【C++】C++入门—初识构造函数 , 析构函数,拷贝构造函数,赋值运算符重载

    如果一个类中什么成员都没有,简称为空类。 空类中真的什么都没有吗? 并不是 任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。 默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数 我们实现了,编译器就不会生成了 构造函数是

    2024年02月21日
    浏览(21)
  • 探索C++赋值运算符重载的内部机制:手把手教你精通

    W...Y的主页 😊 代码仓库分享💕  🍔前言: 前一篇博客中我们已经了解并学习了初始化和清理模块中的构造函数与析构函数,还有拷贝复制中的拷贝复制函数,它们都是类与对象中重要的成员,今天我们要来讲一下拷贝复制模块中另一个非常重要的内容——赋值重载,但是

    2024年02月08日
    浏览(20)
  • C++从入门到精通——类的6个默认成员函数之赋值运算符重载

    类的6个默认成员函数:如果一个类中什么成员都没有,简称为空类。 空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。 默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。 C++为了增强代码的

    2024年04月25日
    浏览(16)
  • 【C++初阶】类与对象:6大默认成员函数------拷贝构造和赋值运算符重载

      拷贝构造函数: 只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰) ,在用已存在的类类型对象创建新对象时由编译器自动调用。 1. 拷贝构造函数是 构造函数的一个重载形式 ; 2. 拷贝构造函数的 参数只有一个且必须是类类型对象的引用 ,使用传值方式编

    2024年02月03日
    浏览(20)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包