二、类和对象
13.运算符重载
赋值运算符重载
我们之前学了一个拷贝构造函数,本质上就是创建一个对象,该对象初始化为一个已经存在的对象的数据。
// 拷贝构造 Date d1(d2);
而赋值运算符重载则是重载一个赋值运算符 “=” ,然后让两个已经存在的对象,一个拷贝赋值给另一个。
// 赋值运算符重载 d1 = d2;
普通赋值运算符是支持连续赋值的,所以我们重载后的也需要连续赋值,即函数需要返回左值。
赋值运算符的实现:
#include<iostream> using namespace std; class Date { public: Date(int year = 1111, int month = 1, int day = 1) { _year = year; _month = month; _day = day; } ~Date() {} void Print() { cout << _year << "-" << _month << "-" << _day << endl; } // 拷贝构造函数 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; } return *this; } private: int _year; int _month; int _day; }; int main() { Date d1(2222, 2, 2); Date d2(d1); d1 = d2; return 0; }
赋值运算符重载函数也是6个默认的成员函数之一,所以我们不写编译器也会自动生成。它跟拷贝构造函数很相似,对内置类型进行浅拷贝处理,对自定义类型去调用它的赋值运算符重载函数。由于也是浅拷贝,所以涉及到堆上的空间开辟时,不能使用编译器自动生成的赋值运算符重载函数。
14. 日期类的实现
这个日期类的实现将会将之前学的所有知识进行融合。我们来进行标准的声明和定义分离。
Date.h头文件
头文件里只包括声明
#pragma once #include<iostream> #include<assert.h> using namespace std; class Date { public: // 构造函数的声明 Date(int year = 1111, int month = 1, int day = 1); // 重载运算符的声明 bool operator<(const Date& d); bool operator<=(const Date& d); bool operator>(const Date& d); bool operator>=(const Date& d); bool operator==(const Date& d); bool operator!=(const Date& d); // 日期加天数 Date& operator+=(int day); Date operator+(int day); Date operator-(int day); Date& operator-=(int day); // ++d1 Date& operator++(); // d1++ 为了跟前置++区分,后置++强行增加了一个int形参,构成重载区分 Date operator++(int); Date& operator--(); Date operator--(int); // 日期减日期 int operator-(const Date& d); int GetMonthDay(int year, int month) { // 断言月份错误 assert(month >= 1 && month <= 12); // 静态变量只初始化一次 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]; } // 打印日期的声明 void Print(); private: int _year; int _month; int _day; };
Date.cpp源文件
这个文件里是各个函数的定义。
#include"Date.h" // 构造函数的定义 Date::Date(int year, int month, int day) { _year = year; _month = month; _day = day; } // 重载运算符的定义 bool Date::operator<(const Date& d) { if (_year < d._year) { return true; } else if (_year == d._year) { if (_month < d._month) { return true; } else if (_month == d._month) { return _day < d._day; } } return false; } bool Date::operator<=(const Date& d) { return *this < d || *this == d; } bool Date::operator>(const Date& d) { return !(*this <= d); } bool Date::operator>=(const Date& d) { return !(*this < d); } bool Date::operator==(const Date& d) { return _year == d._year && _month == d._month && _day == d._day; } bool Date::operator!=(const Date& d) { return !(*this == d); } Date& Date::operator+=(int 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) { // 拷贝构造,避免修改原来的日期 Date tmp(*this); // 使用重载后的+= tmp += day; // 局部对象不能引用返回 return tmp; } Date Date::operator-(int day) { // tmp是刚创建的对象,所以这是拷贝构造而不是赋值 Date tmp = *this; tmp -= day; return tmp; } Date& Date::operator-=(int day) { _day -= day; while (_day <= 0) { --_month; if (_month == 0) { --_year; _month = 12; } _day += GetMonthDay(_year, _month); } return *this; } // ++d1 Date& Date::operator++() { *this += 1; return *this; } // d1++ 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) { int flag = 1; Date max = *this; Date min = d; if (*this < d) { flag = -1; max = d; min = *this; } int n = 0; while (max != min) { ++min; ++n; } return flag * n; } // 打印日期的定义 void Date::Print() { cout << _year << "-" << _month << "-" << _day << endl; }
test.cpp源文件
#include"Date.h" int main() { Date d1(2222, 2, 2); d1.Print(); Date d2 = d1 + 10; d2.Print(); cout << (d1 > d2) << endl; Date d3; d3.Print(); d3 += 10000; d3.Print(); --d3; d3.Print(); cout << (d1 - d3) << endl; return 0; }
结果: