当前位置: 首页 > article >正文

类和对象( 中 【补充】)

目录

一 . 赋值运算符重载

1.1 运算符重载

1.2 赋值运算符重载

1.3 日期类实现

 1.3.1 比较日期的大小 :

  1.3.2 日期+=天数 :

1.3.3 日期 -= 天数 :  

1.3.4  前置++/后置++ 

1.3.5 日期 - 日期 

 1.3.6  流插入 <<  和 流提取 >>

二 . 取地址运算符重载

2.1 const 成员函数

2.2 取地址运算符重载


回顾:借助  三道选择题,深刻回顾以下  上一章节的内容!类和对象(中)-CSDN博客

一 . 下列关于构造函数的描述 正确 的是( ) 

A.构造函数可以声明返回类型

B.构造函数不可以用private修饰

C.构造函数必须与类名相同

D.构造函数不能带参数

A . 构造函数不能声明返回类型,void 也不可以!

B . 可以的 , 只不过不能直接实例化对象了

D . 构造函数不光可以带参数,还可以有多个构造函数构成重载

二 .  在函数F中,本地变量a和b的构造函数(constructor)和析构函数(destructor)的调用顺序是: ( )

Class A;

Class B;

void F() {

A a;

  B b;

  }

A.b构造 a构造 a析构 b析构

B.a构造 a析构 b构造 b析构

C.b构造 a构造 b析构 a析构

D.a构造 b构造 b析构 a析构

构造顺序是按照语句的顺序进行构造,析构是按照构造的相反顺序进行析构 ,   对象析构要在生存作用域结束的时候才进行析构

D

三 . 设已经有A,B,C,D4个类的定义,程序中A,B,C,D析构函数调用顺序为?( )

C c;

int main()

{

A a;

B b;

static D d;

  return 0;

}

A.D B A C

B.B A D C

C.C D B A

D.A B D C

1、类的析构函数调用一般按照构造函数调用的相反顺序进行调用,但是要注意static对象的存在, 因为static改变了对象的生存作用域,需要等待程序结束时才会析构释放对象

2、全局对象先于局部对象进行构造

3、局部对象按照出现的顺序进行构造,无论是否为static

4、所以构造的顺序为 c a b d

5、析构的顺序按照构造的相反顺序析构,只需注意static改变对象的生存作用域之后,会放在局部 对象之后进行析构

6、因此析构顺序为B A D C

一 . 赋值运算符重载

1.1 运算符重载

  • 当运算符被用于类 类型的对象时 , C++语言允许我们通过运算符重载的形式指定新的含义 。 C++规定 类类型对象使用运算符时 , 必须转化成调用对应运算符重载 , 若没有运算符重载 , 则会编译报错 。
  • 运算符重载时具有特定名字的函数 , 它的名字是由 operator 和 后面要定义的运算符共同构成 。 和其他函数一样 , 它也   具有其  返回类型  和  参数列表  以及  函数体
  • 重载运算符函数和参数个数和该运算符作用的运算对象数量一样多 。 一元运算符有一个参数 , 二元运算符有两个参数 , 二元运算符的  侧运算对象  传给  第个参数 ,   侧运算对象  传给  第个参数。
  • 如果一个重载运算符函数是成员函数,则它的第一个运算对象默认传给隐式的 this指针,因此运算符重载作为成员函数时,参数比运算对象少一个。

 内置类型运算时 , 会比较简单 , 能够直接转化成相应的指令 , 下面举个例子 :

int main()
{
	int i = 1, j = 3;
	int ret1 = i + j;
	bool ret2 = i == j;
	int ret3 = i ^ j;
	return 0;
}

我们调试以下 , 转到汇编语言 , 可以看到编译器可以直接转为 add , cmp , xor 指令  , 但是对于自定义类型 , 是由程序员自己定义的 , 需要实现的功能也是由程序员定义的 , 下面我们举一个日期类的例子 :

 我们的编译器充当的是翻译功能 , 当需要实现太复杂的对象与对象之间的运算 ,编译器编不出来

