【C++】年月日计算器——操作符重载的应用(含完整代码,简洁)(一)

简介: 【C++】年月日计算器——操作符重载的应用(含完整代码,简洁)

一.流插入,流提取

【流插入的库是在iostream里,流提取的库是在ostream里】

  • 可以支持内置类型是因为在库里面实现了
  • 可以支持自定义类型,是因为人为进行了函数重载

图示:

此时:cout<<d相当于count.operator(d)

1.为什么流插入<<不能写成成员函数

// 流插入不能写成成员函数?
   //因为Date对象默认占用第一个参数,就是做了左操作数
     如果按照正常使用场景实现出来:
    count<<d1;  如果写在成员函数里会表现出 count.operator<<(d)
    访问不了成员
    只有写成
  d1 << cout;   才会在成员函数里表现出 d1.operator<<(count)
    才能进行传参,访问成员

因此为了使用操作合乎习惯,又要让流插入能够访问成员,只能将流插入重载写在类外(虽然流提取不会出现这种情况,为了统一,一并写在类外)


2.流插入写在类外访问类内成员的方法——友元

但是类内的成员是private(私有的),我们可以通过友元(声明操作符重载函数能进入类内访问的权限)


3.代码展示:  

头文件部分:

#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
  {
    cout << _year << "-" << _month << "-" << _day << endl;
  }
  Date(const Date& d)   // 错误写法:(不加引用)编译报错,会引发无穷递归
  {                     // 拷贝构造
    _year = d._year;
    _month = d._month;
    _day = d._day;
  }
  int GetMonthDay(int year, int month);
private:
  int _year;
  int _month;
  int _day;
};
//虽然友元已经声明,但那与函数声明不同,仅是表示权限
//这里还是要再次进行函数声明
ostream& operator<<(ostream& out, const Date& d);
istream& operator>>(istream& in, Date& d);

.c文件部分:

ostream& operator<<(ostream& out, const Date& d)
{
  out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
  return out;
}
istream& operator>>(istream& in, Date& d)
{
  int year, month, day;
  in >> year >> month >> day;
  if (month > 0 && month < 13
    && day > 0 && day <= d.GetMonthDay(year, month))
  {
    d._year = year;
    d._month = month;
    d._day = day;
  }
  else
  {
    cout << "非法日期" << endl;
    assert(false);
  }
  return in;
}

二.基本运算符重载【>,>=,<,<=等】

1.代码展示:

类内声明:

PS:加const,可以让普通变量和const变量都能调用该函数(具体知识点可见YY的C++知识合集博客,关于const的解读)

    bool operator<(const Date& x) const;
   //相当于bool operator<(const Date* const this,const Date& x);,下列声明同理
  bool operator==(const Date& x) const;
  bool operator<=(const Date& x) const;
  bool operator>(const Date& x) const;
  bool operator>=(const Date& x) const;
  bool operator!=(const Date& x) const;

.c文件实现:

PS:在函数实现过程中可以使用技巧"复用"

(多个函数只需要复用一个定义即可,具体代码)

bool Date::operator==(const Date& x) const
{
  return _year == x._year
    && _month == x._month
    && _day == x._day;
}
bool Date::operator<(const Date& x) const
{
  if (_year < x._year)
  {
    return true;
  }
  else if (_year == x._year && _month < x._month)
  {
    return true;
  }
  else if (_year == x._year && _month == x._month && _day < x._day)
  {
    return true;
  }
  return false;
}
//直接利用一个<的复用完成其他定义
bool Date::operator<=(const Date& x) const
{
  return *this < x || *this == x;
}
bool Date::operator>(const Date& x) const
{
  return !(*this <= x);
}
bool Date::operator>=(const Date & x) const
{
  return !(*this < x);
}
bool Date::operator!=(const Date& x) const
{
  return !(*this == x);
}

三.基本运算符重载【+,+=,-,-=】(日期与天数的运算)

1.代码展示:  

类内声明:


PS:加const,可以让普通变量和const变量都能调用该函数(具体知识点可见YY的C++知识合集博客,关于const的解读)


