赋值运算符重载,取地址及const取地址操作符重载

news2024/11/13 3:33:27

赋值运算符重载

  • 1.运算符重载
  • 2.赋值运算符重载
  • 3.取地址及const取地址操作符重载

如果一个类中什么成员都没有,那么该类简称为空类。而空类中其实并不是真的什么都没有,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。

  • 构造函数:主要完成初始化工作
  • 析构函数:主要完成资源的清理工作
  • 拷贝构造函数:主要用于使用同类对象初始化创建对象
  • 赋值运算符重载:主要是把一个对象赋值给另一个对象
  • 普通对象取地址重载
  • const对象取地址重载(取地址重载很少会自己实现)

本篇文章,我们来学习赋值运算符重载,顺便简单了解一下普通取地址重载和const取地址重载。

1.运算符重载

概念:

对于内置类型而言,可以直接使用各种运算符,对于自定义类型而言,不能直接使用各种运算符,我们需要使用运算符重载来使自定义类型可以直接使用各种运算符,为此C++ 引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

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

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

特性:

  • 不能通过连接其他符号来创建新的操作符:比如operator@
  • 重载的运算符不必是成员函数,但必须有一个自定义类型参数
  • 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
  • 当一个运算符是双操作数的时候,第1个参数是左操作数,第2个参数是右操作数。
  • 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this指针,指向调用对象。非成员版本的重载运算符函数所需的形参数目与运算符使用的操作数数目相同。
  • 运算符重载是一种函数,运算符有几个操作数,相应地函数就有几个参数,返回值是运算符运算后的结果。
  • operator+()函数的名称使得可以使用函数表示法或者运算符表示法来调用它,当自定义类型对象使用运算符运算时,编译器会使用相应的运算符函数替换运算符。运算符左侧的对象是调用对象,运算符右边的对象是作为参数被传递的对象。
  • .*、. 、 ::、 sizeof、 ?: 注意这5个运算符不能重载。这个经常在笔试选择题中出现。
  • 大多数运算符都可以通过成员或非成员函数进行重载,但这4个运算符只能通过成员函数进行重载,分别是赋值运算符=、函数调用运算符()、下标运算符[]、通过指针访问类成员的运算符->
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;
};
// 这里会发现运算符重载成全局的就需要成员变量是公有的,那么问题来了,封装性如何保证?
// 这里其实可以用我们后面学习的友元解决,或者干脆重载成成员函数。
bool operator==(const Date& d1, const Date& d2)
{
	return d1._year == d2._year
		&& d1._month == d2._month
		&& d1._day == d2._day;
}
void Test()
{
	Date d1(2018, 9, 26);
	Date d2(2018, 9, 27);
	cout << (d1 == d2) << endl;
}

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;
	}
	Date& operator+(const Date& d) const
	{
		this->year+=d.year;
		this->month+=d.month;
		this->day+=d.day;
        
        return *this;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1(1999,2,4);
	Date d2(199,4,5);
	d1+d2;//实际上是d1.operate+(d2);
	return 0;
}

重载运算符作为成员函数还是非成员函数?

对于很多运算符来说,可以选择使用成员函数或者非成员函数来实现运算符重载,一般来说,非成员函数应该是友元函数,这样它才能直接访问类的私有数据,但如果是将对象当成一个整体使用而无需访问其中的私有成员,那么非成员函数也无需是友元函数。

加法运算符需要两个操作数,对于成员函数版本来说,一个操作数通过this指针隐式地传递,另一个操作数作为函数参数显示地传递;对于友元版本来说,两个操作数都作为参数来传递。

在定义运算符时,必须选择其中的一种格式,而不能同时选择这两种格式。因为这两种格式都与同一个表达式匹配,同时定义这两种格式将被视为二义性错误,导致编译错误。

2.赋值运算符重载

参数类型: const T&,传递引用可以提高传参效率
返回值类型: T&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值,返回*this :要符合连续赋值的含义。

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)
	{
	//检测是否自己给自己赋值。
		if (this != &d)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}
private:
	int _year;
	int _month;
	int _day;
};

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

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	int _year;
	int _month;
	int _day;
};
// 赋值运算符重载成全局函数,注意重载成全局函数时没有this指针了,需要给两个参数
Date& operator=(Date& left, const Date& right)
{
	if (&left != &right)
	{
		left._year = right._year;
		left._month = right._month;
		left._day = right._day;
	}
	return left;
}
// 编译失败:
// error C2801: “operator =”必须是非静态成员