所以我们需要写一个运算符重载函数 , 实现相应的运算功能 :

 如果这样设为公有 ,成员变量很容易被访问到 ,很不安全 ,以下提供三种方法:  

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;

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

	bool operator==(const Date& x)
	{
		return _year == x._year
			&& _month == x._month
			&& _day == x._day;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1(2024, 11, 15);
	Date d2(2024, 11, 30);

	bool ret1 = d1 == d2;
	cout << ret1 << endl;

	return 0;
}
  •  运算符重载以后 , 其优先级和结合性与对应的内置类型运算符保持一致。
  • 不能通过连接语法中没有的符号来创建新的操作符 : 比如operator@
  •  .*     ::   sizeof    ?:   .     注意以上5个运算符不能重载 。 !!!!

  • 重载操作符至少有一个类  类型参数 , 不能通过运算符重载改变内置类型对象的含义 , 如  int operator+(int x,int y )
  • 一个类需要重载那些运算符 , 是看那些运算符重载后有意义 , 比如Date 类  重载 operator- 就有意义 , 但是重载 opearator+ 就没有意义 。
  • 重载++运算符时 , 有前置++  和后置++ , 运算符重载函数名都是operator++ , 无法很好的区分 。 C++规定 , 后置++重载时候 , 增加一个 int 形参  ,跟前置++ 构成函数重载 , 方便区分 。
  • 重载<<  和 >> 时 , 需要重载函数为全局函数 , 因为重载为成员函数 , this 指针 默认抢占了第一个形参位置 , 第一个形参位置是左侧运算符对象 ,调用时就变成了  对象<<cout , 不符合使用习惯和可读性 。 重载为全局函数把 ostream/istream 放在第一个形参位置就可以了 , 第二个形参位置当类型对象 。 

 .* 应用举例 : 

//.* 举例

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
// 编译报错:“operator +”必须⾄少有⼀个类类型的形参
int operator+(int x, int y)
{
    return x - y;
}
class A
{
public:
	void func()
	{
		cout << "A::func()" << endl;
	}
};
typedef void(A::* PF)(); //成员函数指针类型
int main()
{
	// C++规定成员函数要加&才能取到函数指针
	PF pf = &A::func;
	A obj;//定义ob类对象temp
	// 对象调⽤成员函数指针时,使⽤.*运算符
	(obj.*pf)();
	return 0;
}

1.2 赋值运算符重载

赋值运算符重载是一个默认成员函数 , 用于完成两个  已经存在  的对象直接拷贝赋值这里要注意跟拷贝构造区分 , 拷贝构造用于一个对象拷贝初始化给另一个对象 。 

赋值运算符重载的特点 :

  1.  赋值运算符重载是一个运算符重载 , 规定必须重载为成员函数 。 赋值运算重载的参数建议写成 const 当前类 类型引用 , 否则 会 传值传参会有拷贝 。
  2. 有返回值 , 且建议写成当前类  类型引用 , 引用返回可以提高效率 , 有返回值目的是为了支持连续赋值场景
  3. 没有显式实现时 , 编译器会自动生成一个默认赋值运算符重载 , 默认运算符重载行为跟默认构造函数类似 , 对内置类型成员变量会完成值拷贝 / 浅拷贝(一个字节一个字节的拷贝),对自定义类型成员变量会调用他的拷贝构造 。

什么时候需要实现赋值重载 ? 

如果栈 , 进行赋值重载时 , 但是没有进行写赋值重载函数会发生什么情况 :

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;

class Date
{
public:
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	//赋值重载 -- 两个都是存在的对象
	//d2 = d1
	Date& operator=(const Date& d)
	{
		if (this != &d)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}
	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}

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

typedef int STDataType;
class Stack
{
public:
	Stack(int n = 4)
	{
		_a = (STDataType*)malloc(sizeof(STDataType) * n);
		if (nullptr == _a)
		{
			perror("malloc申请空间失败");
			return;
		}
		_capacity = n;
		_top = 0;
	}
	
	// st2(st1)
	Stack(const Stack& st)
	{
		// 需要对_a指向资源创建同样大的资源再拷贝值
		_a = (STDataType*)malloc(sizeof(STDataType) * st._capacity);
		if (nullptr == _a)
		{
			perror("malloc申请空间失败!!!");
			return;
		}
		memcpy(_a, st._a, sizeof(STDataType) * st._top);
		_top = st._top;
		_capacity = st._capacity;
	}

