C++入门(类与对象)以及日期类的实现

目录

简介

对象

日期类

定义部分

实现部分

构造函数部分

获取给定年份和月份的天数

打印年份月日 

拷贝构造函数 

拷贝构造函数的主要用途包括

析构函数

拷贝赋值运算符( operator= )的实现

 operator+=  成员函数的实现

operator+  成员函数的实现

operator-  成员函数

operator-=  成员函数的实现

 operator++(int)/operator++() 成员函数的实现

 operator--(int)/operator--() 成员函数的实现

operator>()  成员函数的实现

 operator==()  成员函数的实现

operator<() 成员函数的实现

 operator>=  成员函数的实现

operator<=  成员函数的实现

operator!=  成员函数的实现

operator-  成员函数的实现

测试部分

运行截图


简介

上一节我们了解了C++的一些基本名词概念,但没有涉及到最为核心的内容,下面我将会介绍一下两个问题:

  1. 什么是类?
  2. 什么是对象?

在C++中我们一般使用单词class来代表类,类里面分为三个限定访问符:公有(public)、私有(private)、受保护的(protected)。

类中的内容称为类的成员,类中的变量称为类的属性或者成员变量,类中的函数称为类的方法或者成员函数。

下面我用一段代码,定义一个类:

#include<iostream>
using namespace std;
class TestDate
{
public:
	void InitDate(int year)
	{
		year = _year;
	}
private:
	int _year;//一般需要加个前缀,便于区分
};

对象

对象,是一个物体或者说事物。我们用一个类去描述一个对象,类里面的函数,就代表了这个物体的使用方法,类中的变量就代表了我们能够如何调用这个物体,让这个物体运行起来。这些函数就被称为接口,与外界相连,一般也放在public里,而那些变量则被存放在private里面。还有一些很重要的就被丢到protected里。

这个过程就被称为类实例化对象。

日期类

我们通过实现一个日期类来了解类和对象,以及类和对象其中的一些细枝末节的语法内容。

我们采用了声明定义分离的方式来实现日期类,一个是方便阅读理解, 一个是更加规范。

定义部分

下面我们首先看一下声明文件(Date.h),这一部分负责的是函数的定义部分。

#pragma once
#include<iostream>
using namespace std;
class Date
{
public:
	Date(int year = 2024, int month = 1, int day = 1);//全缺省构造函数
	int Get(int year, int month);//获取当前年份以及月份
	Date(const Date& d);//拷贝构造函数->为了防止数据被修改
	void Print();//打印函数
	~Date();//销毁函数

	Date operator=(const Date& d);//运算符=重载->赋值(含义是将年份赋给d.year,月份赋给d.month,日赋给d.day)

	Date& operator+=(int day);
	Date operator+(int day);
	Date operator-(int day);
	Date& operator-=(int day);
	Date& operator++();
	Date operator++(int);
	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);
	bool operator <= (const Date& d);
	bool operator != (const Date& d);

	int operator-(const Date& d);

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

实现部分

然后我们看一下函数的实现部分,Date.cpp。

构造函数部分

Date::Date(int year, int month, int day)
{
	if (month < 1 || month>12 || day<1 || day>Get(year, month))
	{
		cout << "日期非法" << endl;
	}
	_year = year;
	_month = month;
	_day = day;
}

函数接受三个参数:年year、月和日day。首先,函数检查month和day的值是否合法,即month必须在1到12之间,day必须在1到该月最大天数之间。如果非法,函数将输出错误信息"日期非法"。如果参数合法,则将year、month和day的值分别赋值给_year、_month和_day三个成员变量。这个构造函数用于创建一个新的日期对象,并确保其日期是有效的。

获取给定年份和月份的天数

int Date::Get(int year, int month)
{
	int Array[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)) //判断闰年
	{
		Array[2]++;
	}
	return Array[month];//返回当前月份的天数。
}

打印年份月日 

void Date::Print()
{
	cout << _year << "年" << _month << "月" << _day << "日" << endl;
}

