C++拷贝构造函数和运算符重载--2
https://developer.aliyun.com/article/1424586
二,运算符重载
引入:
在内置类型中,系统给我们自动定义了很大运算符,如:+、-、*、/、++、--、>等。这些内置类型和内置类型运算符的使用都是系统定义好的,可直接使用。现在问题来了,自定义类型要想使用这些运算符又当如何?由于自定义类型是我们自己定义的,系统不知道其结构,所以无法直接供我们使用,但C++为了增强代码的可读性引入了运算符重载的概念,可让自定义类型也使用这些运算符。运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
运算符重载的定义:
函数名:关键字operator后面接需要重载的运算符符号。
函数原型:返回值类型 operator操作符(参数列表)。
这里有以下5个注意:
1,不能通过连接其他符号来创建新的操作符:比如operator@
2,重载操作符必须有一个类类型参数
3,用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其+本身的含义
4,作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this指针。
5,“ .* :: sizeof ?: . ” 注意这5个运算符不能重载。这个经常在笔试选择题中出现。
在类的内部定义
第一个参数为this指针 // '='操作符,返回类型为类类型Date的引用 Date& operator=(const Date& d); Date& Date::operator=(const Date& d);//此种情况是在类中声明,在外部实现,用限定符说明是类对象中的成员函数 // "+="操作符,返回类型为类类型Date的引用 Date& operator+=(int day); Date& Date::operator+=(int day);//此种情况是在类中声明,在外部实现,用限定符说明是类对象中的成员函数 // '+'操作符,返回类型为类类型Date的引用 Date operator+(int day); Date Date::operator+(int day);//此种情况是在类中声明,在外部实现,用限定符说明是类对象中的成员函数 // '-'操作符,返回类型为类类型Date的引用 Date operator-(int day); Date Date::operator-(int day);//此种情况是在类中声明,在外部实现,用限定符说明是类对象中的成员函数 // "-="操作符,返回类型为类类型Date的引用 Date& operator-=(int day); Date& Date::operator-=(int day);//此种情况是在类中声明,在外部实现,用限定符说明是类对象中的成员函数
在类的外部定义
没有默认参数,需要把类写入形参中 // "+="操作符,返回类型为类类型Date的引用 Date& operator+=(const Date& d1, int day); // '+'操作符,返回类型为类类型Date的引用 Date operator+(const Date& d1, int day); // '-'操作符,返回类型为类类型Date的引用 Date operator-(const Date& d1, int day); // "-="操作符,返回类型为类类型Date的引用 Date& operator-=(const Date& d1, int day);
运用细节演示:
(1)首先,我们先对“ >,<,>=,<=,==,!= ”这几个简单运算符在类对象内定义进行演示和解说。
#include <iostream> #include <assert.h> using namespace std; //再次提醒一下,类对象中的成员函数第一个默认参数为this,且指向此对象,下面运用时就不做说明 class Date { public: // 全缺省的构造函数 Date(int year = 1900, int month = 1, int day = 1) { _year = year; _month = month; _day = day; } // ==运算符重载 bool operator==(const Date& d) { return _year == d._year && _month == d._month && _day == d._day; } // !=运算符重载 bool operator != (const Date& d) { return !(*this == d); } // >运算符重载 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; return false; } // >=运算符重载 bool operator >= (const Date& d) { return *this > d || *this == d; } // <运算符重载 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; return false; } // <=运算符重载 bool operator <= (const Date& d) { return *this < d || *this == d; } private: int _year; int _month; int _day; }; int main() { Date d1; Date d2(2023, 10, 16); cout << (d1 > d2) << endl;//d1 > d2等效于d1.operator>(d2),这两个表达的意思一样 cout << d1.operator>(d2) << endl; return 0; }
在上面代码中要说明的是在运算符表示过程中,我们即可用函数来表示运算符的含义,也可直使用运算符的形式表示含义。
在上面的运算符函数中: d1 > d2等效于d1.operator(d2) d1 == d2等效于d1.operator(d2) 上面的输出流中之所以(d1 > d2)用括号括起来是因为“ << ”操作符的运算级别高,会先与之运算。
(2)接下来我们对“ +,-,+=,-= ”这几个简单运算符在类对象内定义进行演示和解说。
#include <iostream> #include <assert.h> using namespace std; class Date { public: // 获取某年某月的天数 int GetMonthDay(int year, int month) { assert(year >= 1 && (month >= 1 && month <= 12)); int MonthDays[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; if ((month == 2) && ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0))) return 29; return MonthDays[month]; } // 全缺省的构造函数 Date(int year = 1900, int month = 1, int day = 1) { _year = year; _month = month; _day = day; } // 日期-天数 Date operator-(int day) { _day -= day; while (_day < 0) { if (_month == 1) { _year--; if (_year < 0) { perror("Date Count Error:"); exit(-1); } _month = 12; } else { _month--; } _day += GetMonthDay(this->_year, this->_month); } return *this; } // 日期-=天数 Date& operator-=(int day) { Date DateCopy(*this); //用临时对象返回,相当于函数的返回,需要有个对象去接收,而改变的只是临时对象 //像直接使用类d1 -= 5,表达的只是此函数的功能,d1的值不会改变,若是d1 = d1 -= 5将会改变 //DateCopy = DateCopy.operator-(day); //return DateCopy; //this指针直接指向的是此对象(即此类),用this指针来改变相当于直接改变了d1,类似于达到了改变d1的效果 *this = DateCopy.operator-(day); return *this; } // 日期+=天数 Date& operator+=(int day) { _day += day; while (_day > GetMonthDay(this->_year, this->_month)) { _day -= GetMonthDay(this->_year, this->_month); _month++; if (_month > 12) { _year++; _month -= 12; } } return *this; } // 日期+天数 Date operator+(int day) { Date DateCopy(*this); DateCopy.operator+=(day); return DateCopy; } // 日期-日期 返回天数 int operator-(const Date& d) { int YearDay = 0, MonthDay = 0, Day = _day - d._day; while (--_month) { MonthDay += GetMonthDay(_year, _month); } int month = d._month; while (--month) { MonthDay -= GetMonthDay(d._year, month); } _year--; int year = d._year - 1; for (int YearCount = _year - year; YearCount > 0; YearCount--) { YearDay += 365; if ((_year % 400 == 0) || ((_year % 4 == 0) && (_year % 100 != 0))) YearDay += 1; _year--; } return YearDay + MonthDay + Day; } void Print() { cout << _year << "/" << _month << "/" << _day << endl; } private: int _year; int _month; int _day; }; int main() { Date d1(2023, 10, 16); Date d2; //+=和+运算符重载 //这里要说明的是,由于"+="没有返回值,所以在函数对象内部改变的时候一定要用this指针来改变,this指针指向d1 d1 += 365; cout << "d1重载d1+=365: "; d1.Print(); d2 = d1 + 23; cout << "d2重载d2=d1+23: "; d2.Print(); //-=和-的运算符重载 //"-="运算符与"+="同理 d1 -= 365; cout << "d1重载d1-=365: "; d1.Print(); d2 = d1 - 365; cout << "d2重载d2=d1-365: "; d2.Print(); //日期-日期的运用 cout << "d2-d1: " << d2 - d1 << endl; return 0; }
这里要注意的是函数的返回类型,“ +=,-= ”运算一般是不需要返回类型的,所以在内部实现要用this访问,从而间接实现原对象的运算。“ +,- ”操作符要有返回类型去接收,可直接返回临时对象。
C++拷贝构造函数和运算符重载--4 https://developer.aliyun.com/article/1424601?spm=a2c6h.13148508.setting.29.214f4f0emw3QR7