C++类和对象(下)

运算符重载

赋值运算符重载是⼀个默认成员函数,用于完成两个已经存在的对象直接的拷贝赋值 ,拷贝构造用于⼀个对象拷贝初始化给另⼀个要创建的对象

如何定以运算符重载

返回类 operator 定义的运算符(参数列表)

补充点:如果⼀个重载运算符函数是成员函数,则它的第⼀个运算对象默认传给隐式的this指针,因此运算 符重载作为成员函数时,参数比运算对象少⼀个。

什么时候运用运算符重载

当调用内置类型时候可以通过简单的比较可以进行处理,但是用于自定以类型时,C++规定类类型对象使用运算符时,必须转换成调用对应运算符重载。
简单内置类型

赋值运算符实现的便利性

赋值运算重载有返回值,可以写成当前类类型引用,引用返回可以提高效率,有返回值支持连续赋值场景。

如下面日期类案例:如果按照以比较两个日期是否相同中的普通方法是逐一进行比较,不利于代码的复用性。

cpp 复制代码
// >=运算符重载
bool Date::operator >= (const Date& d) {
	return *this > d || *this == d;
}

不能重载的五个运算符

.* :: sizeof ? : .

赋值运算符的+与+=区别

+这种情况是获得当前的值而加等是获得加后的值,两者的区别也是体现*this指针改变不改变,+的时候并不改变,因此要先用拷贝构造,构造一个和*this一样的对象,而后者就是直接在this上进行修改。

实现+复用+=的优点

Date Date::operator+(int day) {

Date temp = *this;

temp += day;

return temp;

}

存在用+复用+=,也存在+=复用+,但是两者只能在调用时调用其一,+复用+=具有节省时间,效率较高的优点,因为在复用+=时,并不用进行拷贝构造,大大提高了效率。

赋值运算符实现前置加

Date& Date::operator++() {

*this += 1;

return *this;

}

赋值运算符实现后置加

// 后置++

Date Date::operator++(int) {

Date tmp(*this);

*this += 1;

return tmp;

}

tmp在调用结束后就释放了,因此返回的是处理前的值,注意调用时传入的时int类型的变量。

友员类

friend+函数就可以进行变成友员类了

简单来说,友员类就是比如说你有一个好兄弟卖了一个黑神话的游戏你没有,但是你想玩,这会你好兄弟就说我们是好兄弟我的就是你的,拿去玩吧。友员类就是将其他类或函数声明为友元,从而使得这些友元类或函数可以访问该类的私有成员。

流插入流提取

流插入和流提取的参数类型

为什么<<不能重载成员函数

根据重载的规定,如 cout<<d1这样的二元操作符,左侧会传给第一个形参,右侧传递第二个形参,这样就会造成默认的*this指针和cout的返回类型ostream不匹配。因为第一个的默认是*this,有同学就会想到,两个参数互换一下,这种想法其实是不合理的。正确的解决方案是重载成全局函数,全局函数时就没有默认的*this,就可以根据顺序进行设置形参,这里也存在一个问题,重载写在了全局,函数内部是无法调用私有成员变量,因此这里引入了友员函数

注意:

流提取的时候不要使用const进行限制,因为是要向里面写入数据,因此不能进行限制。

当进行多次流插入或者流提取的时候,一定要牢记,让它返回它自己参数类型。

日期类源码

Data.h

cpp 复制代码
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
class Date
{
public:
	Date(int year = 2024, int month = 9, int day = 6) {
		_year = year;
		_month = month;
		_day = day;
	}
	//判断日期的合法性
	bool check() {
		if ((_month < 1 || _month>12) || (_day < 1 || GetMonthDay(_year, _month)))
		{
			return false;
		}
		else
		{
			return true;
		}
	}
	// 获取某年某月的天数
	int GetMonthDay(int year, int month)
	{
		assert(month > 0 && month < 13);
		static int arr[] = { -1,31,28,31,30,31,30,31,31,30,31,30,31 };
		if (month==2 && (year % 4 == 0 && year % 100 != 0) && (year % 400 == 0))
		{
			return arr[month] = 29;
		}
		return arr[month];
	}