PS:const加在后面表示const Date* this ;表明在该成员函数中不能对类的任何成员进行修改,而+=,-=是要实现对类内成员的改变,因此不能加;

    Date& operator+=(int day);
  Date operator+(int day) const;
  Date& operator-=(int day);
  Date operator-(int day) const;

.c文件实现:

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)
    {
      ++_year;
      _month = 1;
    }
  }
  return *this;
}
// d1 + 100
Date Date::operator+(int day)  const
{
    //复用+=
  Date tmp(*this);
  tmp += day;
  return tmp;
  /*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._year;
      tmp._month = 1;
    }
  }
  return tmp;
  */
}
Date& Date::operator-=(int day)
{
  if (day < 0)
  {
    return *this += -day;
  }
  _day -= day;
  while (_day <= 0)
  {
    --_month;
    if (_month == 0)
    {
      _month = 12;
      --_year;
    }
    _day += GetMonthDay(_year, _month);
  }
  return *this;
}
Date Date::operator-(int day) const
{
  Date tmp = *this;
  tmp -= day;
  return tmp;
}


相关文章
|
3月前
|
C++
C++ 语言异常处理实战:在编程潮流中坚守稳定,开启代码可靠之旅
【8月更文挑战第22天】C++的异常处理机制是确保程序稳定的关键特性。它允许程序在遇到错误时优雅地响应而非直接崩溃。通过`throw`抛出异常,并用`catch`捕获处理,可使程序控制流跳转至错误处理代码。例如,在进行除法运算或文件读取时,若发生除数为零或文件无法打开等错误,则可通过抛出异常并在调用处捕获来妥善处理这些情况。恰当使用异常处理能显著提升程序的健壮性和维护性。
72 2
|
3月前
|
算法框架/工具 C++ Python
根据相机旋转矩阵求解三个轴的旋转角/欧拉角/姿态角 或 旋转矩阵与欧拉角(Euler Angles)之间的相互转换,以及python和C++代码实现
根据相机旋转矩阵求解三个轴的旋转角/欧拉角/姿态角 或 旋转矩阵与欧拉角(Euler Angles)之间的相互转换,以及python和C++代码实现
210 0
|
14天前
|
存储 并行计算 安全
C++多线程应用
【10月更文挑战第29天】C++ 中的多线程应用广泛,常见场景包括并行计算、网络编程中的并发服务器和图形用户界面(GUI)应用。通过多线程可以显著提升计算速度和响应能力。示例代码展示了如何使用 `pthread` 库创建和管理线程。注意事项包括数据同步与互斥、线程间通信和线程安全的类设计,以确保程序的正确性和稳定性。
|
1月前
|
Linux C语言 C++
vsCode远程执行c和c++代码并操控linux服务器完整教程
这篇文章提供了一个完整的教程,介绍如何在Visual Studio Code中配置和使用插件来远程执行C和C++代码,并操控Linux服务器,包括安装VSCode、安装插件、配置插件、配置编译工具、升级glibc和编写代码进行调试的步骤。
172 0
vsCode远程执行c和c++代码并操控linux服务器完整教程
|
1月前
|
存储 编译器 C++
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
51 2
|
2月前
|
编译器 C++
【C++核心】函数的应用和提高详解
这篇文章详细讲解了C++函数的定义、调用、值传递、常见样式、声明、分文件编写以及函数提高的内容,包括函数默认参数、占位参数、重载等高级用法。
22 3
|
2月前
|
C++
继续更新完善:C++ 结构体代码转MASM32代码
继续更新完善:C++ 结构体代码转MASM32代码
|
2月前
|
C++ Windows
HTML+JavaScript构建C++类代码一键转换MASM32代码平台
HTML+JavaScript构建C++类代码一键转换MASM32代码平台
|
2月前
|
C++
2合1,整合C++类(Class)代码转换为MASM32代码的平台
2合1,整合C++类(Class)代码转换为MASM32代码的平台
|
2月前
|
前端开发 C++ Windows
C++生成QML代码与QML里面集成QWidget
这篇文章介绍了如何在C++中生成QML代码,以及如何在QML中集成QWidget,包括使用Qt Widgets嵌入到QML界面中的技术示例。