C++第九弹---类与对象(六)

这篇具有很好参考价值的文章主要介绍了C++第九弹---类与对象(六)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

C++第九弹---类与对象(六),C++详解,c++,c语言,算法,数据结构

个人主页: 熬夜学编程的小林

💗系列专栏: 【C语言详解】 【数据结构详解】【C++详解】

日期类

1、日期类的分析和设计

1.1、日期类的功能说明

1.2、日期类的分析和设计

1.2.1、数据结构的分析

1.2.2、文件结构设计

2、日期类的结构分析

2.1、创建日期类及声明

2.2、在类内实现获取天数函数

2.3、在类外实现构造函数

 2.4、在类外实现拷贝构造函数

2.5、在类外实现赋值运算符重载

2.6、在类外实现日期的比较

2.7、在类外实现日期+-天数

2.8、在类外实现日期-日期

3、日期类分文件的代码实现

3.1、test.cpp

3.2、Date.cpp

3.3、Date.h

总结


1、日期类的分析和设计

1.1、日期类的功能说明

创建一个日期类,通过运算符重载实现对日期的相关计算以及比较功能。包含如下:

1、重载日期的大小比较(>  ==  >=  <  <=  !=)

2、重载赋值操作符

3、重载日期+= / -=天数

4、重载日期+ / -天数

5、重载日期前置++ / --

6、重载日期后置++ / --

7、重载日期 - 日期

1.2、日期类的分析和设计

1.2.1、数据结构的分析

创建一个日期类,成员变量包括年月日(最好将成员变量权限设置为private,这样在类外就无法访问类中成员变量,起到一定的保护作用),内部实现获取某年某月的天数的函数,为了实现分文件设计,类中只需声明构造函数,拷贝构造函数以及日期类需要实现的重载函数

1.2.2、文件结构设计

之前我们在C语言中学习了多文件的形式对函数的声明和定义,这里我们C++实践⼀下,我们设计三个文件:

test.cpp    //文件中日期类的测试逻辑
Date.cpp  //文件中写类中重载函数的实现等
Date.h      //文件中写日期类需要的数据类型和函数声明等


建议:写一些代码就测试一些代码。

2、日期类的结构分析

2.1、创建日期类及声明

注意:在实现操作函数之前判断是否会修改成员变量的值,如果不需要改变成员变量的值,可以使用const修饰来保护代码。

class Date
{
public:
	// 构造函数
	Date(int year, int month, int day);
	// 拷贝构造函数
	// d2(d1)
	Date(const Date& d);
	// 赋值运算符重载
	// d2 = d3 -> d2.operator=(&d2, d3)
	// >运算符重载
	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;

	// 操作赋值操作符
	Date& operator=(const Date& d);
	// 日期+=天数
	Date& operator+=(int day);
	// 日期+天数
	Date operator+(int day) const;
	// 日期-天数
	Date operator-(int day) const;
	// 日期-=天数
	Date& operator-=(int day);
	// 前置++
	Date& operator++();
	// 后置++
	Date operator++(int);
	// 后置--
	Date operator--(int);
	// 前置--
	Date& operator--();

	// 日期-日期 返回天数
	int operator-(const Date& d) const;
private:
	int _year;
	int _month;
	int _day;
};

2.2、在类内实现获取天数函数

根据我们日期的规则,只有2月的天数是不同的,此时我们可以创建一个数组来存放对应年份月份的天数,如果是平年的2月则为28天,如果是闰年的2月则为29天,因此我们在创建完数组之后判断一下即可。

uu们可能不太了解什么情况是闰年,闰年的规则如下:

1、每4年为一个闰年,每100年为平年。即年份%4==0且年份%100!=0.

2、每400年为一个闰年。即年份%400==0。

代码实现如下:

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

uu们可能一开始就写出上面的代码, 那么这个代码有没有问题呢?或者说效率高不高呢?

小林的答案是有问题,效率也没有尽可能进行优化,原因如下:

1、可以将该函数加上const进行修饰,因为后面重载函数的实现中可能会被const修饰,那么如果没有const修饰,可以调用该函数,如果有const修饰的函数就不能调用此函数。但是该函数加上const修饰,不管是否有const进行修饰函数,都可以调用。

2、没有对月份进行判断,我们的月份只有1到12月,但是我们不做判断传入负数或者大于12的月份,因此此处可以用我们C语言所学习的断言语句。

3、创建的数组是在栈区创建的,但是获取天数的函数会经常调用,那么调用一次函数就会创建一个栈空间,效率很低,此处我们可以使用static修饰,将数组放在静态区,那么就只会创建一次。