	// st1 = st3
	// st1 = st1;
	Stack& operator=(const Stack& st)
	{
		if (this != &st)
		{
			free(_a);
			_a = (STDataType*)malloc(sizeof(STDataType) * st._capacity);
			if (nullptr == _a)
			{
				perror("malloc申请空间失败!!!");
				return *this;
			}
			memcpy(_a, st._a, sizeof(STDataType) * st._top);
			_top = st._top;
			_capacity = st._capacity;
		}

		return *this;
	}

	void Push(STDataType x)
	{
		if (_top == _capacity)
		{
			int newcapacity = _capacity * 2;
			STDataType* tmp = (STDataType*)realloc(_a, newcapacity *
				sizeof(STDataType));
			if (tmp == NULL)
			{
				perror("realloc fail");
				return;
			}
			_a = tmp;
			_capacity = newcapacity;
		}
		_a[_top++] = x;
	}

	void Pop()
	{
		_a[_top - 1] = -1;
		--_top;
	}

	int Top()
	{
		return _a[_top - 1];
	}

	~Stack()
	{
		cout << "~Stack()" << endl;
		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}
private:
	STDataType* _a;
	size_t _capacity;
	size_t _top;
};

class MyQueue
{
private:
	Stack _pushst;
	Stack _popst;
};

int main()
{
	Date d1(2024, 11, 20);
	d1.Print();

	Date d2(2024, 11, 30);
	d2.Print();

	Date d3 = d2;
	d3.Print();

	Stack st1;
	st1.Push(1);
	st1.Push(2);
	st1.Push(3);
	st1.Push(4);

	Stack st2(10);
	for (size_t i = 0; i < 10; i++)
	{
		st2.Push(i * 10);
	}

	st1 = st2;

	MyQueue q1;
	MyQueue q2(q1);
	MyQueue q3;

	q1 = q3;

	return 0;
}

1.3 日期类实现

为了更好的进行文件管理 , 我们创建三个文件 : Date.cpp  , Date.h    , test,cpp

日期类的实现 需要结合实际生活中的客观现象 : 比如闰年2月为29天等;

 1.3.1 比较日期的大小 :

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)
	{
		return _day > d._day;
	}
	return false;
}

bool Date::operator>=(const Date& d)
{
	return *this > d || *this == d;
}

bool Date::operator<(const Date& d)
{
	return !(*this >= d);
}

bool Date::operator<=(const Date& d)
{
	return !(*this > d);
}

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

bool Date::operator!=(const Date& d)
{
	return !(*this == d);
}

  1.3.2 日期+=天数 :

//  GetMonthDay

	int GetMonthDay(int year, int month)
	{
		static int monthDayArry[13] = { -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 29;
		}
		return monthDayArry[month];
	}

// +=
Date& Date::operator+=(int day)
{
	_day += day;
	while (_day > GetMonthDay(_year, _month))
	{
		_day -= GetMonthDay(_year, _month);
		//天满进月
		++_month;
		//月满进年
		if (_month == 13)
		{
			_month = 1;
			++_year;
		}
	}
	return *this;
}


// +
Date Date::operator+(int day)
{
	Date tmp(*this);
	tmp._day += day;
	while (tmp._day > GetMonthDay(tmp._year, tmp._month))
	{
		tmp._day -= GetMonthDay(tmp._year, tmp._month);
		//天满进月
		++tmp._month;
		//月满进年
		if (tmp._month == 13)
		{
			tmp._month = 1;
			++tmp._year;
		}
	}
	return tmp;
}


  + 与 += 比较 :

Date d1 ;

Date d2 = d1 + 50;

+ : d1 不变(*this)

Date d1;

Date d2 = d1 += 50;

+= :  d1 改变(*this)

可以使用 + 复用实现 += :

Date Date::operator+(int day)
{
	Date tmp(*this);
	tmp._day += day;
	while (tmp._day > GetMonthDay(tmp._year, tmp._month))
	{
		tmp._day -= GetMonthDay(tmp._year, tmp._month);
		//天满进月
		++tmp._month;
		//月满进年
		if (tmp._month == 13)
		{
			tmp._month = 1;
			++tmp._year;
		}
	}
	return tmp;
}

// + 复用实现 +=
Date& Date::operator+=(int day)
{
	*this = *this + _day;
	return *this;
}

可以使用 += 复用实现 + :

