运算符的重载
运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
重载方式:
函数名字为:operator 运算符符号<需要重载的运算符符号>
函数原型:返回值类型 operator操作符(参数列表) int operator==(<参数>)
//如果一个函数的返回值类型是类类型对象的情况下,优先考虑返回引用,不能引用,就值返回 //有个前提:能够返回引用的情况下 //+进行了重载 //只能进行值返回,因为 + 的使用不会改变左右值的内容 Date operator+(int days) { Date temp(*this); //保存了_day temp._day += days; return temp; }
注意:
- 不能通过连接其他符号来创建新的操作符:比如operator@
- 重载操作符必须有一个类类型的参数或者枚举类型的参数用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不能改变其含义。
- 作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数的操作符有一个默认的形参this,限定为第一个形参。
- . * 、:: 、sizeof 、?: 、. 注意以上5个运算符不能重载。这个经常在笔试选择题中出现。
问:什么是运算符重载?为什么需要运算符重载?
答:对于定义类型的对象,编译器不支持该对象直接进行一些运算符操作,需要他通过某种方式让编译器支持自定义类型对象的一些运算符操作。
原因:
- 编译器不支持
- 提高代码可读性
#include<stdio.h> #include<iostream> using namespace std; //运算符重载 class Date { public: //1.无参构造函数 Date() {} //2.带参构造函数 Date(int year, int month, int day) { _year = year; _month = month; _day = day; } //如果一个函数的返回值类型是类类型对象的情况下,优先考虑返回引用,不能引用,就值返回 //有个前提:能够返回引用的情况下 //+进行了重载 //只能进行值返回,因为 + 的使用不会改变左右值的内容 Date operator+(int days) { Date temp(*this); //保存了_day temp._day += days; return temp; //返回对象就是this } //== 重载 bool operator==(const Date& d) //当前对象的年 = d 对象的年 { return _year == d._year && _month == d._month && _day == d._day; } //!= 重载 bool operator!=(const Date& d) { return !(*this == d); } =(赋值运算符)重载,没有返回值 //void operator=(const Date& d){ // _year = d._year; // _month = d._month; // _day = d._day; //} //=(赋值运算符)重载,没有返回值 //if 判断是不是给自己赋值 //给引用参数 效率高, //const 不用修改有操作数的内容 Date& operator=(const Date& d) { if (this != &d) { _year = d._year; _month = d._month; _day = d._day; } return* this; //返回函数对象比函数生命周期长 所以可以进行引用返回 } //前置++ //++d1 Date& operator++(){ _day += 1; return *this; //返回当前对象,引用返回 } //后置++ //d1++ //加 int 实现函数重载 Date operator++(int){ Date temp(*this); _day += 1; return temp; //返回函数栈里面的对象,就是值返回 //int 固定的 } private: int _year; int _month; int _day; }; int main(){ int a = 1; int b = 2; int c = a + b; a = b = c; //重载之后这样也可以 Date d1(2019, 5, 16); Date d2; Date d3; //调用没有返回值的重载: //d3 = d2 = d1; //这样就是错的 因为赋值过程是:从右往左依次来做, //d2.operator=(d1); //d3.operator=(上条语句的结果,因为没有返回值所以是错的) //调用返回值的重载 d3 = d2 = d1; //这样就是对的 //Date类 不重载加号用不了 d2 = d1 + 1; //重载之后成功 d2 = d1; //也可以赋值成功 if (d1 == d2){ cout << "d1==d2" << endl; } else{ cout << "错" << endl; } system("pause"); return 0; }
const成员
const修饰的类成员:成员函数、成员变量
const修饰成员函数:将const修饰的类成员函数称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this 指针,表明在该成员函数中不能对类的任何成员进行修改。
//const修饰成员函数 //const Date * const this:this所指向的内容不能改 //实际修饰该成员函数隐含的this指针 void PrintDate()const { cout << _year << "-" << _month << "-" << _day << endl; }
在 const 修饰的成员函数中:不能修改成员变量。
注:那个成员变量要被修改,就要在成员变量之前加 mutable 。就可以进行更改了。
private: int _year; int _month; mutable int _day; //const修饰成员函数 //const Date * const this:this所指向的内容不能改 //实际修饰该成员函数隐含的this指针 void PrintDate()const { this->_day += 1; //被mutable修饰了,所以可以修改 cout << _year << "-" << _month << "-" << _day << endl; }
问: const对象可以调用非const成员函数吗?
答:不可以。
//问: const对象可以调用非const成员函数吗? const Date d1(2019, 5, 16); d1.PrintDate(); //错的 void PrintDate() { //改成员函数是可以修改当前对象成员的 cout << _year << "-" << _month << "-" << _day << endl; } //但是:这是不可以被修改的,就是会有矛盾 const Date d1(2019, 5, 16);
问:非const对象可以调用const成员函数吗?
答:对的,非const对象是可以不修改的。
//问:非const对象可以调用const成员函数吗? Date d1(2019, 5, 16); d1.PrintDate(); //对的 void PrintDate() const{ //改成员函数是不可以修改当前对象成员的 cout << _year << "-" << _month << "-" << _day << endl; } //但是:这是可以被不修改的,所以就可以 Date d1(2019, 5, 16);
问:const成员函数内可以调用其它的非const成员函数吗?
答:错的。
//问:const成员函数内可以调用其它的非const成员函数吗? void PrintDate()const { //错的 PrintDate(); } //因为 PrintDate() 会修改成员变量,void PrintDate()const 不能修改,就是矛盾,有问题 void PrintDate() const{ //改成员函数是不可以修改当前对象成员的 cout << _year << "-" << _month << "-" << _day << endl; } void PrintDate() { //改成员函数是可以修改当前对象成员的 cout << _year << "-" << _month << "-" << _day << endl; }
问:非const成员函数内可以调用其它的const成员函数吗?
答:对的。
//问:非const成员函数内可以调用其它的const成员函数吗? void PrintDate() { //错的 PrintDate() const; } //因为 PrintDate() 会修改成员变量,void PrintDate()const 不能修改,但是也是成员函数,只是只读。 //只读的放在可读可写的里面就是安全的 void PrintDate() const{ //改成员函数是不可以修改当前对象成员的 cout << _year << "-" << _month << "-" << _day << endl; } void PrintDate() { //改成员函数是可以修改当前对象成员的 cout << _year << "-" << _month << "-" << _day << endl; }
注:这是属于函数重载的。
void PrintDate() { cout << _year << "-" << _month << "-" << _day << endl; } void PrintDate()const { cout << _year << "-" << _month << "-" << _day << endl; }