原因:赋值运算符重载如果不在类中作为成员函数显式实现,编译器会生成一个默认的。此时用户再在类外自己实现一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,故赋值运算符重载只能是类的成员函数。

在这里插入图片描述

用户没有显式实现时,编译器会生成一个默认的赋值运算符重载,默认的赋值运算符重载属于浅拷贝,对内置类型成员变量以值的方式逐字节拷贝。而对自定义类型成员变量需要调用对应类的赋值运算符重载完成赋值。

既然编译器生成的默认赋值运算符重载函数已经可以完成字节序的值拷贝了,还需要自己实现吗?当然像日期类这样的类是没必要的。那么下面的类呢?验证一下试试?

typedef int DataType;
class Stack
{
public:
	Stack(size_t capacity = 10)
	{
		DataType* _array = (DataType*)malloc(capacity * sizeof(DataType));
		if (nullptr == _array)
		{
			perror("malloc申请空间失败");
			return;
		}
		_size = 0;
		_capacity = capacity;
	}
	void Push(const DataType& data)
	{
		// CheckCapacity();
		_array[_size] = data;
		_size++;
	}
	~Stack()
	{
		if (_array)
		{
			free(_array);
			_array = nullptr;
			_capacity = 0;
			_size = 0;
		}
	}
private:
	DataType* _array;
	size_t _size;
	size_t _capacity;
};
int main()
{
	Stack s1;
	s1.Push(1);
	s1.Push(2);
	s1.Push(3);
	s1.Push(4);
	Stack s2;
	s2 = s1;
	return 0;
}

在这里插入图片描述

因此和拷贝构造函数一样,当对象中涉及对资源的申请时,我们需要自己实现赋值运算符来完成深拷贝。

3.取地址及const取地址操作符重载

这两个默认成员函数一般不用重新定义 ,编译器默认会生成。

class Date
{
public:
	Date* operator&()
	{
		return this;
	}
	const Date* operator&()const
	{
		return this;
	}
private:
	int _year; // 年
	int _month; // 月
	int _day; // 日
};

这两个运算符一般不需要重载,使用编译器生成的默认的取地址重载即可,只有特殊情况,才需要重载,比如想让别人获取到指定的内容!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/23470.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

同花顺_代码解析_技术指标_V,W

本文通过对同花顺中现成代码进行解析&#xff0c;用以了解同花顺相关策略设计的思想 目录 V&R VMA VMACD VOSC VPT VR VRFS VRSI VSTD W&R WVAD V&R 波动区间 用来衡量该股的市场波动风险.即95%的概率波动区间. 行号 1 n -> 250 2 x -> 收…

【考研英语语法】状语从句精讲

一、状语从句概述 &#xff08;一&#xff09;状语从句的含义 状语从句&#xff0c;指的就是一个句子作状语&#xff0c;表达“描述性的信息”&#xff0c;补充说明另一个句子&#xff08;主句&#xff09;。描述性的信息有很多种&#xff0c;可以描述时间、地点、原因、结果…

Web大学生网页成品HTML+CSS音乐吧 7页

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 音乐网页设计 | 仿网易云音乐 | 各大音乐官网网页 | 明星音乐演唱会主题 | 爵士乐音乐 | 民族音乐 | 等网站的设计与制作 | HTML期末大学生网页设计作…

Django开发笔记

Django开发笔记Django学习1. Django安装path()函数2. 创建项目2.1 终端命令创建2.2 pycharm创建项目3. App4. 创建页面4.1 再写一个页面4.2 模板---Templates4.3 静态文件4.3.1 创建static目录4.3.2 静态文件的引用5. 模板语法案例&#xff1a;伪联通新闻中心6. 请求和响应案例…

KT148A语音芯片按键版本一对一触发播放常见的问题集锦FAQ_V4

1.1 有3个IO&#xff0c;都是一样的功能吗&#xff1f;从配置文件的说明来看&#xff0c;功能是键控发声&#xff0c;那么3个IO都只能是键控发声吗&#xff1f;还是可以有选择地某个IO对应播放那段语音&#xff1f;三个按键有什么区别&#xff1f;他们和语音号是如何对应的&…

[附源码]java毕业设计校园环境保护监督系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

SpringBoot SpringBoot 开发实用篇 5 整合第三方技术 5.7 memcached 下载与安装

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 开发实用篇 文章目录SpringBootSpringBoot 开发实用篇5 整合第三方技术5.7 memcached 下载与安装5.7.1 memcached 下载5.7.…

基于Web的个人网页响应式页面设计与实现 HTML+CSS+JavaScript(web前端网页制作课作业)

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