拷贝构造函数 

拷贝构造函数是一种特殊的构造函数,它用于创建一个新对象,作为另一个同类型对象的副本。在这个例子中, Date::Date(const Date& d)  接收一个对 Date  类型对象的常量引用 d  作为参数,并将新对象的年( _year )、月( _month )、日( _day )成员变量分别初始化为参数对象 d  的对应成员变量的值。

拷贝构造函数的主要用途包括

  1. 对象复制:当你需要将一个已存在的对象赋值给同类型的另一个新对象时,拷贝构造函数会被自动调用。
  2. 函数参数传递:当对象作为值传递给函数时,会调用拷贝构造函数来创建函数内部使用的对象副本。
  3. 函数返回值:当函数返回对象时(特别是返回局部对象时),会调用拷贝构造函数来创建并返回对象的副本给调用者。

拷贝构造函数需要正确处理对象的深拷贝和浅拷贝问题,以避免出现悬挂指针、重复释放内存等错误。然而,在  Date  类的这个例子中,由于它只包含基本数据类型( int  类型的年、月、日),所以不需要担心这些问题。

Date::Date(const Date& d)
{
    _year = d._year;
    _month = d._month;
    _day = d._day;
}

析构函数

析构函数用于销毁函数。

Date::~Date() {}

拷贝赋值运算符( operator= )的实现

这段代码是 Date  类的拷贝赋值运算符( operator= )的实现。拷贝赋值运算符是一个特殊的成员函数,用于将一个 Date  类型的对象赋值给另一个 Date  类型的对象。

Date Date::operator=(const Date& d)
{
	_year = d._year;
	_month = d._month;
	_day = d._day;
	return*this;
}

 operator+=  成员函数的实现

这段代码是  Date  类的  operator+=  成员函数的实现,用于实现日期加上一定天数的操作。

函数接收一个  int  类型的参数  day ,表示要加上的天数。如果  day  小于 0,函数会调用  operator-=  成员函数(通过将  day  取负)来实现日期减去一定天数的操作。

如果  day  大于等于 0,函数会将  _day  成员变量加上  day ,表示日期加上一定天数。然后,函数会检查  _day  是否大于当前月份的最大天数。如果是,函数会进入一个循环,将  _day  减去当前月份的最大天数,并将  _month  成员变量加 1,表示日期进入了下一个月份。

如果  _month  等于 13,表示日期进入了下一年份,函数会将  _month  重置为 1,并将  _year  成员变量加 1,表示日期进入了下一年份。

最后,函数返回  *this ,即当前对象的引用,使得该函数可以链式调用。

Date& Date::operator+=(int day)
{
	if (day < 0)
	{
		*this -= (-day);
		return *this;
	}
	_day += day;
	while (_day > Get(_year, _month))
	{
		//月进位
		_day -= Get(_year, _month);
		++_month;

		//年进位
		if (_month == 13)
		{
			++_year;
			_month = 1;
		}
	}
	return*this;

}

operator+  成员函数的实现

这段代码是  Date  类的  operator+  成员函数的实现,用于实现日期加上一定天数的操作。

函数接收一个  int  类型的参数  day ,表示要加上的天数。如果  day  小于 0,函数会调用  operator-  成员函数(通过将  day  取负)来实现日期减去一定天数的操作,然后将结果返回。

如果  day  大于等于 0,函数会创建一个新的  Date  对象  tmp ,并将其初始化为当前对象的拷贝。然后,函数会使用  operator+=  成员函数(通过将  day  加到  tmp  对象上)来实现日期加上一定天数的操作。最后,函数将  tmp  对象返回,表示新的日期。

这种实现方式避免了在  operator+  函数中直接修改当前对象的状态,而是创建了一个新的  Date  对象来保存结果,这使得  Date  类更加符合不可变性原则,即一个对象的状态在其生命周期内不应该被改变。

