【 C++ 7.赋值运算符重载和取地址重载】

6 篇文章 0 订阅
5 篇文章 0 订阅
本文详细介绍了C++中的运算符重载,特别是赋值运算符的重载。讨论了重载的规则、参数类型、返回值、自我赋值检查以及连续赋值的支持。同时,讲解了const成员函数的概念及其在取地址运算符重载中的应用,强调了封装性和效率的考虑。最后,探讨了const对象与非const成员函数的调用规则。
摘要由CSDN通过智能技术生成

1. 赋值运算符重载

a. 运算符重载

C++为了增强代码的可读性引入了运算符重载,运算符重载时具有特殊函数名的函数,也具有返回值类型,函数名字和参数列表,其返回值类型与参数列表和普通函数相似。
函数名字:关键字operator后面接需要重载的运算符符号
函数原型:返回值类型operator操作符
还需要注意:
1.不能通过连接其他符号来创建新的操作符:比如operator@ ,就是说:要重载的运算符,一定是C++支持的运算符号。
2.重载操作符必须有一个类类型或者枚举类型的操作数
3.用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不能改变其含义
4.操作符有一个默认的形参this,限定为第一个形参,但是并不显示
bool operator==(Date* this,const Date& d)
5.作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数的,这是由于,左操作数是this指针指向的调用对象。
6. ‘ .*’ 、‘::’ 、‘sizeof’ 、‘?:’ 、‘.’ 注意以上5个运算符不能重载。这个经常在笔试选择题中出现。

//日期
class Date
{
public:
	bool IsEqual(const Date& d)
	{
		return _year == d._year &&
			_month == d._month &&
			_day == d._day;
	}
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;

	}
//private:
	int _year;
	int _month;
	int _day;
};
//1.什么是运算符重载
// 2.为什么重载
// 3.如何重载
// 4.和函数重载有何区别

//返回值类型 operator操作符(参数列表)

全局的operator==
bool operator==(const Date& d1, const Date& d2)
{
	return d1._year == d2._year
		&& d1._month == d2._month
		&& d1._day == d2._day;

}
//1.要重载的运算符,一定是C++支持的运算符号
int main()
{
	Date d1(2002,1,5);
	Date d2(2002,1,6);

	if (d1.IsEqual(d2))
	{
		cout << "d1==d2" << endl;
	}
	else
	{
		cout << "d1!=d2" << endl;
	}
	//对于自定义的类型对象,不能直接使用相应的运算符,比如:判断两个对象是否相等
	//原因:自定义类型中包含有多个成员,如何比较编译器不知道如何比较
	operator==(d1,d2);
	if (d1 == d2)
	{
		cout << "d1==d2" << endl;
	}
	else
	{
		cout << "d1!=d2" << endl;
	}
	return 0;
}
d1!=d2
d1!=d2

运算符重载目的:告诉编译器,自定义的对象遇到该运算符时应该如何操作。
可是也有问题,将运算符重载成全局的,就需要将成员变量设置为public的,那么封装性如何保证。
及可以将运算符重载放到类中,重载成成员函数。就解决了封装性的问题。

class Date
{
public:

    //bool operator==(Date* this,const Date& d)
	//需要注意的是,左操作数是this指针指向的调用对象
	bool operator==(const Date& d)
	{
		return _year == d._year &&
			_month == d._month &&
			_day == d._day;
	}
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;

	}
	private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1(2002, 1, 5);
	Date d2(2002, 1, 6);
	d1.operator==(d2);
	if (d1 == d2)
	{
		cout << "d1==d2" << endl;
	}
	else
	{
		cout << "d1!=d2" << endl;
	}
	return 0;
}
d1!=d2

b. 赋值运算符重载

1.参数的类型

void operator=(const Date& d);
Date& operator=(const Date& d);//为了能够支持连续赋值

如果是自定义类型作为函数参数,尽量传递引用,因为在传参时,不需要拷贝临时对象,如果不想通过形参修改外部的实参,最好给形参加上const

2.返回值