Date& Date::operator+=(int day)
{
	_day += day;
	while (_day > GetMonthDay(_year, _month))
	{
		_day -= GetMonthDay(_year, _month);
		//天满进月
		++_month;
		//月满进年
		if (_month == 13)
		{
			_month = 1;
			++_year;
		}
	}
	return *this;
}


//+= 复用实现 + 
Date Date::operator+(int day)
{
	Date tmp(*this);
	tmp += day;
	return tmp;
}

 + 复用实现 += 的情况好 还是 += 复用实现 + 的情况好 ?

对比调用拷贝构造的次数 :

使用 += 复用 + 更好 !

1.3.3 日期 -= 天数 :  

Date& Date::operator-=(int day)
{
	_day -= day;
	while (_day<=0)
	{
		//借位
		--_month;
		if (_month == 0)
		{
			--_year;
			_month = 12;
		}
		_day += GetMonthDay(_year, _month);
	}
	return *this;
}

Date Date::operator-(int day)
{
	Date tmp(*this);
	tmp._day -= day;
	while (tmp._day <= 0)
	{
		//借位
		--tmp._month;
		if (tmp._month == 0)
		{
			--tmp._year;
			tmp._month = 12;
		}
		tmp._day += GetMonthDay(tmp._year, tmp._month);
	}
	return tmp;
}

 如果 d1 += -100

         d2  -=  -100

在程序中可以得到合理结果吗?

运行 ---  -28 日不存在 -- 不合理 !

1 ) d1 += -100        ----->  实际就是 -=100

2 )  d2  -=  -100        ----->  实际就是 +=100

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 == 13)
		{
			_month = 1;
			++_year;
		}
	}
	return *this;
}


Date& Date::operator-=(int day)
{
	if (day < 0)
		return *this += (-day);
	_day -= day;
	while (_day<=0)
	{
		//借位
		--_month;
		if (_month == 0)
		{
			--_year;
			_month = 12;
		}
		_day += GetMonthDay(_year, _month);
	}
	return *this;
}

1.3.4  前置++/后置++ 

重载++运算符时 , 有前置++ 和 后置 ++ , 运算符重载函数名都是 operator++ , 无法很好的区分 , C++规定 , 后置++ 重载时 , 增加一个 int 形参 , 跟前置 ++ 构成函数重载 , 方便区分!

多了一个参数仅仅是为了区分前置和后置

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

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

1.3.5 日期 - 日期 

//d1 - d2
int Date::operator-(const Date& d)
{
	int flag = 1;
	Date max = *this;
	Date min = d;
	if (*this < d)
	{
		max = d;
		min = *this;
		flag = -1;
	}
	//对于++,前置++的效率更大
	int n = 0;
	while (min != max)
	{
		++min;
		++n;
	}
	return flag * n;
}

 1.3.6  流插入 <<  和 流提取 >>

注意 : 如果<< 的运算符重载写在成员函数里 , 第一个参数一定是this ,那么插入操作就必须写成 d1<<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 << "请依次输入年月日:>";
	//默认用空格 或者 换行 分割
	in>> d._year >>  d._month >> d._day;
	return in;
}

但是 如果我输入2023年2月29日  ( 不合法的日期)  是否可以正常打印呢 ?  

那就意味着我们还需要写一个 合法检查函数 , 控制在输入 和 构造函数 必须是合法的日期;

bool Date::CheckDate()
{
	if (_month < 1 || _month > 12|| _day < 1 || _day > GetMonthDay(_year, _month))
	{
		return false;
	}
	else
	{
		return true;
	}
}

Date::Date(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;

	if (!CheckDate())
	{
		cout << "日期非法:" << *this << endl;
	}
}

// 流提取 >>   写
istream& operator>>(istream& in, Date& d)
{
	while (1)
	{
		cout << "请依次输入年月日:>";
		//默认用空格 或者 换行 分割
		in >> d._year >> d._month >> d._day;
		if (d.CheckDate())
		{
			break;
		}
		else
		{
			cout << "输入的日期非法,请重新输入:"<<endl;
		}
	}
	return in;
}

二 . 取地址运算符重载

2.1 const 成员函数

  1. 将const 修饰的成员函数称之为 const 成员函数 , const 修饰成员函数放在成员函数参数后面
  2. const 实际修饰  该成员函数隐含的 this 指针 ,表明在该成员函数中不能对类的任何成员进行修改 。 const 修饰Date 类的 Print成员函数 , Print 隐含的   this指针由   Date* const this 变为  Date* const this  