Date Date::operator+(int day)
{
	if (day < 0)
	{
		return *this - (-day);
	}
	Date tmp(*this); //拷贝构造
	tmp += day; //复用+=运算符
	return tmp;
}

operator-  成员函数

这段代码是  Date  类的  operator-  成员函数的实现,用于实现日期减去一定天数的操作。

函数接收一个  int  类型的参数  day ,表示要减去的天数。函数首先创建一个新的  Date  对象  tmp ,并将其初始化为当前对象的拷贝。然后,函数会使用  operator-=  成员函数(通过将  day  减到  tmp  对象上)来实现日期减去一定天数的操作。最后,函数将  tmp  对象返回,表示新的日期。

这种实现方式避免了在  operator-  函数中直接修改当前对象的状态,而是创建了一个新的  Date  对象来保存结果,这使得  Date  类更加符合不可变性原则,即一个对象的状态在其生命周期内不应该被改变。

Date Date::operator-(int day)
{
	Date tmp = *this;
	tmp -= day;
	return tmp;
}

operator-=  成员函数的实现

这段代码是  Date  类的  operator-=  成员函数的实现,用于实现日期减去一定天数的操作。

函数接收一个  int  类型的参数  day ,表示要减去的天数。如果  day  小于 0,函数会调用  operator+=  成员函数(通过将  day  取负)来实现日期加上一定天数的操作。

如果  day  大于等于 0,函数会将  _day  成员变量减去  day ,表示日期减去一定天数。然后,函数会检查  _day  是否小于等于 0。如果是,函数会进入一个循环,将  _month  成员变量减 1,表示日期进入了上一个月份。

如果  _month  等于 0,表示日期进入了上一年份,函数会将  _month  重置为 12,并将  _year  成员变量减 1,表示日期进入了上一年份。

然后,函数会将  _day  加上当前月份的最大天数,表示日期进入了上一个月份的最后一天。

最后,函数返回  *this ,即当前对象的引用,使得该函数可以链式调用。

Date& Date::operator-=(int day)
{
	if (day < 0)
	{
		*this += (-day);
		return *this;
	}
	_day -= day;
	while (_day <= 0)
	{
		//月让位
		--_month;

		//年让位
		if (_month == 0)
		{
			--_year;
			_month = 12;
		}
		_day += Get(_year, _month);
	}
	return *this;
}

 operator++(int)/operator++() 成员函数的实现

这段代码是  Date  类的  operator++(int)  成员函数的实现,用于实现日期增加一天的操作。

函数接收一个  int  类型的参数,但未使用。这个参数是  operator++(int)  的后置版本( operator++(int) )使用的,用于区分前置版本( operator++() )和后置版本。

函数首先创建一个  Date  类的临时对象  tmp ,并将其初始化为当前对象的拷贝。然后,函数调用  operator+=  成员函数,将当前日期增加一天。最后,函数返回  tmp ,即增加一天前的日期对象。

注意,该函数的实现依赖于  Date  类的  operator+=  成员函数,该函数用于实现日期加上一定天数的操作。因此,在实际使用中,需要确保  operator+=  函数已经被正确实现

Date& Date::operator++()
{
	*this += 1; //先+1
	return *this; //再返回,返回+1后的结果
}
Date Date::operator++(int)
{
	Date tmp(*this); //拷贝一份
	*this += 1; //然后+1
	return tmp; //返回+1前的结果
}

 operator--(int)/operator--() 成员函数的实现

这段代码是  Date  类的  operator--()  成员函数的实现,用于实现日期减少一天的操作。

函数接收一个  int  类型的参数,但未使用。这个参数是  operator--(int)  的后置版本( operator--(int) )使用的,用于区分前置版本( operator--() )和后置版本。

函数首先创建一个  Date  类的临时对象  tmp ,并将其初始化为当前对象的拷贝。然后,函数调用  operator-=  成员函数,将当前日期减少一天。最后,函数返回  tmp ,即减少一天前的日期对象。

Date& Date::operator--()
{
	*this -= 1; //先-1
	return *this; //再返回,返回-1后的结果
}

