【C++】3.类和对象(中)

1.类的6个默认成员函数

一个类什么都没有不是空类 我们没有写相关函数 但编译器会自动生成6个默认函数

2.构造函数

1°概念

构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,保证每个数据成员都有一个合适的初始值,并且在对象的生命周期内只调用一次。

#include <iostream>
using namespace std;

class Date
{
public:
    //构造函数->初始化函数
    //构造函数->在对象构造时调用的函数 这个函数完成初始化工作
    //构造函数可以重载
    Date(int year, int month, int day)
    {
        _year = year;
        _month = month;
        _day = day;
    }
    //不想传参 默认初始化
    Date()
    {
        _year = 0;
        _month = 1;
        _day = 1;
    }
    void Print()
    {
        cout << _year << "/" << _month << "/" << _day << endl;
    }
private:
    int _year;
    int _month;
    int _day;
};

int main()
{
    //对象实例化时自动调用
    Date d1(2023,2,10);//有参
    d1.Print();
    Date d2;//无参 不能加括号 
    d2.Print();
    return 0;
}

这样写有参和无参就很傻 能不能合并?

可以 利用缺省函数 当你不传参就可以用缺省值进行初始化

Date(int year = 0, int month = 1, int day = 1)
{
    _year = year;
    _month = month;
    _day = day;
}

2°特性

构造函数是特殊的成员函数,需要注意的是,构造函数的虽然名称叫构造,但是需要注意的是构造函数的主要任务并不是开空间创建对象,而是初始化对象

  • 函数名与类名相同。
  • 无返回值。
  • 对象实例化时编译器自动调用对应的构造函数。
  • 构造函数可以重载。(无参和带参)
  • 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。

调用默认构造函数:1.无参 2.全缺省 3.编译器自动生成的

特点:不用传参 三个只能有一个

无参初始化和全缺省不能同时存在 调用时会有歧义

  • 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认成员函数。

  • 成员变量的命名风格 有_ 初始化时year = year就很傻 需要区分

    扫描二维码关注公众号,回复: 14588149 查看本文章

我们会自己实现构造函数 那么编译器的构造函数是不是没有用?

有用 存在即合理

#include <iostream>
using namespace std;

class Time
{
public:
    Time()
    {
        _hour = 0;
        _minute = 0;
        _second = 0;
        cout << "Time()" << endl;
    }
private:
    int _hour;
    int _minute;
    int _second;
};

class Date
{
public:
    //Date(int year, int month, int day)
    //{
    //	_year = year;
    //	_month = month;
    //	_day = day;
    //}
    //Date()
    //{
    //	_year = 0;
    //	_month = 1;
    //	_day = 1;
    //}
    void Print()
    {
        cout << _year << "/" << _month << "/" << _day << endl;
    }
private:
    int _year;
    int _month;
    int _day;
    Time _t;
};

int main()
{
    Date d1;//调用编译器自动生成的
    d1.Print();//随机值 并不是什么都没有干
    //1°针对内置类型的成员变量没有做处理
    //2°针对自定义类型的成员变量 调用它的构造函数初始化/析构
    //自己定义了一个初始化的 编译器不会再帮你定义
    //比如定义了一个要传参的 不传参的也要自己定义
    return 0;
}

3.析构函数

1°概念

析构函数:与构造函数功能相反,析构函数不是完成对象的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成类的一些资源清理工作。

2°特性

  • 析构函数名是在类名前加上字符 ~
  • 无参数无返回值。
  • 一个类有且只有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。
  • 对象生命周期结束时,C++编译系统系统自动调用析构函数。
  • 编译器生成的默认析构函数,对会自定类型成员调用它的析构函数。
#include <iostream>
using namespace std;

class Date
{
public:
    Date(int year = 0, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
        cout << "Date()" << endl;
    }
    void Print()
    {
        cout << _year << "/" << _month << "/" << _day << endl;
    }
    //~析构
    ~Date()
    {
        cout << "~Date()" << endl;
    }
private:
    int _year;
    int _month;
    int _day;
};