2.2 取地址运算符重载

取地址运算符重载分为普通取地址运算符重载 和 const取地址运算符重载 , 一般这两个函数编译器自动生成的就可以够我们用了 , 不需要去显示实现 。 除非一些很特殊的场景 , 比如我们不想取到当前类对象的地址 , 就可以自己实现一份 , 胡乱返回一个地址 。 

class Date
{
public:
	Date* operator&()
	{
		return this;
		// return nullptr;
	}
	const Date * operator&()const
	{
		return this;
		// return nullptr;
	 }
private:
	int _year; // 年
	int _month; // ⽉
	int _day; // ⽇
};

另 :  不要过分相信编译器的红色波浪线的报错 , 一切以编译的结果为准 , 因为编译器在这里进行的只是预检查 , 可能具有滞后性 , 或者一些BUG

总代码:

Date.cpp

#include "Date.h"

bool Date::CheckDate()
{
	if (_month < 1 || _month > 12|| _day < 1 || _day > GetMonthDay(_year, _month))
	{
		return false;
	}
	else
	{
		return true;
	}
}

Date::Date(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;

	if (!CheckDate())
	{
		cout << "日期非法:" << *this << endl;
	}
}


Date* Date::operator&()
{
	return this;
	// return nullptr;
}
const Date* Date::operator&()const
{
	return this;
	// return nullptr;
}

void Date::Print()const
{
	cout << _year << "/" << _month <<"/" << _day<<endl;
}



bool Date::operator>(const Date& d) const
{
	if (_year > d._year)
	{
		return true;
	}
	else if(_year == d._year&&_month >d._month)
	{
		return true;
	}
	else if(_year == d._year && _month == d._month)
	{
		return _day > d._day;
	}
	return false;
}

bool Date::operator>=(const Date& d) const
{
	return *this > d || *this == d;
}

bool Date::operator<(const Date& d) const
{
	return !(*this >= d);
}

bool Date::operator<=(const Date& d) const
{
	return !(*this > d);
}

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

bool Date::operator!=(const Date& d) const
{
	return !(*this == d);
}

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 == 13)
		{
			_month = 1;
			++_year;
		}
	}
	return *this;
}

//Date Date::operator+(int day)
//{
//	Date tmp(*this);
//	tmp._day += day;
//	while (tmp._day > GetMonthDay(tmp._year, tmp._month))
//	{
//		tmp._day -= GetMonthDay(tmp._year, tmp._month);
//		天满进月
//		++tmp._month;
//		月满进年
//		if (tmp._month == 13)
//		{
//			tmp._month = 1;
//			++tmp._year;
//		}
//	}
//	return tmp;
//}

// + 复用实现 +=
//Date& Date::operator+=(int day)
//{
//	*this = *this + _day;
//	return *this;
//}


//+= 复用实现 +  
Date Date::operator+(int day) const
{
	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)
		{
			--_year;
			_month = 12;
		}
		_day += GetMonthDay(_year, _month);
	}
	return *this;
}

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

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

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

//d1 - d2
int Date::operator-(const Date& d) const
{
	int flag = 1;
	Date max = *this;
	Date min = d;
	if (*this < d)
	{
		max = d;
		min = *this;
		flag = -1;
	}
	//对于++,前置++的效率更大
	int n = 0;
	while (min != max)
	{
		++min;
		++n;
	}
	return flag * n;
}

// 流插入<<   读
ostream& operator<<(ostream& out, const Date& d)
{
	out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
	return out;
}

// 流提取 >>   写
istream& operator>>(istream& in, Date& d)
{
	while (1)
	{
		cout << "请依次输入年月日:>";
		//默认用空格 或者 换行 分割
		in >> d._year >> d._month >> d._day;
		if (d.CheckDate())
		{
			break;
		}
		else
		{
			cout << "输入的日期非法,请重新输入:"<<endl;
		}
	}
	return in;
}

Date.h

#pragma once
#include <iostream>
#include <assert.h>
using namespace std;

class Date
{
	//友元函数
	friend ostream& operator<<(ostream& out, const Date& d);
	friend istream& operator>>(istream& in, Date& d);
public:
	Date(int year = 1, int month = 1, int day = 1);
	void Print()const;