4、判断是否为闰年时,我们可以做小小的调整,根据C语言学习的短路求值原则,与运算中左边的为假则结束运算,因此我们可以将容易判断的条件放在左边。

经过调整的获取某年某月的天数函数如下:

	// 获取某年某月的天数
	int GetMonthDay(int year, int month) const
	{
		assert(month > 0 && month < 13);//月份的判断
		// 因为该函数会经常调用,但是数组的值一直是不需要变化的,因此可以使用静态数组
		// 好处是在静态区只会创建一份变量
		static int days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
		if ((month == 2) && ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0) ))
			return 29;
		return days[month];
	}

注意:该函数实现的年数对负数是不支持的,1582年也可能会出现问题,因为1582年少了10天。 

2.3、在类外实现构造函数

注意:在类外实现类中声明的构造函数需要使用域作用符。

// 构造函数
Date::Date(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;
}

 2.4、在类外实现拷贝构造函数

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

2.5、在类外实现赋值运算符重载

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

	return *this;
}

2.6、在类外实现日期的比较

// >运算符重载
bool Date::operator>(const Date& d) const
{
	if (_year > d._year)
		return true;
	else if (_year == d._year)
	{
		if (_month > d._month)
			return true;
		else if (_month == d._month)
		{
			if (_day > d._day)
				return true;
		}
	}
	return false;
}
// ==运算符重载
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 || *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 !(*this == d);
}

注意:此处使用的思想是先实现两个比较操作,然后通过位运算操作符实现其他的操作。

2.7、在类外实现日期+-天数

// 日期+=天数
Date& Date::operator+=(int day)
{
	_day += day;
	while (_day > GetMonthDay(_year, _month))
	{
		_day -= GetMonthDay(_year, _month);
		++_month;
		if (_month == 13)
		{
			++_year;
			_month = 1;
		}
	}
	return *this;
}
// 日期+天数 ---使用前面实现的+=运算符重载实现
//Date Date::operator+(int day) const
//{
//	Date temp(*this);
//	temp += day;
//	return temp;
//}
 
// 日期+天数 ---直接实现
Date Date::operator+(int day) const
{
	Date temp(*this);
	temp._day += day;
	while (temp._day > GetMonthDay(_year, _month))
	{
		temp._day -= GetMonthDay(temp._year, temp._month);
		++temp._month;
		if (temp._month == 13)
		{
			++temp._year;
			temp._month = 1;
		}
	}
	return temp;
}
// 日期-=天数
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) const
{
	//Date temp(*this);
	Date temp(*this);
	temp -= day;

	return temp;
}

 日期-天数 ---直接实现
//Date Date::operator-(int day) const
//{
//	//Date temp(*this);
//	Date temp(*this);
//	temp._day -= day;
//	while (temp._day <= 0)
//	{
//		--temp._month;
//		if (temp._month == 0)
//		{
//			--temp._year;
//			temp._month = 12;
//		}
//		temp._day += GetMonthDay(temp._year, temp._month);
//	}
//	return temp;
//}

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

2.8、在类外实现日期-日期

思想:计算第一个类与第二个类的差值,我们在前面已经实现了++和比较操作,此处只需要先判断哪个日期类大,小的日期类++多少次等于大的日期类就是相差的天数。

// 日期-日期 返回天数
int Date::operator-(const Date& d) const
{
	int flag = 1;
	Date max = *this;
	Date min = d;
	if (*this < d)
	{
		flag = -1;
		max = d;
		min = *this;
	}
	int n = 0;
	while (min != max)
	{
		min++;
		n++;
	}
	return n * flag;
}

3、日期类分文件的代码实现

3.1、test.cpp

#define _CRT_SECURE_NO_WARNINGS
#include "Date.h"

int main()
{
	Date d1(2022, 1, 1);
	d1 += 1;

	Date d2(2022, 1, 2);
	d2 = d2 + 10;

	Date d3(2022, 1, 3);
	d3 -= 2;
	
	Date d4(2022, 1, 4);
	d4 = d4 - 10;

	Date d5(2022, 1, 5);
	Date d6 = d5--;

	//Date d6 = d5.operator--(10);  //后置--

	Date d7(2022, 1, 18);
	Date d8(2022, 1, 8);

	cout << (d7 - d8) << endl;

	return 0;
}

3.2、Date.cpp

#define _CRT_SECURE_NO_WARNINGS
#include "Date.h"


// 构造函数
Date::Date(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;
}
// 拷贝构造函数
// d2(d1)
Date::Date(const Date& d)
{
	_year = d._year;
	_month = d._month;
	_day = d._day;
}
// 赋值运算符重载
// d2 = d3 -> d2.operator=(&d2, d3)
Date& Date::operator=(const Date& d)
{
	_year = d._year;
	_month = d._month;
	_day = d._day;

	return *this;
}

