首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【C++】类和对象之常引用与运算符重载

【C++】类和对象之常引用与运算符重载

作者头像
zxctscl
发布2024-02-29 09:50:45
发布2024-02-29 09:50:45
3380
举报
文章被收录于专栏:zxctscl个人专栏zxctscl个人专栏

1. 前言

在之前的文章中提到了常引用,再来看运算符重载之前,先来看看常引用的使用。

2. 常引用

在使用引用的时候可能会出现一些问题,例如:b是a的别名,b++,那么a肯定也加加了,但有时我们也不希望这样。

如果不希望a传过去改变,那么就得加上const

那么这里就能使用const加引用。

这里用到常引用,c是a的别名,但是不能修改,也就是不能通过c修改a。他是一种权限的缩小 。

这里要给x取别名,是不可以的。 因为这里权限放大,这里x是只读的,但y是x别名之后却可读可写,这是不能的。 所以加上const就可以了。

取别名不能放大权限。 权限缩小是可以的,但是权限放大是不行的。

像下面这种也是可以的。 z是常量的别名了。

还可以有这样的。

但是像下面这样就不行,因为临时变量具有常性,不能被修改。 这里是权限的放大,a+x表达式的返回值是临时对象。

如果不用const引用,如果这里传了a,那么后面的10就不能传过去,后面的表达式也不能传过去。 所以建议引用传const。

得注意:权限可以缩小,权限可以平移,但权限不能放大。

这里d可以给i,因为隐式类型转换。 但传引用就不行,因为类型不同。

但是加了const就行,为什么呢? 因为类型转换中间会有临时变量。

这里严格来说不是把d给i,然后d构造的临时变量拷贝给i。 下面的引用也是一样的,是把d拷贝给临时变量,ri是这个临时变量的别名,因为临时变量具有常性,所以用常引用。

那么为什么要产生临时变量呢?

这里i和ch比较为什么会相等? 因为i和ch不能直接去比较,在操作符两边的操作数类型不一样时,会有类型提升或截断。 这里是不能把ch扩到4个字节,所以这里会产生一个临时变量,ch不会变,变的是ch会产生的有4个字节的临时变量,4个字节把ch的值拿过去以后,按类型提升的规则,最高位也就是符号位,往上补0。a的ascii码值是97,97的最高位是0,往上补,补成4个字节,还是97。所以这里的i不是和ch比较的,而是和那个临时变量比较的。

3. 运算符重载

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

像下面代码,要比较两个日期,不能直接比较。 内置类型就可以,是语言定义的。 自定义类型是多个类型的组合,编译器不知道怎么比较,所以不支持,需要自己来定义。

代码语言:javascript
复制
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 DateCompare(const Date& x, const Date& y)
{
	return x._year == y._year
		&& x._month == y._month
		&& x._day == y._day;

}

int main()
{
	Date d1(2024, 1, 1);
	Date d2(2024, 2, 27);
	cout << DateCompare(d1, d2) << endl;

如果是比较大小,像下面这样是肯定不行的,不是某一个小就小。

那么该这样写,得先比较年,年小就小,年相同后再是月,月小就小,月再相同才比较天。

代码语言:javascript
复制
bool DateCompare2(const Date& x, const Date& y)
{

	if (x._year < y._year)
	{
		return true;
	}
	else if (x._year == y._year)
	{
		if (x._month < y._month)
		{
			return true;
		}
		else if (x._month == y._month)
		{
			return x._day < y._day;
		}
	}

	return false;
}

所以自定义类型的比较得实现函数,如果函数名乱取的话,就很难判断它是用来干啥的。 为了避免这样就有了运算符重载。

函数名字为:关键字operator后面接需要重载的运算符符号。 这里的重载是指对运算符的重新定义,按照用户的需求去控制。

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

代码语言:javascript
复制
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& x, const Date& y)
{
	return x._year == y._year
		&& x._month == y._month
		&& x._day == y._day;
}


bool operator<(const Date& x, const Date& y)
{
	if (x._year < x._year)
	{
		return true;
	}
	else if (x._year == x._year)
	{
		if (x._month < y._month)
		{
			return true;
		}
		else if (x._month == y._month)
		{
			return x._day < y._day;
		}
	}

	return false;
}

int main()
{
	Date d1(2024, 1, 1);
	Date d2(2024, 2, 27);


	cout << operator==(d1, d2) << endl;
	cout << operator<(d1, d2) << endl;
    
    cout << (operator==(d1, d2)) << endl;

	cout << (d1 < d2) << endl;
	return 0;
}

但不仅仅是这样,还有可以直接用

出现这样的情况是因为<<的优先级比==的高,加上括号就行。

为什么这里实现结果是一样的呢? 因为编译器会给去调用对应的函数。 但是在实践中私有变量肯定不是像上面代码一样。在类外面是不能访问的,那怎么办呢? 类外面不能服务,那么就放到类里面。 但不要忘记,类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this。

代码语言:javascript
复制
class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	bool operator==(const Date& y)
	{
		return _year == y._year
			&& _month == y._month
			&& _day == y._day;
	}

	bool operator<(const Date& y)
	{
		if (_year < y._year)
		{
			return true;
		}
		else if (_year == y._year)
		{
			if (_month < y._month)
			{
				return true;
			}
			else if (_month == y._month)
			{
				return _day < y._day;
			}
		}

		return false;
	}

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


int main()
{
	Date d1(2024, 1, 1);
	Date d2(2024, 2, 27);
	cout << d1.operator==(d2) << endl;
	cout << d1.operator<(d2) << endl;

	cout << (d1 == d2) << endl; 
	cout << (d1 < d2) << endl;  

	return 0;
}

如果是内置类型去比较,直接转化成指令

注意:

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

有问题请指出,大家一起进步!!!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-02-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 前言
  • 2. 常引用
  • 3. 运算符重载
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档