为了能让operator==支持连续赋值,则要存在返回值
返回引用是为了提高效率,如果返回引用,在返回式就不需要拷贝构造临时对象,效率也提高了

class Date
{
public:
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
	 	_day = d._day;
	}
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	运算符重载时一定要符合其含义
	//不能连续赋值
	//void operator=(const Date& d)
	//{
	//	_year = d._year;
	//	_month = d._month;
	//	_day = d._day;
	//}

	//为了能让operator支持连续赋值,则需要其存在返回值
	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;
};
//注意:赋值运算符重载必须要重载成类的成员函数,否则编译失败
//void operator=(const Date& left, const Date& right)
//{}
int main()
{
	int a = 1;
	int b, c;
    //赋值操作
    b=a;

    Date d1(2001, 1, 1);
	Date d2(2002, 2, 2);
	d1 = d2;//把d2的值赋给d1  
	//d1.operator=(d2);//等同于d1=d2;

	//支持连续赋值 
	c = b = a;
	
	//连续赋值
	Date d3(2003, 3, 3);
	d1 = d2 = d3;  //本质就是两次operator函数的调用。先用d3给d2赋值,再用d2给d3赋值
	
	//自己给自己赋值,通过检验this与&d来判断
	d1 = d1;
	return 0;
}

注意:赋值运算符重载必须要重载成类的成员函数,否则编译失败
因为:赋值运算符重载是默认成员函数,如果用户没有显式定义时,则编译器会自动生成一份,如果自己在类外实现一份,相当于赋值运算符重载了两份.

3.检验是否给自己复制

自己给自己赋值,通过检验this与&d来判断,如果 this指针与&d相等,那麽就直接返回this指针,提高效率

Date& operator=(const Date& d)
	{
		if (this != &d)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}

4.返回*this

//取地址&操作符重载 this的类型;Date* const
	Date* operator&()
	{
		return this;
	}

2.取地址及const取地址操作符重载

这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有在特殊情况下才使用,比如想让别人获取到指定内容

	Date* operator&()
	{
		return this;
	}
	const Date* operator&() const //只读函数--在该成员函数中只可以读取对象中的内容,但是不能修改对象中的内容
	{
		return this;
	}

取地址&操作符重载 this的类型: Date* const
this指针的指向不可修改,但是this指针指向的对象中的内容可以修改

const取地址&操作符重载 this的类型:const Date* const
前面const修饰返回值,后面的const用来修饰成员函数,将const修饰的成员函数称为const成员函数

3.const成员

a.const修饰类的成员函数

将const修饰的类成员函数称为const成员函数,实际修饰该成员函数隐含的this指针,const成员函数特性:在该函数内部不能修改任何成员变量,在该成员函数中只可以读取对象中的内容,但是不能修改对象中的内容

class Date
{
public:
	void PrintDate()const
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
	//全缺省构造函数
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	//拷贝构造函数
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	Date* operator&()
	{
		return this;
	}
	const Date* operator&() const 
	{
		return this;
	}
private:
	int _year;
	int _month;
	int _day;//mutable修饰该成员变量;该成员变量可以在const中被修改
};
int main()
{
	//普通类型的对象:普通成员函数和const成员函数都可以调用,可以读取其内容,也可以修改其内容
	Date d1(2001,1,1);
	Date* pd1 = &d1;
	d1.PrintDate();

	//const类型的对象:只能调用const成员函数,不能调用普通成员函数,只能读取其中的内容
	const Date d2(d1);
	const Date* pd2 = &d2;
	return 0;
}

b.常见的问题

1.const对象可以调用非const成员函数吗?
const类型对象只能调用const成员函数,const对象只能读取且内容
2.非const对象可以调用const成员函数吗?
普通对象:普通成员函数和const成员函数都可以调用,这是因为普通对象可以读取其内容也可以修改其内容
3.cost成员函数内可以调用其他非const成员函数吗?
不可与调用,const修饰的成员函数本质就是在修饰this,表明this指针的指向对象不能被修改。
4.非cost成员函数内可以调用其他const成员函数吗?
可以调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值