【C++初阶】日期类实现、const成员函数、取地址及const取地址操作符重载

本文深入探讨C++编程,通过日期类实例详细讲解了包括构造函数、赋值运算符重载、const成员函数以及取地址操作符重载等核心概念。同时,分析了const成员函数在权限控制上的作用,并提供了相关代码示例以加深理解。
摘要由CSDN通过智能技术生成

🌟hello,各位读者大大们你们好呀🌟

🍭🍭系列专栏:【C++学习与应用】

✒️✒️本篇内容:日期类的代码实现、const成员函数的概念和作用、取地址及const取地址操作符重载

🚢🚢作者简介:计算机海洋的新进船长一枚,请多多指教( •̀֊•́ ) ̖́-

📡📡同期文章:【C++初阶】简析构造函数、析构函数

                           【C++初阶】简析拷贝构造、赋值运算符重载

目录

一、引言

二、日期类

1. 获取某年某月的天数

2.全缺省的构造函数

3.拷贝构造函数

4.赋值运算符重载

5.析构函数 

6.日期+天数

7.日期+=天数

8.日期-天数

9.日期-=天数

10.前置++

11.后置++

12.前置--

13.后置--

14.>运算符重载

15.==运算符重载

16.>=运算符重载 

17.<运算符重载

18.<=运算符重载

19.!=运算符重载

20.日期-日期 返回天数

三、const成员函数

四、取地址及const取地址操作符重载


一、引言

之前我们学习了赋值运算符重载的相关知识,今天就让我们一起通过日期类实现,用代码来实践一下赋值运算符重载,深入了解部分代码细节。

学习完日期类的实现后,我们再进入下一块知识:const成员,取地址及const取地址操作符重载,领会C++设立const成员语法的意义。


二、日期类

日期类计划主要用代码讲解,以下讲解的函数主要为类的成员函数

1. 获取某年某月的天数

    // 获取某年某月的天数
    int GetMonthDay(int year, int month)
	{
		static int monthDayArray[13] = { 0, 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 29;
		}
		else
		{
			return monthDayArray[month];
		}
	}

2.全缺省的构造函数

	// 全缺省的构造函数
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;

		// 检查日期是否合法
		if (!(year >= 1
			&& (month >= 1 && month <= 12)
			&& (day >= 1 && day <= GetMonthDay(year, month))))
		{
			cout << "非法日期" << endl;
		}
	}

3.拷贝构造函数

	// 拷贝构造函数
    // d2(d1)
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

4.赋值运算符重载

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

		return *this;
	}

5.析构函数 

由于是日期类,对象都是内置类型,我们可以使用编译器默认生成的析构函数

6.日期+天数

	// 日期+天数
	//	Date Date::operator+(int day) const - 声明定义分离写法
	Date operator+(int day)
	{
		Date ret(*this);
		ret += day;
		return ret;
	}

7.日期+=天数

	// 日期+=天数
	//	Date& Date::operator+=(int day) - 声明定义分离写法
	Date& operator+=(int day)
	{
		if (day < 0)
		{
			//return *this -= -day;
			return *this -= abs(day);//abs求绝对值
		}

		_day += day;

		while (_day > GetMonthDay(_year, _month))//day>某年某月的天数
		{
			_day -= GetMonthDay(_year, _month);
			_month++;

			if (_month == 13)//超过12月,加1年,月回1
			{
				++_year;
				_month = 1;
			}
		}

		return *this;
	}

8.日期-天数

	// 日期-天数
	//	Date Date::operator-(int day) const - 声明定义分离写法
	Date operator-(int day)
	{
		Date ret(*this);
		ret -= day;

		return ret;
	}

9.日期-=天数

	// 日期-=天数
	//	Date& Date::operator-=(int day) - 声明定义分离写法
	Date& operator-=(int day)
	{
		if (day < 0)
		{
			//return *this -= -day;
			return *this += abs(day);
		}

		_day -= day;

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

			_day += GetMonthDay(_year, _month);
		}

		return *this;
	}

10.前置++

	// 前置++
	//	Date& Date::operator++() - 声明定义分离写法
	Date& operator++()
	{
		*this += 1;
		return *this;
	}

11.后置++

	// 后置++
	//	Date Date::operator++(int) - 声明定义分离写法
	Date operator++(int)
	{
		Date tmp(*this);

		*this += 1;

		return tmp;
	}

12.前置--

	// 前置--
	//	Date& Date::operator--() - 声明定义分离写法
	Date& operator--()
	{
		*this -= 1;
		return *this;
	}