// >运算符重载
bool Date::operator>(const Date& d) const
{
	if (_year > d._year)
		return true;
	else if (_year == d._year)
	{
		if (_month > d._month)
			return true;
		else if (_month == d._month)
		{
			if (_day > d._day)
				return true;
		}
	}
	return false;
}
// ==运算符重载
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 || *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 !(*this == d);
}


// 日期+=天数
Date& Date::operator+=(int day)
{
	_day += day;
	while (_day > GetMonthDay(_year, _month))
	{
		_day -= GetMonthDay(_year, _month);
		++_month;
		if (_month == 13)
		{
			++_year;
			_month = 1;
		}
	}
	return *this;
}
// 日期+天数 ---使用前面实现的+=运算符重载实现
//Date Date::operator+(int day) const
//{
//	Date temp(*this);
//	temp += day;
//	return temp;
//}
 
// 日期+天数 ---直接实现
Date Date::operator+(int day) const
{
	Date temp(*this);
	temp._day += day;
	while (temp._day > GetMonthDay(_year, _month))
	{
		temp._day -= GetMonthDay(temp._year, temp._month);
		++temp._month;
		if (temp._month == 13)
		{
			++temp._year;
			temp._month = 1;
		}
	}
	return temp;
}
// 日期-=天数
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) const
{
	//Date temp(*this);
	Date temp(*this);
	temp -= day;

	return temp;
}

 日期-天数 ---直接实现
//Date Date::operator-(int day) const
//{
//	//Date temp(*this);
//	Date temp(*this);
//	temp._day -= day;
//	while (temp._day <= 0)
//	{
//		--temp._month;
//		if (temp._month == 0)
//		{
//			--temp._year;
//			temp._month = 12;
//		}
//		temp._day += GetMonthDay(temp._year, temp._month);
//	}
//	return temp;
//}

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



// 日期-日期 返回天数
int Date::operator-(const Date& d) const
{
	int flag = 1;
	Date max = *this;
	Date min = d;
	if (*this < d)
	{
		flag = -1;
		max = d;
		min = *this;
	}
	int n = 0;
	while (min != max)
	{
		min++;
		n++;
	}
	return n * flag;
}

3.3、Date.h

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

class Date
{
public:
	// 获取某年某月的天数
	int GetMonthDay(int year, int month) const
	{
		assert(month > 0 && month < 13);
		// 因为该函数会经常调用,但是数组的值一直是不需要变化的,因此可以使用静态数组
		// 好处是在静态区只会创建一份变量
		static int days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
		if ((month == 2) && ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)))
			return 29;
		return days[month];
	}
	// 构造函数
	Date(int year, int month, int day);
	// 拷贝构造函数
	// d2(d1)
	Date(const Date& d);
	// 赋值运算符重载
	// d2 = d3 -> d2.operator=(&d2, d3)
		// >运算符重载
	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;

	// 操作赋值操作符
	Date& operator=(const Date& d);
	// 日期+=天数
	Date& operator+=(int day);
	// 日期+天数
	Date operator+(int day) const;
	// 日期-天数
	Date operator-(int day) const;
	// 日期-=天数
	Date& operator-=(int day);
	// 前置++
	Date& operator++();
	// 后置++
	Date operator++(int);
	// 后置--
	Date operator--(int);
	// 前置--
	Date& operator--();

	// 日期-日期 返回天数
	int operator-(const Date& d) const;
private:
	int _year;
	int _month;
	int _day;
};

总结


本篇博客就结束啦,谢谢大家的观看,如果公主少年们有好的建议可以留言喔,谢谢大家啦!文章来源地址https://www.toymoban.com/news/detail-848174.html