class Stack
{
public:
    Stack(int n = 10)
    {
        _a = (int*)malloc(sizeof(int) * n);
        _size = 0;
        _capacity = n;
        cout << "Stack()" << endl;
    }
    //清理动态开辟空间
    ~Stack()
    {
        free(_a);
        _a = nullptr;
        _size = 0;
        _capacity = 0;
        cout << "free:_a" << endl;
    }
private:
    int* _a;
    int  _size;
    int  _capacity;
};

int main()
{
    //析构:对象生命周期到了以后 自动调用 完成对象的资源清理工作 不是完成d1和d2的销毁
    Date d1;
    Date d2;
    Stack s1;
    Stack s2;
    //析构是倒着析构的 后进去的先析构
    return 0;
}

4.拷贝构造函数

1°概念

构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

2°特征

  • 拷贝构造函数是构造函数的一个重载形式。
  • 拷贝构造函数的参数只有一个且必须使用引用传参使用传值方式会引发无穷递归调用。(传参的过程是一个赋值过程 传值的话会再次调用构造函数)

  • 若未显示定义,系统生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝我们叫做浅拷贝,或者值拷贝。
  • 既然有了默认生成的拷贝函数 那么我们还需要自己实现拷贝构造函数吗? 需要 有的地方需要深拷贝
#include <iostream>
using namespace std;

class Date
{
public:
    //构造函数
    Date(int year = 0, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
    }
    //Date d2(d1) 拷贝构造函数
    //Date(Date d) 无穷递归(画图)
    //调用的时候调用的是拷贝构造
    //调用的过程中先传参 
    //传参的过程是一个初始化过程 赋值
    //赋值完后又再次进行拷贝构造

    //没有引用
    //Date d = d1;(然后再次进行拷贝构造)
    //引用解决这个问题
    //Date& d = d1;
    //d是d1的别名
    Date(const Date& d)//const可保护 不可改变原来的d1
    {
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }
    void Print()
    {
        cout << _year << "-" << _month << "-" << _day << endl;
    }
private:
    int _year;
    int _month;
    int _day;
};

int main()
{
    Date d1(2023,2,10);
    Date d2(d1);//拷贝构造
    d1.Print();
    d2.Print();
    return 0;
}

5.赋值运算符重载

1°运算符重载

C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

函数名字为:关键字operator后面接需要重载的运算符符号。

函数原型:返回值类型 operator操作符(参数列表)

注意:

  • 不能通过连接其他符号来创建新的操作符:比如operator@
  • 重载操作符必须有一个类类型或者枚举类型的操作数
  • 用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不 能改变其含义
  • 作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数的操作符有一个默认的形参this,限定为第一个形参
  • .* 、:: 、sizeof 、?: 、. 注意以上5个运算符不能重载。这个经常在笔试选择题中出现。

编译器会自己做一些事

比如说实现了operator==这个功能 最后调用函数的时候

直接d1 == d2;判断即可 编译器会转化成operator(d1,d2);

#include <iostream>
using namespace std;

class Date
{
public:
    Date(int year = 0, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
    }
    Date(const Date& d)
    {
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }
    void Print()
    {
        cout << _year << "-" << _month << "-" << _day << endl;
    }
//private:
    int _year;
    int _month;
    int _day;
};

//运算符有几个操作数:operator重载的函数就有几个参数
bool operator==(const Date& d1, const Date& d2)
{
    //这里需要去掉private
    return d1._year  == d2._year
        && d1._month == d2._month
        && d1._day    == d2._day;you
}

//自定义类型是不能用运算符的 要用就实现重载函数
//自定义类型用的时候等价于调用这个重载函数

int main()
{
    Date d1(2023, 2, 10);
    Date d2(2023, 2, 11);
    //比如Date的对象想比较大小相等
    //自定义类型 还是要自己来比
    //运算符函数重载
    d1 == d2;//编译如何调用->这里编译器会转换成opeartopr==(d1,d2); 就是一个函数调用
    //operator==(d1, d2);//可读性差
    //这两个是一样的
    return 0;
}