	void print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

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

	// 日期+=天数
	Date& operator+=(int day);

	// 日期+天数
	Date operator+(int day);

	// 日期-天数
	Date operator-(int day);

	// 日期-=天数
	Date& operator-=(int day);

	// 前置++
	Date& operator++();

	// 后置++
	Date operator++(int);

	// >运算符重载
	bool operator>(const Date& d);

	// ==运算符重载
	bool operator==(const Date& d);

	// >=运算符重载
	bool operator >= (const Date& d);

	// !=运算符重载
	bool operator != (const Date& d);

	// 日期-日期 返回天数
	int operator-(const Date& d);
private:
	int _year;
	int _month;
	int _day;
};

Data.c

cpp 复制代码
#include"Data.h"
bool Date::operator>(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;
	}
	return false;
}

// ==运算符重载
bool Date::operator==(const Date& d) {
	if (_year == d._year && _month == d._month && _day == d._day)
	{
		return true;
	}
	else
		return false;
}

// >=运算符重载
bool Date::operator >= (const Date& d) {
	return *this > d || *this == d;
}
// !=运算符重载
bool Date::operator != (const Date& d) {
	return !(*this == d);

}
//赋值
Date& Date::operator=(const Date& d) {
	if (this != &d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	return *this;
}

// 日期-=天数

Date& Date::operator+=(int day) {
	//
	if (day < 0)
	{
		return *this-=-day;
	}
	_day += day;
	while (_day>GetMonthDay(_year,_month))
	{
		//找对应的天数
		_day -= GetMonthDay(_year, _month);
		++_month;
		if (_month > 12)
		{
			_year++;
			_month = 1;
		}
	}
	return *this;
}

// 日期+=天数
Date Date::operator+(int day) {
	Date temp = *this;
	temp += day;
	return temp;
}

// 日期-天数
Date Date::operator-(int day) {
	Date tmp(*this);
	tmp -= day;
	return tmp;

}

// 日期-=天数
Date& Date::operator-=(int day) {
	if (day < 0)
	{
		return *this += -day;
	}

	_day -= day;
	while (_day <= 0)
	{
		--_month;
		if (_month == 0)
		{
			_month = 12;
			--_year;
		}

		_day += GetMonthDay(_year, _month);
	}

	return *this;

}

// 前置++
Date& Date::operator++() {
	*this += 1;
	return *this;
}

// 后置++
Date Date::operator++(int) {
	Date tmp(*this);
	*this += 1;
	return tmp;
}

// 日期-日期 返回天数
int Date::operator - (const Date& d) {

	Date max = *this;
	Date min = d;
	int flag = 1;
	if(*this < d)
	{
		max = d;
		min = *this;
		flag = -1;
	}

	int n = 0;
	while (min != max)
	{
		++min;
		++n;
	}

	return n * flag;
}
相关推荐
此生只爱蛋4 分钟前
【手撕排序2】快速排序
c语言·c++·算法·排序算法
blammmp11 分钟前
Java:数据结构-枚举
java·开发语言·数据结构
何曾参静谧24 分钟前
「C/C++」C/C++ 指针篇 之 指针运算
c语言·开发语言·c++
暗黑起源喵30 分钟前
设计模式-工厂设计模式
java·开发语言·设计模式
WaaTong34 分钟前
Java反射
java·开发语言·反射
Troc_wangpeng36 分钟前
R language 关于二维平面直角坐标系的制作
开发语言·机器学习
努力的家伙是不讨厌的37 分钟前
解析json导出csv或者直接入库
开发语言·python·json
Envyᥫᩣ1 小时前
C#语言:从入门到精通
开发语言·c#
童先生1 小时前
Go 项目中实现类似 Java Shiro 的权限控制中间件?
开发语言·go
lulu_gh_yu1 小时前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法