到了这里,关于C++第九弹---类与对象(六)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 深入篇【C++】类与对象:运算符重载详解 -上

    深入篇【C++】类与对象:运算符重载详解 -上

    内置类型(int /double…… )是可以之间进行运算符之间的比较的,因为编译器知道它们之间的比较规则,可以之间转化为指令。 那如果自定义类型能否之间进行运算符之间的比较呢?当然不能了,因为编译器是不知道这个自定义类型的规则是什么,不知道如何进行比较。 1.内置

    2024年02月03日
    浏览(13)
  • C++初阶类与对象(二):详解构造函数和析构函数

    C++初阶类与对象(二):详解构造函数和析构函数

    上次为类与对象开了一个头:C++初阶类与对象(一):学习类与对象、访问限定符、封装、this指针 今天就来更进一步 如果一个类中什么成员都没有,简称为空类。 空类中并不是什么都没有,任何类在什么都不写时,编译器会 自动生成上面6个默认成员函数 。 默认成员函数

    2024年01月19日
    浏览(16)
  • ​​力扣刷MySQL-第九弹(详细讲解)

    ​​力扣刷MySQL-第九弹(详细讲解)

     🎉欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克🍹 ✨博客主页:小小恶斯法克的博客 🎈该系列文章专栏:力扣刷题讲解-MySQL 🍹文章作者技术和水平很有限,如果文中出现错误,希望大家能指正🙏 📜 感谢大家的关注! ❤️ 目录  变更性别

    2024年02月22日
    浏览(14)
  • 【Linux系统编程】第九弹---权限管理操作(下)

    【Linux系统编程】第九弹---权限管理操作(下)

      ✨ 个人主页:   熬夜学编程的小林 💗 系列专栏:   【C语言详解】   【数据结构详解】 【C++详解】 【Linux系统编程】 目录 1、目录权限 2、粘滞位 总结 首先提出一个问题,删除一个文件需要什么权限呢??? 回答这个问题之前我们先通过命令来看看现象。 通过上面的

    2024年04月28日
    浏览(13)
  • 【浅尝C++】继承机制=>虚基表/菱形虚继承/继承的概念、定义/基类与派生类对象赋值转换/派生类的默认成员函数等详解

    【浅尝C++】继承机制=>虚基表/菱形虚继承/继承的概念、定义/基类与派生类对象赋值转换/派生类的默认成员函数等详解

    🏠专栏介绍:浅尝C++专栏是用于记录C++语法基础、STL及内存剖析等。 🎯每日格言:每日努力一点点,技术变化看得见。 我们生活中也有继承的例子,例如:小明继承了孙老师傅做拉面的手艺。继承就是一种延续、复用的方式。C++为了提高代码的可复用性,引入了继承机制,

    2024年04月10日
    浏览(16)
  • C++初阶学习第三弹——类与对象(上)——初始类与对象

    C++初阶学习第三弹——类与对象(上)——初始类与对象

    前言: 在前面,我们已经初步学习了C++的一些基本语法,比如内敛函数、函数重载、缺省参数、引用等等,接下来我们就将正式步入C++的神圣殿堂,首先,先给你找个对象 目录 一、类与对象是什么? 二、类的各部分组成 1、类的定义 2、类的访问限定符及封装 3、类的作用域

    2024年04月26日
    浏览(12)
  • [C++] 类与对象(上)

    [C++] 类与对象(上)

      目录 1、前言 2、类的引入 3、类的定义 3.1 类的两种定义方式 4、类的访问限定符 5、类的作用域 6、类的实例化 7、类对象模型 7.1 内存对齐规则 7.1 类对象的存储方式 8、this指针 8.1 this指针的特性 8.2 this指针是否可以为空 C语言是 面向过程 的, 关注 的是 过程 ,分析出求解

    2024年02月15日
    浏览(8)
  • C++ 类与对象(下)

    C++ 类与对象(下)

    目录 1. 再谈构造函数 1.1 构造函数体赋值  1.2 初始化列表  1.3 explicit  2. static成员 2.1 概念 2.2 特性  3.友元 3.1友元函数   3.2 友元类 4. 内部类 5.匿名对象  6.拷贝对象时的一些编译器优化  7. 再次理解类和对象 1. 再谈构造函数 2. Static成员 3. 友元 4. 内部类 5.匿名对象

    2024年02月19日
    浏览(7)
  • C++ 类与对象(上)

    C++ 类与对象(上)

    目录 本节目标  1.面向过程和面向对象初步认识  2.类的引入  3.类的定义 4.类的访问限定符及封装 4.1 访问限定符 4.2 封装 5. 类的作用域 6. 类的实例化  7.类对象模型 7.1 如何计算类对象的大小 7.2 类对象的存储方式猜测 7.3 结构体内存对齐规则  8.this指针 8.1 this指针的引出

    2024年02月19日
    浏览(5)
  • 【C++】类与对象(中)

    【C++】类与对象(中)

    目录 1. 类的6个默认成员函数 2. 构造函数 2.1 概念 2.2 特性 3. 析构函数 3.1 概念 3.2 特性 4. 拷贝构造函数 4.1 概念 4.2 特征 5. 赋值运算符重载 5.1 运算符重载 5.2 赋值运算符重载 5.3 前置++和后置++重载 6. const成员 7. 取地址及const取地址操作符重载 如果一个类中什么成员都没有,

    2024年02月05日
    浏览(7)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包