如何不去掉private并且实现功能?

写一个成员函数 注意有一个隐含的this指针 所以参数只用写一个

外面可以访问public 里面public可以访问private

解决在外面访问不了private的问题

写:bool operator==(const Date& d)

隐含:bool operator==(Date*this,const Date& d)

写:d1 == d2;//d1给到this指针 d2给到别名d进行判断

隐含:d1.opertor==(&d1,d2);

真正:operator==(d2)

#include <iostream>
using namespace std;

class Date
{
public:
    Date(int year = 0, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
    }
    Date(const Date& d)
    {
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }
    void Print()
    {
        cout << _year << "-" << _month << "-" << _day << endl;
    }
    //d1 == d2;
    //隐含:d1.operator==(&d1,d2);
    //&d1就是this指针 d2给到别名d
    //真正写:operator==(d2);
    bool operator==(const Date& d)//(Date* this,const Date& d)
    {
        //这里需要去掉private
        return _year  == d._year
            && _month == d._month
            && _day   == d._day;
    }
    //d1 > d2
    bool operator>(const Date& d)
    {
        if (_year > d._year)
            return true;
        else if (_year == d._year && _month > d._month)
            return true;
        else if (_year == d._year && _month == d._month && _day > d._day)
            return true;
        else
            return false;
    }
private:
    int _year;
    int _month;
    int _day;
};

int main()
{
    Date d1(2023, 2, 10);
    Date d2(2023, 2, 11);
    cout << (d1 == d2) << endl;
    cout << (d1 > d2) << endl;
    return 0;
}

2°赋值运算符重载

class Date
{ 
public:
  Date(int year = 1900, int month = 1, int day = 1)
  {
    _year = year;
    _month = month;
    _day = day;
  }
 
  Date (const Date& d)
  {
    _year = d._year;
    _month = d._month;
    _day = d._day;
  }
 
  Date& operator=(const Date& d)
  {
    if(this != &d)
    {
      _year = d._year;
      _month = d._month;
      _day = d._day;
    }
  }
private:
  int _year;
  int _month;
  int _day;
};
  • 参数类型
  • 返回值
  • 检测是否自己给自己赋值
  • 返回*this
  • 一个类如果没有显式定义赋值运算符重载,编译器也会生成一个,完成对象按字节序的值拷贝。

和拷贝构造一样 编译器默认生成的都是值拷贝 有时候需要深拷贝 我们还是要自己实现

6.浅拷贝vs深拷贝

我们如果没有实现默认函数

编译器会默认生成相关函数

  • 编译器生成的默认构造函数和析构函数

    针对成员变量:内置类型就不处理 自定义类型会调这个成员的构造和析构

  • 编译器生成拷贝构造和operator= 会完成按字节的值拷贝(浅拷贝)

    浅拷贝:将对象按一个一个字节拷贝过去 也就是说有些类

    我们是不需要去实现拷贝构造和operate=的 因为编译器默认生成的就够用

所以 我们写拷贝构造的意义是什么?

下面程序会崩溃 原因是什么?

#include <iostream>
using namespace std;

class Stack
{
public:
    //构造
    Stack(int n = 10)
    {
        _a = (int*)malloc(sizeof(int) * n);
        _size = 0;
        _capacity = n;
        cout << "Stack()" << endl;
    }
    //析构
    ~Stack()
    {
        if (_a != nullptr)//还是会崩溃 制空的时st2这个指针 还是会找到st1
        {
            free(_a);
            _a = nullptr;
            _size = 0;
            _capacity = 0;
            cout << "free:_a" << endl;
        }
    }
private:
    int* _a;
    int  _size;
    int  _capacity;
};

