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

C++讲解---什么是静态成员函数

静态成员函数与静态数据成员一样,不依赖于类的实例,不属于各个对象。我们可以通过之前的日期类的闰年判断功能来看一下具体的使用。

1. 日期类复习

日期类的成员

成员类型成员名称作用说明
私有数据成员int y存储公历年份
私有数据成员int m存储月份(1-12)
私有数据成员int d存储日数(1-31)
构造函数Date()默认构造函数
构造函数Date(int, int, int)带参构造函数(支持默认参数)
成员函数year()返回当前年份
成员函数month()返回当前月份
成员函数day()返回当前日数
成员函数preceding_day()返回前一天的日期对象
成员函数to_string()返回日期字符串表示
友元函数operator<<输出流重载(支持cout << date_obj格式)
友元函数operator>>输入流重载(支持cin >> date_obj格式)

日期类的讲解及其代码如下:
创建日期类
代码:

//头文件
#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);
};
//源文件
#include <ctime> // 获取当前日期
#include <sstream>// 字符串流操作
#include <iostream> //输入输出操作
#include "Date.h"using namespace std;//--- Date 的默认构造函数(设置为当前日期)---//
Date::Date() {time_t current = time(NULL);struct tm* local = localtime(&current);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();
}

2. 完善功能后的日期类函数

完善功能后的日期类

成员类型成员名称作用说明
私有数据成员int y存储公历年份
私有数据成员int m存储月份(1-12)
私有数据成员int d存储日数(1-31)
静态数据成员static int dmax[]存储平年各月的天数数组
静态成员函数days_of_month计算指定年份(y)和月份(m)的天数
静态成员函数is_leap(int year)判断指定年份是否为闰年(静态版本)
构造函数Date()默认构造函数
构造函数Date(int, int, int)带参构造函数(支持默认参数)
成员函数year()返回当前年份
成员函数month()返回当前月份
成员函数day()返回当前日数
成员函数is_leap() const判断当前年份是否为闰年(调用静态版本)
成员函数preceding_day()返回前一天的日期对象
成员函数following_day()返回后一天的日期对象
成员函数day_of_year()返回当年内的累计天数
成员函数day_of_week()返回星期几(0=周日,1=周一…)
成员函数to_string()返回日期字符串表示
友元函数operator<<输出流重载(支持cout << date_obj格式)
友元函数operator>>输入流重载(支持cin >> date_obj格式)

这里有两个注意的点:
1. days_of_month,is_leap(int year)是静态成员函数,这两个函数是纯粹的日期计算工具,不依赖或修改任何特定 Date对象的状态(y, m, d),仅通过参数进行运算。所以设计为静态成员函数更加灵活。
2. 这里有两个版本的is_leap()函数,一个为静态成员函数,一个是成员函数,只是调用了静态成员函数is_leap()。那么静态成员函数不需要依赖对象,只需要知道y值即可,而成员函数需要一个具体的对象。具体差别请参考使用示例

代码如下:

// 日期类 Date (第4版: 头文件)
#ifndef ___Class_Date
#define ___Class_Date
#include <string>
#include <iostream>class Date {int y;      // 私有:公历年(1900-9999)int m;      // 私有:月(1-12)int d;      // 私有:日(1-31,根据月份和闰年变化)static int dmax[];  // 静态数组:存储各月最大天数(考虑闰年)static int days_of_month(int y, int m); // 静态方法:计算y年m月的天数public:// 构造函数Date();                             // 默认构造(当前日期)Date(int yy, int mm = 1, int dd = 1); // 带参构造(年月日)// 静态方法:闰年判断static bool is_leap(int year) {return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;}// 访问器(const成员函数)int year() const { return y; }      // 返回年int month() const { return m; }     // 返回月  int day() const { return d; }       // 返回日// 功能方法bool is_leap() const { return is_leap(y); }          // 当前年份是否闰年Date preceding_day() const;                         // 返回前一天的日期Date following_day() const;                          // 返回后一天的日期int day_of_year() const;                             // 返回年内经过天数int day_of_week() const;                             // 返回星期(0=周日,1=周一...)std::string to_string() const;                       // 返回字符串表示(如"2023-12-25")
};// 流操作符重载(非成员函数)
std::ostream& operator<<(std::ostream& s, const Date& x); // 输出日期(格式:yyyy-mm-dd)
std::istream& operator>>(std::istream& s, Date& x);       // 输入日期(格式:yyyy mm dd)#endif
// 日期类 Date(第4版:源文件)
#include <ctime>
#include <sstream>
#include <iostream>
#include "Date.h"
using namespace std;// 静态数据成员初始化(平年各月天数)
int Date::dmax[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};// 静态成员函数:计算指定年月天数(考虑闰年)
int Date::days_of_month(int y, int m) {return dmax[m - 1] + (is_leap(y) && m == 2); // 闰年2月加1天
}// 默认构造函数(设置为当前系统日期)
Date::Date() {time_t current = time(NULL);        // 获取当前时间戳struct tm* local = localtime(&current); // 转换为本地时间结构y = local->tm_year + 1900;          // 年份转换(tm_year从1900起)m = local->tm_mon + 1;              // 月份转换(0~11 → 1~12)d = local->tm_mday;                 // 直接获取日期(1~31)
}// 带参构造函数(年月日)
Date::Date(int yy, int mm, int dd) {y = yy;m = mm;d = dd;
}// 返回年内经过天数(从1月1日起)
int Date::day_of_year() const {int days = d;  // 当前月已过天数for (int i = 1; i < m; i++)         // 累加前m-1个月的天数days += days_of_month(y, i);return days;
}// 返回前一天的日期
Date Date::preceding_day() const {Date temp = *this;                  // 复制当前日期if (temp.d > 1)                     // 简单情况:非月初temp.d--;else if (--temp.m < 1) {            // 跨年到上一年temp.y--;temp.m = 12;temp.d = 31;                    // 12月31日} else {                            // 跨月到上一月temp.d = days_of_month(temp.y, temp.m); // 上一月的最后一天}return temp;
}// 返回后一天的日期  
Date Date::following_day() const {Date temp = *this;                  // 复制当前日期if (temp.d < days_of_month(temp.y, temp.m)) // 简单情况:非月末temp.d++;else if (++temp.m > 12) {           // 跨年到下一年temp.y++;temp.m = 1;temp.d = 1;                     // 1月1日} else {                            // 跨月到下一月temp.d = 1;                     // 下一月的第一天}return temp;
}// 返回字符串表示(格式:yyyy年mm月dd日)
string Date::to_string() const {ostringstream s;s << y << "年" << m << "月" << d << "日";return s.str();
}// 计算星期(Zeller公式:0=周日,1=周一...6=周六)
int Date::day_of_week() const {int yy = y;int mm = m;if (mm == 1 || mm == 2) {           // 1月2月当作前一年的13月14月yy--;mm += 12;}return (yy + yy/4 - yy/100 + yy/400 + (13*mm+8)/5 + d) % 7;
}// 输出流重载(使用to_string格式)
ostream& operator<<(ostream& s, const Date& x) {return s << x.to_string();
}// 输入流重载(格式:yyyy/mm/dd 或 yyyy-mm-dd)
istream& operator>>(istream& s, Date& x) {int yy, mm, dd;char ch;                            // 用于读取分隔符s >> yy >> ch >> mm >> ch >> dd;    // 支持多种分隔符x = Date(yy, mm, dd);               // 构造新日期对象return s;
}
// DateTest.cpp - 日期类Date(第4版)使用示例
#include <iostream>
#include "Date.h"
using namespace std;int main()
{Date today;                             // 创建今天日期对象(自动获取系统日期)cout << "今天的日期:" << today << '\n';  // 输出格式:yyyy年mm月dd日cout << "昨天的日期:" << today.preceding_day() << '\n';cout << "前天的日期:" << today.preceding_day().preceding_day() << '\n';cout << "明天的日期:" << today.following_day() << '\n';cout << "后天的日期:" << today.following_day().following_day() << '\n';cout << "从元旦开始经过了" << today.day_of_year() << "天。\n";cout << "今年" << (today.is_leap() ? "是闰年。" : "不是闰年。") << '\n';int y;cout << "公历年:"; cin >> y;                               // 用户输入任意年份cout << "该年" << (Date::is_leap(y) ? "是闰年。" : "不是闰年。") << '\n';
}
http://www.dtcms.com/a/355021.html

相关文章:

  • 云计算学习100天-第28天
  • 软件测试(三):测试流程及测试用例
  • 如果被控端显示器分辨率是2k,远程控制软件的画质设置是4k,主控端显示器的分辨率是2k,那主控端看到的被控端画面是几k
  • list 手动实现 1
  • IO多路复用---EPOLL
  • 把llamafacoty微调后的模型导出ollama模型文件
  • SPARK入门
  • Python 多版本环境治理理念驱动的系统架构设计——三维治理、四级隔离、五项自治 原则(路径治理升级修订 V 2.0 版)
  • 七牛云实践:我们如何用 AIGC 将产品开发从“人想图”变为“图选图”
  • 使用astah制作专业状态图及C/C++实现解析
  • 随手小记:elementUI的勾选框使用的坑
  • 大模型微调示例五之Llama-Factory_agent_functioncalling
  • 大数据原生集群 (Hadoop3.X为核心) 本地测试环境搭建三
  • 仓颉编程语言:全场景开发的未来选择
  • SAP-ABAP:SAP HANA 架构解析:主从(Scale-Out)与主备(High Availability)架构深度对比
  • 从零开始学习JavaWeb-20
  • 架构评审:构建稳定、高效、可扩展的技术架构(上)
  • 刷题日记0828
  • AMGCL介绍和使用
  • Spark 安装教程与使用指南
  • Jetson(meta‑tegra)升级要点与 doflash.sh 组件清单
  • 嵌入式研发工程师成长路线图,基础入门 → 中级提升 → 高级进阶 → 专家方向
  • 基于 Spring AMQP 的 RabbitMQ 分布式消息系统实战
  • imx6ull-驱动开发篇47——Linux SPI 驱动实验
  • Java全栈工程师的实战面试:从基础到微服务的全面解析
  • 磁力计校准矩阵求解方法解析
  • go grpc使用场景和使用示例
  • python02
  • Codeforces Round 1043 (Div. 3) F. Rada and the Chamomile Valley
  • 02Shell的变量运算以及数据比较