Date Date::operator--(int)
{
	Date tmp(*this); //拷贝一份
	*this -= 1; //然后-1
	return tmp; //返回-1前的结果
}

operator>()  成员函数的实现

这段代码是  Date  类的  operator>()  成员函数的实现,用于实现日期的比较操作。

函数接收一个  const Date&  类型的参数  d ,表示要比较的日期对象。

函数首先比较当前对象的年份  _year  和参数对象  d  的年份  _year 。如果当前对象的年份大于参数对象的年份,函数返回  true ,表示当前日期比参数日期晚。

如果当前对象的年份等于参数对象的年份,函数会比较当前对象的月份  _month  和参数对象  d  的月份  _month 。如果当前对象的月份大于参数对象的月份,函数返回  true ,表示当前日期比参数日期晚。

如果当前对象的年份和月份都等于参数对象的年份和月份,函数会比较当前对象的日期  _day  和参数对象  d  的日期  _day 。如果当前对象的日期大于参数对象的日期,函数返回  true ,表示当前日期比参数日期晚。

如果前面的条件都不符合,说明当前日期比参数日期早,函数返回  false 。

 operator==()  成员函数的实现

这段代码是  Date  类的  operator==()  成员函数的实现,用于实现日期的相等性比较操作。

函数接收一个  const Date&  类型的参数  d ,表示要比较的日期对象。

函数使用逻辑与运算符  &&  将三个条件连接在一起:
当前对象的年份  _year  等于参数对象  d  的年份  _year 。
当前对象的月份  _month  等于参数对象  d  的月份  _month 。
当前对象的日期  _day  等于参数对象  d  的日期  _day 。
如果这三个条件都成立,即当前日期与参数日期的年份、月份和日期都相等,函数返回  true ,表示当前日期等于参数日期。

否则,如果这三个条件中的任何一个条件不成立,即当前日期与参数日期的年份、月份或日期至少有一个不相等,函数返回  false ,表示当前日期不等于参数日期。

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

operator<() 成员函数的实现

这段代码是  Date  类的  operator<() 成员函数的实现,用于实现日期的比较操作。

函数接收一个  const Date&  类型的参数  d ,表示要比较的日期对象。

函数使用逻辑非运算符  !  将  (*this == d) || (* this > d)  的结果取反。

 (*this == d)  表示当前日期是否等于参数日期, (* this > d)  表示当前日期是否大于参数日期。

如果  (*this == d)  为  true ,表示当前日期等于参数日期,如果  (* this > d)  为  true ,表示当前日期大于参数日期。

因此, (*this == d) || (* this > d)  表示当前日期等于参数日期或者当前日期大于参数日期。

取反操作  !  将  (*this == d) || (* this > d)  的结果取反,即如果当前日期等于参数日期或者当前日期大于参数日期,结果为  false ;否则,结果为  true 。

也就是说, !((*this == d) || (* this > d))  的结果为  true ,当且仅当当前日期既不等于参数日期,也不大于参数日期。

因此, Date::operator<(const Date& d)  函数的返回值表示当前日期是否小于参数日期。如果当前日期小于参数日期,函数返回  true ;否则,返回  false 。

bool Date::operator<(const Date& d)
{
	return !((*this == d) || (*this > d)); //逻辑非之后表示既不大于也不等于
}

 operator>=  成员函数的实现

这段代码是  Date  类的  operator>=  成员函数的实现,用于实现日期的比较操作。

函数接收一个  const Date&  类型的参数  d ,表示要比较的日期对象。

函数使用逻辑非运算符  !  将  (*this < d)  的结果取反。

 (* this < d)  是  Date::operator<(const Date& d)  函数的调用,用于判断当前日期是否小于参数日期。 

如果  (*this < d)  为  true ,表示当前日期小于参数日期,取反后结果为  false ;否则,结果为  true 。

因此, !(* this < d)  的结果为  true ,当且仅当当前日期不小于参数日期。