int main()
{
    Stack st1(10);
    Stack st2(st1);//拷贝构造
    Stack st3(30);//构造
    st1 = st3;//赋值 operator=
    //浅拷贝问题
    //当赋值和拷贝构造的时候 指针赋给指针 此时两个指针指向同一块空间
    //出作用域后开始析构
    //st2析构 free(st2._a) st1析构 free(st1._a) 再次释放同一块空间 崩溃
    //崩溃原因:同一块空间释放两次
    //如果不写析构 内存泄漏
    //解决:深拷贝 值拷贝过来并且指向一块新的空间
}

浅:p1 p2指向同一块空间 当调用析构函数的时候导致多次释放空间

深:多次释放空间也不会受影响 两块空间不同

所以我们有时候要自己实现拷贝构造或者operator=

7.const成员

将const修饰的类成员函数称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。

  1. const对象可以调用非const成员函数吗?
  2. 非const对象可以调用const成员函数吗?
  3. const成员函数内可以调用其它的非const成员函数吗?
  4. 非const成员函数内可以调用其它的const成员函数吗?

1:可以 2:不可以 3:可以 4:不可以

const->const 不能放大权限

非const->非const/const

  • const Date* p1
  • Date const* p2
  • Date* const p3

三者const修饰的分别是什么

1和2的const修饰指针指向的对象

3的const修饰的是指针本身

看const后面是什么即可

  • const该如何使用呢?

当this指向的内容在函数里面不再修改 就可以加上const

8.取地址和const取地址操作符重载

#include <iostream>
using namespace std;

class Date
{
public:
    Date(int year = 0, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
    }
    void Print() const
    {
        cout << _year << "-" << _month << "-" << _day << endl;
    }
    //&重载
    Date* operator&()
    {
        cout << "operator&()" << endl;
        return this;
    }
    //const&
    const Date* operator&() const //最前面const保持类型一样才能返回
    {
        cout << "operator&() const" << endl;
        return this;
    }
private:
    int _year;
    int _month;
    int _day;
};

int main()
{
    Date d1;
    Date d2;
    const Date d3;
    //取地址默认可以用 自己写也可以
    cout << &d1 << endl;
    cout << &d2 << endl;
    cout << &d3 << endl;//放大了 const到非const
    //实际上不用写 编译器默认写
    //返回空可以写
    return 0;
}

这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需要重载,比如想让别人获取到指定的内容

9.实现一个完整的日期类

声明和定义分开

Date.h

#include <iostream>
using namespace std;

class Date
{
public:
    //得到每个月的天数(自己写)
    int GetMonthDay(int year, int month) const;
    //构造(有默认的)
    Date(int year = 0, int month = 1, int day = 1);
    //拷贝构造(有默认的)
    Date(const Date& d);
    //赋值重载(有默认的)
    Date& operator=(const Date& d);
    //运算操作符重载(自己写)
    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+=(int day);
    Date operator+(int day) const;
    Date& operator-=(int day);
    Date operator-(int day) const;
    Date& operator++();
    Date operator++(int);
    Date& operator--();
    Date operator--(int);
    //日期-日期(自己写)
    int operator-(const Date& d) const;
    //打印(自己写)
    void Print() const;
private:
    int _year;
    int _month;
    int _day;
};

1°GetMonthDay

