C++面向对象 - 运算符重载的应用

第1关:日期类的运算符重载

头文件 date.h

复制代码
// 头文件保护宏,防止重复包含
#ifndef DATE_CLASS
#define DATE_CLASS
#include <iostream>
using namespace std;

// Date日期类声明
class Date{
    // 私有成员:年、月、日
    int year,month,day;

    // 私有成员函数
    bool isLeap()const;      // 判断当前年份是否为闰年
    int dayInMonth()const;   // 获取当前月份的总天数
    void normalize();        // 日期标准化:自动修正非法年月日(比如日超过当月天数、月份超出1-12)

public:
    // 构造函数:默认参数 年=1,月=1,日=1
    Date(int y=1,int m=1,int d=1);

    // 关系运算符重载 == < > <= >= !=
    bool operator==(const Date& other)const; // 判断两个日期是否相等
    bool operator<(const Date& other)const;  // 判断当前日期是否早于other日期
    bool operator>(const Date& other)const;  // 判断当前日期是否晚于other日期
    bool operator<=(const Date& other)const; // 判断当前日期是否早于/等于other日期
    bool operator>=(const Date& other)const; // 判断当前日期是否晚于/等于other日期
    bool operator!=(const Date& other)const; // 判断两个日期是否不相等

    // 复合赋值运算符重载:日期增减N天
    Date& operator+=(int days); // 当前日期向后推days天,返回自身引用
    Date& operator-=(int days); // 当前日期向前推days天,返回自身引用

    // 自增运算符重载(日期+1天)
    Date& operator++();    // 前置++:++date,先自增再返回自身
    Date operator++(int); // 后置++:date++,先返回原值再自增

    // 自减运算符重载(日期-1天)
    Date& operator--();    // 前置--:--date,先自减再返回自身
    Date operator--(int);  // 后置--:date--,先返回原值再自减

    // 友元运算符重载
    friend int operator-(const Date& d1,const Date& d2); // 两个日期相减,返回相差天数(d1-d2)
    friend ostream& operator<<(ostream& os,const Date& dt); // 输出流重载 cout << Date对象
    friend istream& operator>>(istream& is,Date& dt);      // 输入流重载 cin >> Date对象
};
#endif

源文件 date.cpp

复制代码
#include"date.h"
using namespace std;

// 判断闰年:能被4整除且不能被100整除,或能被400整除
bool Date::isLeap()const{
    return (year%4==0&&year%100!=0)||(year%400==0);
}

// 获取当月总天数:2月闰年29天,平年28天;其他月份固定天数
int Date::dayInMonth()const{
    int days[]={31,28,31,30,31,30,31,31,30,31,30,31};
    if(month==2&&isLeap())return 29;
    return days[month-1];
}

// 日期标准化函数:自动修正非法日期
void Date::normalize(){
    // 当日数大于当月总天数:进位到下个月
    while(day>dayInMonth()){
        day-=dayInMonth();
        month++;
        // 月份超过12,进位到下一年
        if(month>12){
            month=1;
            year++;
        }
    }
    // 当日数小于1:向上个月借天数
    while(day<1){
        month--;
        // 月份小于1,借到上一年12月
        if(month<1){
            month=12;
            year--;
        }
        day+=dayInMonth();
    }
}

// 构造函数:初始化年月日,调用标准化函数修正非法输入
Date::Date(int y,int m,int d):year(y),month(m),day(d){
    normalize();
}

// ==重载:年月日全部相等才返回true
bool Date::operator==(const Date& other)const{
    return year==other.year&&month==other.month&&day==other.day;
}

// <重载:先比年,年相同比月,月相同比日
bool Date::operator<(const Date& other)const{
    if(year!=other.year)return year<other.year;
    if(month!=other.month)return month<other.month;
    return day<other.day;
}

// >重载:利用<运算符,other早于this等价于this晚于other
bool Date::operator>(const Date& other)const{
    return other<*this;
}

// <=重载:取反 > 运算符
bool Date::operator<=(const Date& other)const{
    return !(other<*this);
}

// >=重载:取反 < 运算符
bool Date::operator>=(const Date& other)const{
    return !(*this<other);
}

// !=重载:取反 == 运算符
bool Date::operator!=(const Date& other)const{
    return !(*this==other);
}

// +=重载:日期向后加days天,标准化后返回自身
Date& Date::operator+=(int days){
    day+=days;
    normalize();
    return *this;
}

// -=重载:日期向前减days天,标准化后返回自身
Date& Date::operator-=(int days){
    day-=days;
    normalize();
    return *this;
}

// 前置++:日期+1天,返回自增后的自身
Date& Date::operator++(){
    *this+=1;
    return *this;
}

// 后置++:先保存当前日期副本,再日期+1天,返回原来的副本
Date Date::operator++(int){
    Date temp=*this;
    *this+=1;
    return temp;
}

// 前置--:日期-1天,返回自减后的自身
Date& Date::operator--(){
    *this-=1;
    return *this;
}

// 后置--:先保存当前日期副本,再日期-1天,返回原来的副本
Date Date::operator--(int){
    Date temp=*this;
    *this-=1;
    return temp;
}

// 友元-重载:计算两个日期相差天数 d1 - d2
int operator-(const Date& d1,const Date& d2){
    Date temp=d2;
    int days=0;
    // 如果d1更早,temp不断往前减,days记负数
    if(d1<d2){
        while(temp>d1){
            --temp;
            days--;
        }
        return days;
    }else{
        // 如果d1更晚,temp不断往后加,days记正数
        while(temp<d1){
            ++temp;
            days++;
        }
        return days;
    }
}

// 输出流重载:打印格式 年-月-日
ostream& operator<<(ostream& os,const Date& dt){
    os<<dt.year<<"-"<<dt.month<<"-"<<dt.day;
    return os;
}

// 输入流重载:读取年、月、日,读取后标准化修正
istream& operator>>(istream& is,Date& dt){
    is>>dt.year>>dt.month>>dt.day;
    dt.normalize();
    return is;
}

主函数 main.cpp

复制代码
#include"date.h"
using namespace std;

int main(){
    Date d1,d2;
    // 输入两个日期
    cin>>d1>>d2;

    // d1向后推2天,输出d1
    d1+=2;
    cout<<d1<<endl;

    // d2向前推3天,输出d2
    d2-=3;
    cout<<d2<<endl;

    // 前置++:d1日期+1,输出新d1
    ++d1;
    cout<<d1<<endl;

    // 后置++:先输出原值,d2再+1
    d2++;
    cout<<d2<<endl;

    // 判断d1和d2大小,输出相差天数
    if(d1==d2){
        cout<<0<<endl;
    }else if(d1<d2){
        cout<<d2-d1<<endl;
    }else{
        cout<<d1-d2<<endl;
    }

    // 前置--:d1先-1,把修改后的d1赋值给d3,输出d3
    Date d3=--d1;
    cout<<d3<<endl;

    // 后置--:先把d2原值赋值给d4,d2再-1,输出d4
    Date d4=d2--;
    cout<<d4<<endl;

    // 判断d3和d4大小,输出相差天数
    if(d3==d4){
        cout<<0<<endl;
    }else if(d3<d4){
        cout<<d4-d3<<endl;
    }else{
        cout<<d3-d4<<endl;
    }

    return 0;
}
相关推荐
福大大架构师每日一题1 小时前
rust 1.96.0 更新:语言、编译器、Cargo、Rustdoc、兼容性全面升级,必看完整解读
android·开发语言·rust
思麟呀1 小时前
C++11并发编程:互斥锁
linux·开发语言·c++·windows
AC赳赳老秦1 小时前
OpenClaw批量任务队列优化:解决任务堆积、执行缓慢、优先级混乱问题
java·大数据·数据库·c++·自动化·php·openclaw
晚风予卿云月1 小时前
《二分答案》算法练习
数据结构·c++·算法·二分·竞赛·算法随笔
郭涤生1 小时前
C++ 各类数据的内存分区与读写性能详解
开发语言·c++
Pluchon1 小时前
萌萌技术分享笔记——Java综合项目
java·开发语言·笔记·git·github·mybatis·postman
j_xxx404_1 小时前
Linux 线程日志系统设计:从策略模式、RAII 到 pthread 线程安全与内核写入路径|附源码
linux·运维·服务器·开发语言·c++·人工智能·策略模式
普马萨特1 小时前
搜索核心算法:从召回到排序
算法·搜索引擎
sheeta19981 小时前
LeetCode 每日一题笔记 日期:2026.05.31 题目:2126. 摧毁小行星
笔记·算法·leetcode