裁员潮血洗硅谷,推特、Meta、亚麻都扛不住了!

据纽约时报14日报道&#xff0c;亚马逊计划最早于本周开启大规模裁员&#xff0c;上万名员工将被波及&#xff0c;Alexa、零售和人力部门将是重灾区。 在亚马逊员工人人自危的情况下&#xff0c;新的噩梦才刚刚开始&#xff0c;因为&#xff0c;这不过是硅谷裁员潮的冰山一角……

36、Java——一个案例学会三层架构对数据表的增删改查

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;Java案例分…

Spring Security(1)

您好&#xff0c;我是湘王&#xff0c;这是我的CSDN博客&#xff0c;欢迎您来&#xff0c;欢迎您再来&#xff5e; 虽然说互联网是一个非常开发、几乎没有边界的信息大海&#xff0c;但说起来有点奇怪的是&#xff0c;每个稍微有点规模的互联网应用都有自己的权限系统&#xff…

BSV 上的 PLONK

我们很自豪地宣布 BSV 现在支持 PLONK。关于 PLONK 工作原理的详细说明&#xff0c;可以参考我们之前的解释 第一部分 和 第二部分。 我们之前已经实现了 Groth16&#xff0c;这是最小且最高效的 SNARK 构造。但是&#xff0c;它需要为每个电路进行可信设置。通过消除对每条电…

算法工程师应该熟知的C++高级用法

1. lambda表达式&#xff08;C11&#xff09; 1.1 lambda表达式的组成 []/*1*/ ()/*2*/ mutable/*3*/ throw()/*4*/ -> int/*5*/ {}/*6*/capture子句参数列表(optional)可变规范(optional)异常定义(optional)返回类型(optional)函数体 1.2 即看即用 语法&#xff1a; […

我现在是如何听歌的?

个人听歌需求 首先讲下个人听歌的情况&#xff0c;再讲讲我是怎么解决自己的听歌需求的&#xff0c;不一定适合所有人&#xff0c;但多少有点启发。我个人听歌的特殊需求其实还蛮多的。 比如&#xff1a; 突然会想单曲循环一首歌&#xff0c;直到耳朵说够了。 喜欢组装各种歌…

小啊呜产品读书笔记001:《邱岳的产品手记-06》第13讲 无用却必要:产品规划【上】 第14讲 留白与节奏:产品规划【下】

小啊呜产品读书笔记001&#xff1a;《邱岳的产品手记-06》第13讲 无用却必要&#xff1a;产品规划【上】 & 第14讲 留白与节奏&#xff1a;产品规划【下】一、今日阅读计划二、泛读&知识摘录1、第13讲 无用却必要&#xff1a;产品规划【上】2、第14讲 留白与节奏&#…

数据中心网络是什么?如何管理数据中心网络

什么是数据中心网络 数据中心网络是提供网络、存储和计算资源&#xff0c;为企业/企业数据中心租户执行广泛的工作负载。这些工作负载需要不同的硬件或高端网络组件来计算、存储、检索和传输来自本地和广域网的工作负载中的数据。 数据中心网络的核心支柱 在数据中心网络架构…

【第四部分 | JavaScript 基础】2:运算、控制流程、数组

目录 | 运算符 概述 浮点数有精度误差 自增和自减 比较运算符 逻辑运算符 赋值运算符 运算优先级 | 流程控制 条件判断 if、if...else 三元表达式 分支语句 switch | 循环 | 断点调试 | 数组 创建数组 访问与遍历 获取数组长度 JavaScript的数组 和 Java 的区…

LabVIEW项目中实时目标出现黄色感叹号

LabVIEW项目中实时目标出现黄色感叹号 当打开一个包含实时目标的LabVIEW项目&#xff08;如CompactRIO&#xff08;cRIO&#xff09;、CompactDAQ&#xff08;cDAQ&#xff09;或实时PXI&#xff09;时&#xff0c;在目标旁边看到一个黄色感叹号。单击目标时&#xff0c;收到以…

目标检测论文解读复现之十四:一种基于残差网络优化的航拍小目标检测算法

前言 此前出了目标改进算法专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读最新目标检测算法论文&#xff0…

代码随想录算法训练营第六天|字符串 栈 队列

字符串 字符串是我的弱点&#xff0c;主要是函数用的不是很熟练 注意因为字符串是左闭右开区间&#xff0c;而且字符串末尾还有一个"/0"&#xff0c;所以我们在reverse的时候是 [s.begin(),s.begin() len] 其中len是string的长度&#xff0c;假如string的长度是6…