int Date::GetMonthDay(int year, int month) const
{
    static int monthDays[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
    if (month == 2 && (year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
    {
        return 29;
    }
    return monthDays[month];
}

利用数组来获取

2°构造函数

Date::Date(int year, int month, int day) //缺省参数声明给了就行
{
    if (year >= 0
        && month >= 1 && month <= 12
        && day >= 1 && day <= GetMonthDay(year, month))
    {
        _year = year;
        _month = month;
        _day = day;
    }
    else
    {
        cout << "非法日期" << endl;
    }
}

要在范围内初始化

3°拷贝构造

Date::Date(const Date& d)
{
    _year = d._year;
    _month = d._month;
    _day = d._day;
}

this指针不能加const 对应的年月日会被修改

4°operator=

Date& Date::operator=(const Date& d)
{
    if (this != &d)
    {
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }
    return *this;
}

引用返回 提高效率 加一个判断条件 防止自己给自己赋值

5°operator<

bool Date::operator<(const Date& d) const
{
    if (_year < d._year)
        return true;
    else if (_year == d._year && _month < d._month)
        return true;
    else if (_year == d._year && _month == d._month && _day < d._day)
        return true;
    else
        return false;
}

年小就是小

年等就比月 月小就是小

年等月等就比天 天小就是小

6°operator==

bool Date::operator==(const Date& d) const
{
    return _year == d._year && _month == d._month && _day == d._day;
}

7°operator<=

bool Date::operator<=(const Date& d) const
{
    return *this < d || *this == d;
}

小于等于->小于或者等于->复用已经实现的<和==

注意是看*this this指向的年月日

8°operator>

bool Date::operator>(const Date& d) const
{
    return !(*this <= d);
}

复用<= 加上取反

9°operator!=

bool Date::operator!=(const Date& d) const
{
    return !(*this == d);
}

复用== 加上取反

10°operator+=

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;
}

先加天 再减去本月的天 月++ 如果月==13 那就年++ 然后月变为1

循环条件是天数>本月的天数

11°operator+

Date Date::operator+(int day) const
{
    Date ret(*this);
    ret += day;
    return ret;
}

+和+=/-和-=的区别:

+/-是在d1上加减 但d1不变 需要中间变量

+=/-=直接在d1上加减

拷贝构造给ret+直接复用

12°operator-=

Date& Date::operator-=(int day)
{
    if (day < 0)
    {
        return *this += -day;
    }
    _day -= day;
    while (_day < 0)
    {
        --_month;
        if (_month == 0)
        {
            --_year;
            _month = 12;
        }
        _day += GetMonthDay(_year, _month);
    }
    return *this;
}

先减天 天如果小于0 就月-- 如果月==0 就减年 再加上这个月的天数

循环条件就是天<0

13°operator-

Date Date::operator-(int day) const
{
    Date ret(*this);
    ret -= day;
    return ret;
}

复用即可

注意operator+和operator-都不能引用返回

本身ret这个变量在栈上 出了这个函数就销毁了 不能再使用这块空间

14°opeartor++

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

Date Date::operator++(int)//后置++
{
    Date tmp(*this);
    *this += 1;
    return tmp;
}

后置加一个int参数 区分前置++和后置++

15°operator--

Date& Date::operator--()
{
    *this -= 1;
    return *this;
}

Date Date::operator--(int)
{
    Date tmp = *this;
    *this -= 1;
    return tmp;
}

16°日期-日期

看成小的日期不断++并计数

int Date::operator-(const Date& d) const//const Date* this
{
    int flag = 1;
    Date max = *this;
    Date min = d;
    if (*this < d)//这里小于开始调不动 const <那里是非const
    {
        max = d;
        min = *this;
        flag = -1;
    }
    int n = 0;
    while (min != max)
    {
        ++min;
        ++n;
    }
    return n * flag;
}

17°打印

void Date::Print() const
{
    cout << _year << "-" << _month << "-" << _day << endl;
}

18°const添加情况

结论:什么时候会给成员函数加const-> 只要成员函数中不需要改变成员变量最好都加上const 好处:const对象和非const对象都可以调用 加在参数后面的const修饰的是隐含的*this

10.日期类代码

Date.h

#include <iostream>
using namespace std;

class Date
{
public:
    //得到每个月的天数(自己写)
    int GetMonthDay(int year, int month) const;
    //构造(有默认的)
    Date(int year = 0, int month = 1, int day = 1);
    //拷贝构造(有默认的)
    Date(const Date& d);
    //赋值重载(有默认的)
    Date& operator=(const Date& d);
    //运算操作符重载(自己写)
    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+=(int day);
    Date operator+(int day) const;
    Date& operator-=(int day);
    Date operator-(int day) const;
    Date& operator++();
    Date operator++(int);
    Date& operator--();
    Date operator--(int);
    //日期-日期(自己写)
    int operator-(const Date& d) const;
    //打印(自己写)
    void Print() const;
private:
    int _year;
    int _month;
    int _day;
};

Date.cpp

#define _CRT_SECURE_NO_WARNINGS 1

#include "Date.h"

//加一个Date::类
int Date::GetMonthDay(int year, int month) const
{
    static int monthDays[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
    if (month == 2 && (year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
    {
        return 29;
    }
    return monthDays[month];
}

Date::Date(int year, int month, int day) //缺省参数声明给了就行
{
    if (year >= 0
        && month >= 1 && month <= 12
        && day >= 1 && day <= GetMonthDay(year, month))
    {
        _year = year;
        _month = month;
        _day = day;
    }
    else
    {
        cout << "非法日期" << endl;
    }
}

Date::Date(const Date& d)
{
    _year = d._year;
    _month = d._month;
    _day = d._day;
}

bool Date::operator<(const Date& d) const//*this不修改
{
    if (_year < d._year)
        return true;
    else if (_year == d._year && _month < d._month)
        return true;
    else if (_year == d._year && _month == d._month && _day < d._day)
        return true;
    else
        return false;
}

Date& Date::operator=(const Date& d)
{
    if (this != &d)//防止自己给自己赋值
    {
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }
    return *this;//返回的是对应的年月日 *this
}

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)
{
    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;
}

Date Date::operator+(int day) const
{
    Date ret(*this);
    ret += day;
    return ret;
}

Date& Date::operator-=(int day)
{
    if (day < 0)
    {
        return *this += -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 ret(*this);
    ret -= day;
    return ret;
}

Date& Date::operator++()
{
    *this += 1;
    return *this;
}

Date Date::operator++(int)
{
    Date tmp(*this);
    *this += 1;
    return tmp;
}

Date& Date::operator--()
{
    *this -= 1;
    return *this;
}

Date Date::operator--(int)
{
    Date tmp = *this;
    *this -= 1;
    return tmp;
}

int Date::operator-(const Date& d) const//const Date* this
{
    int flag = 1;
    Date max = *this;
    Date min = d;
    if (*this < d)//这里小于开始调不动 const <那里是非const
    {
        max = d;
        min = *this;
        flag = -1;
    }
    int n = 0;
    while (min != max)
    {
        ++min;
        ++n;
    }
    return n * flag;
}

void Date::Print() const
{
    cout << _year << "-" << _month << "-" << _day << endl;
}

Test.cpp

#include "Date.h"
int main()
{
    Date d1(2022, 2, 20);
    d1.Print();
    Date d2(2023, 2, 10);
    d2.Print();
    Date d3(2023, 4, 20);
    //只要实现一个<=或者>= 其他就可以进行复用
    cout << (d1 < d2) << endl;
    cout << (d1 > d2) << endl;
    cout << (d1 == d2) << endl;
    cout << (d1 != d2) << endl;
    cout << (d1 <= d2) << endl;
    cout << (d1 >= d2) << endl;
    
    //+
    Date d4 = d1 + 1000;
    d4.Print();
    
    //+=
    d2 += 1000;
    d2.Print();
    
    //=
    d3 = d1;//这是operator= d3已经存在 赋值操作
    d3.Print();

    //-
    Date d5 = d1 - 10;
    d5.Print();

    //-=
    Date d6(d1);
    d6 -= 10;
    d6.Print();

    //++
    Date d7= ++d1;
    d7.Print();
    Date d8= d1++;
    d8.Print();
    d1.Print();
    
    //--
    Date d9 = --d1;
    Date d10 = d1--;
    d9.Print();
    d10.Print();
    d1.Print();

    //日期-日期
    d1.Print();
    d2.Print();
    cout << d1 - d2 << endl;
    cout << d2 - d1 << endl;

    return 0;
}

【C++】3.类和对象(中) 完

猜你喜欢

转载自blog.csdn.net/szh0331/article/details/129155611