上一节讲解中有讲解如何创建一个类,现在我们由最简单的定义到添加函数功能将一个可以实际应用的日期类创建并应用一下。
1.实现日期存储功能
我们先来将日期数据存储起来,不用实现日期的有效性检查、日期运算等更复杂的功能。
- 构造函数:用于初始化日期类的私有成员变量(年、月、日)。
- 私有成员变量:y、m、d分别用于存储年、月、日。
- 注释:代码中包含了中文注释,解释了每个成员变量的含义。
cpp
// 日期类 Date(第 1 版:源文件)
#include "Date.h"
//-- 类 Date 的构造函数 ----
Date::Date(int yy, int mm, int dd)
{
y = yy; // 公历年
m = mm; // 月
d = dd; // 日
}
2.构造函数指定默认初始值
在这里可以使用构造函数给到默认初始值。
cpp
// 日期类 Date(第 1 版:源文件)
#include "Date.h"
//-- 类 Date 的构造函数 ----
Date::Date(int yy=1, int mm=1, int dd=1)
//给到默认初始值都为1
{
y = yy; // 公历年
m = mm; // 月
d = dd; // 日
}
3.设定const成员函数
如果想增加纪念日的日期记录功能,最好是使用const成员函数来建不可修改的对象。
cpp
// 日期类 Date(添加成员函数调用次数)
#include <iostream>
using namespace std;
class Date {
int y; // 公历年
int m; // 月
int d; // 日
public:
Date(int yy = 1, int mm = 1, int dd = 1) // 构造函数
int year() const {return y;} // 返回年
int month() const { return m;} // 返回月
int day() const { return d;} // 返回日
};
使用日期类存储纪念日----------------------------------------------------------
int main() {
const Date birthday(1963, 11, 18); // 生日
cout << "birthday = " << birthday.year() << "年"
<< birthday.month() << "月"
<< birthday.day() << "日\n";
}
4. 将系统日期添加为默认初始值
如果我们想把程序运行时的时间设置为这个类的默初始值的话,可以使用这个ctime头文件获取当前时间戳,然后将这个时间戳转化为现有的日期类的初始值。
同时这里简单做一下改动,把原来的类分为 头文件 和 源文件。
cpp
//头文件------------------------------------------
#include <string>
#include <iostream>
class Date {
private:
int y; // 公历年
int m; // 月
int d; // 日
public:
Date();
Date(int yy, int mm , int dd );
int year() const { return y; }
int month() const { return m; }
int day() const { return d; }
};
//源文件----------------------------------------------------------------
#include <ctime>//<ctime> 用于处理时间相关功能
#include <iostream>
#include "Date.h"
using namespace std;
//--- Date 的默认构造函数(设置为当前日期)---
//如果你需要创建一个表示当前日期的对象,就使用默认构造函数 Date()
Date::Date() {
//time函数固定用法,获取系统日期时间戳
time_t current = time(NULL);
struct tm* local = localtime(¤t);
y = local->tm_year + 1900;
m = local->tm_mon + 1;
d = local->tm_mday;
}
//--- Date 的构造函数(设置为指定的年、月、日)---//
//如果你需要创建一个表示特定日期的对象,就使用带参数的构造函数 Date(int yy, int mm, int dd)。
Date::Date(int yy, int mm, int dd) {
y = yy;
m = mm;
d = dd;
}
5. 添加可以返回前一天日期的函数
先分析一下,如果想要添加返回前一天日期的功能,那么我们需要添加一个判断,就是当d = 1时,需要返回上一个月的最后一天;当m = 1且d= 1时,需要返回上一年的最后一天。而每个月的最后一天是不一样的,这里我们需要设计一下判断条件,并且返回到上月的最后一天。
可以使用this指针创建当前日期的副本解决这个问题。
cpp
//--- 返回前一天的日期(不支持闰年的处理)---//
Date Date::preceding_day() const {
int dmax[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // 各月的天数
Date temp = *this; // 使用this指针创建当前日期的副本
if (temp.d > 1)// 当"日"的值大于 1 时,只需递减 temp.d;否则必须递减 temp.m,回到前一个月。
temp.d--;
else {
//先判断是不是月份为1
if (--temp.m < 1) {// 如果月份减到 0,年份减 1,月份设为 12;
//"--temp.m<1"的意思是先自减再比较是否小于1.
temp.y--;
temp.m = 12;
}
temp.d = dmax[temp.m - 1];
}
return temp;
}
它首先创建当前日期的一个副本,然后检查当前日期是否是当月的第一天。如果是,则将日期设置为上个月的最后一天;如果不是,则日期减 1。这个函数不支持闰年的处理,所以 2 月的天数固定为 28 天。
6.增加可以输出日期字符串的函数
如果想要将一个实体对象,输出为"yy 年 mm 月 dd 日 ",我们可以添加函数to_string(),在函数中使用字符串流ostringstream(执行字符串流的输出)来控制输出什么样的日期形式。字符串流它们属于 std 命名空间。
cpp
//--- 返回字符串表示 ---//
string Date::to_string() const {
ostringstream s;//执行字符串流的输出
s << y << "年" << m << "月" << d << "日";
return s.str();
然后我们需要在头文件中,将这个已经更改后的输出流声明一下
cpp
std::ostream& operator<<(std::ostream& s, const Date& x);
std::istream& operator>>(std::istream& s, Date& x);
7. 日期类最终形式
头文件如下:
cpp
#include <string>
#include <iostream>
class Date {
private:
int y; // 公历年
int m; // 月
int d; // 日
public:
Date();
Date(int yy, int mm = 1, int dd = 1);
int year() const { return y; }
int month() const { return m; }
int day() const { return d; }
Date preceding_day() const;
std::string to_string() const;
std::ostream& operator<<(std::ostream& s, const Date& x);
std::istream& operator>>(std::istream& s, Date& x);
};
源文件如下:
cpp
#include <ctime> // 获取当前日期
#include <sstream>// 字符串流操作
#include <iostream> //输入输出操作
#include "Date.h"
using namespace std;
//--- Date 的默认构造函数(设置为当前日期)---//
Date::Date() {
time_t current = time(NULL);
struct tm* local = localtime(¤t);
y = local->tm_year + 1900;
m = local->tm_mon + 1;
d = local->tm_mday;
}
//--- Date 的构造函数(设置为指定的年、月、日)---//
Date::Date(int yy, int mm, int dd) {
y = yy;
m = mm;
d = dd;
}
//--- 返回前一天的日期(不支持闰年的处理)---//
Date Date::preceding_day() const {
int dmax[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
Date temp = *this;
if (temp.d > 1)
temp.d--;
else {
if (--temp.m < 1) {
if (temp.m == 0) {
temp.y--;
temp.m = 12;
}
temp.d = dmax[temp.m - 1];
}
}
return temp;
}
//--- 返回字符串表示 ---//
string Date::to_string() const {
ostringstream s;
s << y << "年" << m << "月" << d << "日";
return s.str();
}