也就是说, Date::operator>=(const Date& d)  函数的返回值表示当前日期是否大于等于参数日期。如果当前日期大于等于参数日期,函数返回  true ;否则,返回  false 。

bool Date::operator>=(const Date& d)
{
	return !(*this < d); //复用<运算符
}

operator<=  成员函数的实现

这段代码是  Date  类的  operator<=  成员函数的实现,用于实现日期的比较操作。

函数接收一个  const Date&  类型的参数  d ,表示要比较的日期对象。

函数使用逻辑非运算符  !  将  (*this > d)  的结果取反。

 (* this > d)  是  Date::operator>(const Date& d)  函数的调用,用于判断当前日期是否大于参数日期。

如果  (*this > d)  为  true ,表示当前日期大于参数日期,取反后结果为  false ;否则,结果为  true 。

因此, !(* this > d)  的结果为  true ,当且仅当当前日期不大于参数日期。

也就是说, Date::operator<=(const Date& d)  函数的返回值表示当前日期是否小于等于参数日期。如果当前日期小于等于参数日期,函数返回  true ;否则,返回  false 。

bool Date::operator<=(const Date& d)
{
	return !(*this > d); //复用>运算符
}

operator!=  成员函数的实现

这段代码是  Date  类的  operator!=  成员函数的实现,用于实现日期的不相等比较操作。

函数接收一个  const Date&  类型的参数  d ,表示要比较的日期对象。

函数使用逻辑非运算符  !  将  (*this == d)  的结果取反。

 (* this == d)  是  Date::operator==(const Date& d)  函数的调用,用于判断当前日期是否等于参数日期。

如果  (*this == d)  为  true ,表示当前日期等于参数日期,取反后结果为  false ;否则,结果为  true 。

因此, !(* this == d)  的结果为  true ,当且仅当当前日期不等于参数日期。

也就是说, Date::operator!=(const Date& d)  函数的返回值表示当前日期是否不等于参数日期。如果当前日期不等于参数日期,函数返回  true ;否则,返回  false

bool Date::operator!=(const Date& d)
{
	return !(*this == d); //复用==运算符
}

operator-  成员函数的实现

这段代码是  Date  类的  operator-  成员函数的实现,用于实现l两个日期的相减操作。(相当于函数重载了)

函数接收一个  const Date&  类型的参数  d ,表示要减去的日期对象。

函数首先假设当前日期  *this  较小,将当前日期赋值给  min ,将参数日期  d  赋值给  max ,并将  flag  初始化为  -1 ,用于表示最后相减结果的符号。

然后,函数判断假设是否成立。如果  min > max ,表示假设不成立,函数将  min  和  max  互换,并将  flag  设为  1 。

接下来,函数使用  while  循环,将  min  累加,直到  min  大于等于  max 。

最后,函数返回  ret * flag ,其中  ret  表示  min  累加的次数, flag  表示相减结果的符号。

也就是说, Date::operator-(const Date& d)  函数的返回值表示当前日期与参数日期之间的天数差。如果当前日期大于参数日期,返回值为正数;否则,返回值为负数。

int Date::operator-(const Date& d)
{
	//找出较小的那个日期,这里先假设*this较小
	Date min = *this;
	Date max = d;
	int flag = -1; //用于表示最后相减结果的符号
	if (min > max) //假设不成立,互换
	{
		min = d;
		max = *this;
		flag = 1;
	}

	//小的进行累加,直到二者相等
	int ret = 0; //统计min累加的次数
	while (max > min)
	{
		min++;
		ret++;
	}
	return ret * flag; //最终累加的次数即为日期差
}

测试部分

Test.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include"Date.h"
using namespace std;
int main()
{
	Date d1(2019, 9, 18);
	d1.Print();
	Date d2;
	d2 = d1 + 66;
	d2.Print();

	Date d3;
	d3 += 66;
	d3.Print();

	Date d4;
	d4 = d1 - 66;
	d4.Print();

	system("pause");
	return 0;
}

运行截图

  • 10
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值