1.赋值运算符重载
1.1 运算符重载
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名字为:关键字operator后面接需要重载的运算符符号。
函数原型:返回值类型 operator操作符(参数列表)
#include<iostream>
using namespace std;
class Date
{
public:
Date(int y = 1, int m = 1, int d = 1)
{
int _y;
int _m;
int _d;
}
bool isEqual(const Date& d)
{
return _y == d._y
&&_m == d._m
&&_d == d._d;
}
//成员函数都会有一个隐藏的this指针
//运算符重载函数作为成员函数,参数列表中显示定义的参数个数
//需要比实际参数少一个
bool operator==(const Date& d)
{
return _y == d._y
&&_m == d._m
&&_d == d._d;
}
private:
int _y;
int _m;
int _d;
};
//运算符重载
//函数名:operator==
//bool operator==(const Date& d1, const Date& d2)
//{
//
//}
//内置类型的逻辑不能修改=======》运算符的所有参数都为类型
//int operator(int a, int b)
//{
// return a*b;
//}
void test()
{
Date d1(2020,12,10);
Date d2(2020, 11,10);
//判断日期对象是否相等
/*if (d1.isEqual(d2))
{
}*/
//调用运算符重载函数的完整形式
if (d1.operator==(d2))
//如果运算符重载函数不是成员函数
//if (operator==(d1,d2))
//简写形式:可读性高
//if(d1==d2)
{
cout << "==" << endl;
}
else
{
cout << "!=" << endl;
}
}
int main()
{
test();
system("pause");
return 0;
}
注意:
1.不能通过连接其他符号来创建新的操作符:比如operator@
2.重载操作符必须有一个类类型或者枚举类型的操作数用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不 能改变其含义
3.作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数的操作符有一个默认的形参this,限定为第一个形参
4.* 、:: 、sizeof 、?: 、. 注意以上5个运算符不能重载
1.2 赋值运算符重载
#include<iostream>
using namespace std;
struct A
{
void operator=(const A& a)
{
cout << "A operator=" << endl;
}
};
class Date
{
public:
Date(int y = 1, int m = 1, int d = 1)
{
int _y;
int _m;
int _d;
}
bool isEqual(const Date& d)
{
return _y == d._y
&&_m == d._m
&&_d == d._d;
}
Date(const Date& d)
{
_y = d._y;
_m = d._m;
_d = d._d;
cout << "Date(const Date& d)" << endl;
}
//成员函数都会有一个隐藏的this指针
//运算符重载函数作为成员函数,参数列表中显示定义的参数个数
//需要比实际参数少一个
bool operator==(const Date& d)
{
return _y == d._y
&&_m == d._m
&&_d == d._d;
}
void operator=(const Date& d)
{
//判断对象是否是同一个对象:通过指针判断
if (this != &d) //地址是否相同
{
_y = d._y;
_m = d._m;
_d = d._d;
cout << "operator=" << endl;
}
}
Date& operator=(const Date& d)
{
//判断对象是否是同一个对象:通过指针判断
if (this != &d) //地址是否相同
{
_y = d._y;
_m = d._m;
_d = d._d;
cout << "operator=" << endl;
}
return *this;
}
private:
int _y;
int _m;
int _d;
};
void test()
{
Date d1(2021, 3, 21);
Date d2(2021, 3, 22);
Date d3(2021, 3, 23);
//赋值:调用赋值运算符重载函数:修改已经存在的对象内容
d2 = d1;
d2.operator=(d3);
d2 = d2;
d1 = d3;
d2 = d1;
}
Date& operator=(const Date& d)
{
//判断对象是否是同一个对象:通过指针判断
if (this != &d) //地址是否相同
{
_y = d._y;
_m = d._m;
_d = d._d;
cout << "operator=" << endl;
}
return *this;
}
void test()
{
Date d1(2021, 3, 21);
Date d2(2021, 3, 22);
Date d3(2021, 3, 23);
int a, b, c;
//连续赋值:从右向左
a = b = c = 100;
//完整形式
d1.operator=(d2.operator=(d3));
//简写形式
d1 = d2 = d3;
}
Date(const Date& d)
{
_y = d._y;
_m = d._m;
_d = d._d;
cout << "Date(const Date& d)" << endl;
}
void test()
{
Date d1(2021, 3, 21);
Date d2(2021, 3, 22);
Date d3(2021, 3, 23);
int a, b, c;
//连续赋值:从右向左
a = b = c = 100;
//完整形式
d1.operator=(d2.operator=(d3));
//简写形式
d1 = d2 = d3;
//是否为赋值:不是赋值
Date d4 = d1;
}
2.const成员
2.1 const修饰类的成员函数
将const修饰的类成员函数称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。
#include<iostream>
using namespace std;
class A
{
public:
//原则:权限够不够(读写)---->权限不能放大,但是可以缩小
//int setI(A* const this,int i)
int setI(int i)
{
_i = i;
//非const成员函数中,可以调用const成员函数
getI(); //const * = *
}
//const修饰this指针:this指针指向的对象内容不能变
//int getI(const A* const this)
int getI() const //const this:const A* const
{
/*_i = 100;
this->_i = 100;*/
//const成员函数中,不能调用const成员函数
//setI(10);
return _i;
}
private:
int _i;
};
void test()
{
A a;
//原则:权限够不够(读写)---->权限不能放大,但是可以缩小
//非const对象可以调用const成员函数:可以
a.setI(10);
a.getI();
const A b;
//const对象可以调用const成员函数:不可以
//b.setI(10);
b.getI();
}
void test()
{
int a = 10;
//pa:指向和内容都可以修改
int*pa = &a;
//cpa:内容可以修改,指向不能改
int * const cpa = &a;
//cpa:指向和内容都不可以修改
const int* const cpa = &a;
int b;
pa = &b;
*pa = 100;
//cpa = &b;
*cpa = 1000;
//cpa = &b;
*cpa = 10000;
}
//const只修饰成员函数
//void fun1(int a) const
//{
// a = 100;
//}
3.取地址及const取地址操作符重载
这两个默认成员函数一般不用重新定义 ,编译器默认会生成。
class A
{
public:
//原则:权限够不够(读写)---->权限不能放大,但是可以缩小
//int setI(A* const this,int i)
void setI(int i)
{
_i = i;
//非const成员函数中,可以调用const成员函数
getI(); //const * = *
}
//const修饰this指针:this指针指向的对象内容不能变
//int getI(const A* const this)
int getI() const //const this:const A* const
{
/*_i = 100;
this->_i = 100;*/
//const成员函数中,不能调用const成员函数
//setI(10);
return _i;
}
//this:A* const
A* operator&()
{
return this;
}
//this:const A* const
const A* operator&() const
{
return this;
}
//private:
int _i;
};
void test()
{
A obja;
A* pa = &obja;
pa->setI(10);
const A objb;
const A* pb = &objb;
}
这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需要重载,比如想让别人获取到指定的内容!