13.后置--

    // 后置--
	//	Date Date::operator--(int) - 声明定义分离写法
	Date operator--(int)
	{
		Date tmp = *this;
		*this -= 1;

		return tmp;
	}

14.>运算符重载

	// >运算符重载
	//	bool Date::operator>(const Date& d) const - 声明定义分离写法
	bool 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;
	}

15.==运算符重载

	// ==运算符重载
	bool operator==(const Date& d) - 声明定义分离写法
	{
		return _year == d._year
			&& _month == d._month
			&& _day == d._day;
	}

16.>=运算符重载 

	// >=运算符重载
	//	bool Date::operator>=(const Date& d) const - 声明定义分离写法
	bool operator >= (const Date& d)
	{
		return *this > d || *this == d;
	}

17.<运算符重载

	// <运算符重载
	//	bool Date::operator<(const Date& d) const - 声明定义分离写法
	bool operator < (const Date& d)
	{
		return !(*this >= d);
	}

18.<=运算符重载

	// <=运算符重载
	//	bool Date::operator<=(const Date& d) const - 声明定义分离写法
	bool operator <= (const Date& d)
	{
		return !(*this > d);
	}

19.!=运算符重载

	// !=运算符重载
	//	bool Date::operator!=(const Date& d) const - 声明定义分离写法
	bool operator != (const Date& d)
	{
		return !(*this == d);
	}

20.日期-日期 返回天数

	// 日期-日期 返回天数
	//int Date::operator-(const Date& d) const - 声明定义分离写法
	int operator-(const Date& d)
	{
		Date max = *this;
		Date min = d;
		int flag = 1;

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

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

		return n * flag;
	}


三、const成员函数

用const修饰的“成员函数”称之为const成员函数,const修饰类的成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改

在下图中,左图和右图代表的含义实际上是相同的,我们可以将右图看为是作图的展开

下面我们一起看一段代码 

class Date
{
public:
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << "Print()" << endl;
		cout << "year:" << _year << endl;
		cout << "month:" << _month << endl;
		cout << "day:" << _day << endl << endl;
	}
	void Print() const
	{
		cout << "Print()const" << endl;
		cout << "year:" << _year << endl;
		cout << "month:" << _month << endl;
		cout << "day:" << _day << endl << endl;
	}
private:
	int _year; // 年
	int _month; // 月
	int _day; // 日
};

int main()
{
	Date d1(2022, 1, 13);
	d1.Print();

	const Date d2(2022, 1, 13);
	d2.Print();
	return 0;
}

它的输出结果如下

通过结果我们可以知,d2.Print() 和 d1.Print() 调用的函数并不相同,因为在定义 Date d2时,在前面加上了const ,因此调用的函数不能更改 d2,否则就造成了权限放大,编译器报错,所以编译器会默认调用 void Print() const 函数。

接下来我们思考一个问题,不要 void Print() 函数可不可以呢?答案是当然可以,默认允许更改->不能更改,实际上时权限的缩小

光说不练假把式,我们直接编译一下

 从编译结果得证:调用类函数允许权限缩小和平移,不允许权限缩小

接下来我们再看一组练习强化理解一下:

1. const对象可以调用非const成员函数吗?

2. 非const对象可以调用const成员函数吗?

3. const成员函数内可以调用其它的非const成员函数吗?

4. 非const成员函数内可以调用其它的const成员函数吗?

答案:

1、const对象不能调用非const成员函数,const对象可以调用const成员函数
2、非const对象可以调用const成员函数,非const对象可以调用非const成员函数
3、const成员函数不能调用非const成员函数
4、非const成员函数可以调用非const成员函数

因此,当我们在使用成员函数需要某些限制时,const成员的作用就凸显出来了。


四、取地址及const取地址操作符重载

之前我们就介绍过,类里面有6个默认函数,前四个(构造、析构、拷贝、赋值重载)我们都在前面的博客详细解说过了,今天我们就继续来谈谈最后两个默认函数,取地址及const取地址操作符重载。

事实上,取地址及const取地址操作符重载,这两种默认函数需要我们显式实现的情况少之又少,编译器已经基本帮我们准备好了。所以我们简单了解一下即可。

class Date
{
public:
	Date* operator&()    //取地址操作符重载
	{
		return this;
	}

	const Date* operator&()const    //const取地址操作符重载
	{
		return this;
	}
private:
	int _year; // 年
	int _month; // 月
	int _day; // 日
};

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


🌹🌹今天的内容大概就讲到这里啦,博主后续会继续向大家介绍更多实用有趣的工具,干货满满,如果觉得博主写的还不错的话,希望各位小伙伴不要吝啬手中的三连哦!你们的支持是博主坚持创作的动力!💪💪

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值