类与对象(三)---运算符重载

开头:

      在类与对象(二)————构造与析构函数-CSDN博客中我们介绍了默认成员函数六个里的前三个,了解过它们的功能并能写出符合我们要求的各式函数包括构造、析构、拷贝构造。本篇继续认识默认成员函数。

 在从C语言到C++-CSDN博客中我们介绍过函数重载(遗忘的建议看一下),允许在C++中使用同名函数来提高代码灵活度,与今天我们要介绍的运算符重载无关,因为运算符重载的目的是改变运算符对自定义类型的行为。

已知运算符对内置类型的操作(如加减乘除比较大小),那怎么才能让自定义类型也能实现这些操作呢?实现的过程就叫运算符重载

运算符重载:

特点:

   1. 参数个数:与运算符的操作对象一样多,如果作为成员函数,第一个参数默认是*this(隐式),参数就少一个。

   2.至少有一个自定义类型使用了该运算符,才会调用该运算符重载,而且自动调用。

   3. "  "     "   .*  "     "  ::  "     "   sizeof "    "   ?  "  五个运算符不能重载。

   4.要求重载后要求运算符与原运算符的优先级、结合性相同。

   5.每一次出现自定义类型和该运算符都会调用重载函数。

eg:(仍以日期类实现

// 获取某年某月的天数
inline int GetMonthDay(int year, int month)
{
	static int monthday[13] = { -1,31,28,31,30,31,30,31,31,30,31,30,31 };
	if (((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)&&month==2)
		return 29; 
	else
		return monthday[month];
}

该函数用于获取某年某月的天数,接下来会频繁使用,所以写成inline内联函数。

重载+=运算符:

// 日期+=天数 改变原来的日期,得到的是新日期
Date& operator+=(int day)
{
	if (day < 0)     //考虑day的正负
	{
		return (*this -= (-day));
	}
	_day += day;
	while (_day > GetMonthDay(_year, _month))
	{
		_day -= GetMonthDay(_year, _month);
		++_month;
		if (_month==13)
		{
			++_year;
			_month = 1;
		}
	}
	return *this;
}

运行时:

这样一来+=可以对Date类的对象使用,我们可以再重载+运算符。

与+=不同的是+运算符不能改变对象本身。因此我们要运用到this指针来保证对象本身不被改变

(详见从C语言到C++-CSDN博客

// 日期+天数  不改变原来日期,就像i+10,不改变i一样 
Date operator+(int day)
{
	Date tmp = *this;
	tmp += day;
	return tmp;   
}

这样一来我们就可以重载+、+=、-、-=、给类的对象使用。

而判断两个对象的大小关系用到的> <  >= <= ==  !=

前置++  后置++的重载:

前置++  后置++(减减同理)相比以上的运算符重载更重要。

如果是前置++的话,先加1再返回使用该对象,相当于+=1

Date& operator++()
{
	*this += 1;
	return *this;
}

后置++相比于前置++,是应该先使用该对象,再+=1

Date operator++(int)
{
	Date tmp = *this;
	*this += 1;
	return tmp;
}

注意:  

     1.两者之间前置++返回的是Date型引用减少了拷贝复制,而后置++要返回的是临时对象tmp,临时对象函数结束被销毁,所以不能传引用返回。

     2.因为返回值类型不同不能作为函数重载的条件,所以为区别两函数,后置++函数参数多了一个int型参数,函数调用时正常使用即可,不需要传int参数

建议自己写一遍 前置-- 和 后置--,为方便读者将它们放在下面:

// 后置--
Date operator--(int)
{
	Date tmp = *this;
	*this -= 1;
	return tmp;
}
// 前置--
Date& operator--()
{
	*this -= 1;
	return *this;
}

流插入 流提取 运算符重载:

     在 C++ 中,<<>> 运算符也被称为流插入运算符和流提取运算符。它们是重载的运算符,这意味着它们的行为取决于它们的操作数的类型。对于流对象(如 std::coutstd::cin),这些运算符被重载为执行输入输出操作。(cout cin是 C++ 标准库中的两个流对象,cinistream 类型的对象,coutostream 类型的对象,它们做参数时,只能引用传参。)

因为cout / cin也是<< / >>的操作对象, <<  / >>重载时肯定不能写成成员函数,因为成员函数第一个参数默认是this指针,要将类的对象作为第二操作数。

还要能连续输出,就需要return cout

//重载<<
ostream& operator<<(ostream& out,const Date& d)
{
	out << d._year<<"/" << d._month << "/" << d._day << endl;
	return  out;
}
//重载>>
istream& operator>>(istream& in, Date& d) 
{
	cout << "请输入年月日:>" << endl; 
	in >> d._year >> d._month >> d._day;
	return  in;
}

赋值运算符重载:

定义:

     1.用两个已经存在的对象直接拷贝赋值,一定要与拷贝构造函数区别开

     2.特殊的运算符重载,规定必须是成员函数

也是要实现d1=d2=d3;(d1 d2 d3都是某类的对象),和拷贝构造函数不同的是d1 d2已经存在,而不是用d3初始化。

 实现:

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

很明显,赋值运算符重载 和 编译器自带的默认成员函数 也是浅拷贝,如果是Date类这种可以不写赋值运算符重载函数,一旦遇到stack类这种向内存申请空间的类,一定需要自己写,且需要深拷贝,具体与拷贝构造函数相似。

取地址运算符重载:

     这是我们讲的六个默认成员函数里的最后一个,也是最省力的一个成员函数。

     在这之前,我们要了解一下  const 

const:

在 C++ 中,`const` 关键字用于声明常量,它如下几种用途:

1. 修饰变量:当 const 修饰一个变量时,这个变量的值在初始化后就不能被改变。

2. 修饰函数参数:当 const 修饰函数参数时,表示该参数在函数内部不能被修改。这通常用于传递对象时,防止对象在函数内部被修改。

3. 修饰成员函数:当 const 修饰成员函数时,表示这个成员函数不会修改对象的状态(即不会修改对象的任何成员变量)。这样的成员函数可以在常量对象上调用。

使用 const 可以提高代码的可读性和安全性,因为它明确了变量、参数或成员函数的行为。同时,它也有助于编译器进行优化。

回到 重载&函数:

有两个取地址运算符重载函数:

左边就是编译器里的默认成员函数,自动生成。

即便对const 类的对象取地址,也不会用到第二个,因为会自动生成。

所以还是不用自己写。

总结:

认识运算符重载函数,以及特殊的运算符重载。

百看不如一写,真正的掌握还需自己实践获得。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值