运算符重载&取地址&const成员函数
运算符重载
在类中有一些成员变量,但是当我们需要让两个对象进行运算,例如+ - * /
等操作时,需要定义一些专门用于运算的函数,例如
class Data
{
public:
bool IsSame(const Data& d)
{
return _year == d._year &&
_month == d._month &&
_day == d._day;
}
private:
int _year;
int _month;
int _day;
}
这样写确实可以实现比较两个对象的值,但是这样写会使得代码的可读性不高,我们是否可以使用==的方式进行实现?
运算符重载
class Data
{
public:
bool operator==(const Data& d)
{
return _year == d._year &&
_month == d._month &&
_day == d._day;
}
private:
int _year;
int _month;
int _day;
}
使用operator+"运算符"就可以实现运算符的重载。这样就可以直接使用==了。
但是前提是进行重载的运算符必须是c++中支持的运算,并且.* :: sizeof ?: .
这几个运算符除外。
注意:
1.重载操作符必须有一个类类型参数,
2.用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其含义,
3.作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
对于==重载,看起来只有一个参数,实际上第一个参数是编译器自动添加的this指针,相当于
bool operator==(Data* this, const Data& d);
赋值运算符重载
和运算符重载相似,赋值运算符也需要有参数类型,返回值,同时需要检测是否给自己赋值,并且要符合赋值运算符的实际意义。
赋值运算符和运算符有一个区别就是,赋值运算符重载时,只能重载成类的成员函数,不能重载成全局函数(因为如果用户给赋值运算符在全局中定义了,那么编译器并不知道,则会在类中默认定义一个赋值运算符,这时候如果调用赋值,就会发生冲突)
如果用户自己没有在类中定义重载运算符,那么编译器会默认生成一个,默认生成的这个赋值运算符,其实是属于浅拷贝,只会将成员变量中的值原封不动的复制一份过去,那么当类中涉及到了资源管理时,就会出错。
因此,当涉及到资源管理时,需要主动定义赋值运算符,并且定义为成员函数
Data& operator=(const Data& d)
{
if(this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
前置++和后置++重载
当需要实现前置++和后置++重载时,需要这样设置
//前置++
//由于默认第一个参数是this,则对于这个一元运算符来说,不需要传参
//返回的是++后的结果,函数结束后this指向的对象不会销毁,以引用的方式返回提高效率
Data& operator++()
{
_day = _day + 1;
return *this;
}
//后置++
//需要返回+1前的值,需要借助拷贝构造函数创建一个临时对象,
//由于tmp在函数结束时就销毁了,则只能用返回值的方式
Data operator++()
{
Data tmp(*this);
_day = _day + 1;
return tmp;
}
const成员函数
将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this
指针,表明在该成员函数中不能对类的任何成员进行修改。
this指针的实际类型为:const Date* const this,这就表明了this指针本身的值不能被修改(指向不能被修改),同时this指向的空间中的值不能被this修改。
与普通成员函数相比
普通成员函数–是可读写的(即可以修改成员变量,也可以不修改成员变量),this指向对象可以修改也可以修改
const成员函数:只读函数(函数体内部不能修改成员变量),this指向的对象不能修改
因此,对于普通成员对象来说,可以调用普通成员函数,也可以调用const成员函数。
而对于const成员对象来说,只能调用const成员函数,因为只有const成员函数才会保证其成员变量不会被修改
class Data
{
public:
void PrintData() const
{
cout << _day << endl;
}
void SetData(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
}
int main()
{
//这里的d1是const对象,那么只能调用const成员函数
const Data d1;
d1.PrintData();
Data d2;
//这里的d2是普通对象,那么既可以调用普通成员函数,也可以调用const成员函数
d2.SetData(2023, 4, 6);
d2.PrintData();
return 0;
}