	//
	Date* operator&();
	const Date* operator&()const;

	bool CheckDate();
	int GetMonthDay(int year, int month)
	{
		static int monthDayArry[13] = { -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 29;
		}
		return monthDayArry[month];
	}
	//运算符重载
	bool operator>(const Date& d) const;
	bool operator>=(const Date& d) const;
	bool operator<(const Date& d) const;
	bool operator<=(const Date& d) const;
	bool operator==(const Date& d) const;
	bool operator!=(const Date& d) const;

	//d1 += 天数
	Date operator+(int day)const;
	Date& operator+=(int day);

	//d1 -= 天数
	Date operator-(int day)const;
	Date& operator-=(int day);

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

	//前置 / 后置 --
	//前置--
	Date& operator--();
	//后置--
	Date operator--(int);

	//d1 - d2
	int operator-(const Date& d) const;

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

// 流插入 <<
ostream& operator<<(ostream& out, const Date& d);

// 流提取 >>
istream& operator>>(istream& in,Date& d);

Test.cpp

#include "Date.h"

void Test1()
{
	// >
	Date d1(2024, 11, 22);
	Date d2(2024, 11, 1);
	Date d3(d1);
	d1.Print();
	d2.Print();
	d3.Print();
	cout << (d2 > d1) << endl;
	cout << (d2 >= d3) << endl;
	cout << (d2 < d1) << endl;
	cout << (d2 <= d1) << endl;
	cout << (d1 == d3) << endl;
	cout << (d1 != d3) << endl;

}

void Test2()
{
	//+ / += 
	//Date d1(2024, 11, 1);
	//Date d2 = d1 += 50;
	//Date d3 = d1 + 50;
	//d1.Print();
	//d2.Print();
	//d3.Print();
	//d1.Print();
	//Date d1(2024, 11, 22);
	//Date d2 = d1 += -50;
	//d1.Print();
	//d2.Print();

	Date d3(2024, 11, 22);
	//Date d4 = d3--;
	//Date d5 = --d3;
	//d4.Print();
	//d5.Print();
	//d3.Print();
	cout << d3;

}

void Test3()
{
	Date d1(2024, 11, 22);
	Date d2(2024, 11, 1);
	cout << d1 << d2 <<" "<<d1;

	cin >> d1 >> d2;
}

void Test4()
{
	Date d1(2024, 2, 29);
	Date d2(2023, 2, 29);

	cin >> d1 >> d2;
	cout << d1 << d2;
}

void Test5()
{
	const Date d1(2024, 2, 29);

	Date d2(2023, 2, 29);
}
int main()
{
	//Test1();
	//Test2();
	//Test3();
	Test4();
	return 0;
}


http://www.kler.cn/a/405952.html

相关文章:

  • 回溯法基础入门解析
  • @Autowired与构造器注入区别,为什么spring推荐使用构造注入而不是Autowired?
  • 最大熵谱估计
  • uniapp input限制输入负数,以及保留小数点两位.
  • 电解车间铜业机器人剥片技术是现代铜冶炼过程中自动化和智能化的重要体现
  • TCP Listen 队列详解与优化指南
  • 关于xftp7 的中文乱码问题
  • C语言执行Lua进行错误处理
  • FPGA 14 ,硬件开发板分类详解,FPGA开发板与普通开发板烧录的区别
  • 优化 Spring Boot 性能
  • ubuntu22.04 android studio老卡
  • 滚珠导轨在极端温度下性能如何?
  • redis6.0之后的多线程版本的问题
  • 泷羽sec学习打卡-网络七层杀伤链1
  • 基于Java Springboot甘肃“印象”网站
  • 机器学习阶段学习Day31
  • 最长回文子串
  • 动态规划 —— 子数组系列-环绕字符串中唯⼀的子字符串
  • 工业相机视场角计算
  • java版工程项目管理系统源码:Spring Cloud与前后端分离的完美结合
  • 可视化建模与UML《协作图实验报告》
  • 五天SpringCloud计划——DAY2之单体架构和微服务架构的选择和转换原则
  • 人工智能在金融领域的应用与风险防范研究
  • java基础概念38:正则表达式3-捕获分组
  • 利用c语言详细介绍下选择排序
  • 单细胞|M3-4. 细胞聚类与轨迹推断