C++入门系列-赋值运算符重载

admin2024-05-15  0

C++入门系列-赋值运算符重载,第1张

🌈个人主页:羽晨同学 

💫个人格言:“成为自己未来的主人~”  

C++入门系列-赋值运算符重载,第2张

赋值运算符重载

运算符重载

C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型和参数列表与普通的函数类似。

 函数名字为:关键字operator后面接需要重载的运算符符号。

函数原型:返回值类型operator操作符(参数列表)

注意:

  • 不能通过连接其他符号来创建新的操作符,比如operator@,这个其实完全没意义。
  • 重载操作符必须有一个类类型参数,这个就证明了重载操作符是针对自定义类型的,不可能针对内置类型。
  • 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其含义。
  • 作为类成员函数重载时,其形参看起来比操作数少一,因为有一个隐藏的this指针。
  • .*   ::  sizeof  ?:   .这五个运算符是不能重载的。

接下来我们先来讲讲这五个不能重载的运算符中的第一个。这个运算符是极其少见的。

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class OB
{
public:
	void func()
	{
		cout << "void func()" << endl;
	}
};
typedef void(OB::* PtrFunc)();

int main()
{
	PtrFunc fp = &OB::func;//成员函数取地址要加一个&,普通函数函数名就是地址
	
	OB temp;
	
	(temp.*fp)();


	return 0;
}

其实.*的作用是什么呢,我们可以通过这段代码看到,.*的作用就是帮助我们调用成员函数的指针。

C++入门系列-赋值运算符重载,第3张 接下来,我们就回到了operator关键字的作用,这个关键字可以极大的提高代码的可读性,我们来看下面的代码。

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};
bool operator==(const Date& d1, const Date& d2)
{
	return d1._year == d2._year
		&& d1._month == d2._month
		&& d1._day == d2._day;
}
void Test()
{
	Date d1(2018,9.26);
	Date d2(2018, 9, 27);
	cout << (d1 == d2) << endl;
}

这段代码是operator的全局调用,我们会看到如果全局调用的话会存在一个问题,那就是成员变量是私有的。我们无法保证封装性。

这里的解决办法有三种,

  1.  提供这些成员的get和set
  2. 友元 
  3. 重载为成员函数

我们一般使用的就是第三种。重载为成员函数

什么意思呢?我们来看下面的这段代码

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	bool Func(const Date& d)
	{
		return this->_year == d._year
			&& this->_month == d._month
			&& this->_day == d._day;
	}
	bool operator==(const Date& d)
	{
		return this->_year == d._year
			&& this->_month == d._month
			&& this->_day == d._day;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d3(2024, 4, 14);
	Date d4(2024, 4, 15);

	cout << d3.operator==(d4) << endl;
	cout << (d3 == d4) << endl;
	return 0;
}

 懂了吗,我们将重载函数放到成员函数里面,就避免了权限不够的问题。

赋值运算符重载

赋值运算符重载格式

  • 参数类型:const T&,传递引用可以提高传参效率。
  • 返回值类型: T&,返回引用可以提高返回的效率,有返回值目的是为了支持连续复制
  • 检测是否自己给自己复制
  • 返回*this,要复合连续赋值的含义。
#include<iostream>
using namespace std;

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date(const Date& d)
	{
		cout << "	Date(const Date& d)" << endl;

		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	Date& operator=(const Date& d)
	{
		if (this != &d)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
	~Date()
	{
		cout << "~Date()" << endl;
		_year = -1;
		_month = -1;
		_day = -1;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1(2024, 4, 14);
	Date d2(d1);
	Date d3 = d1;
	return 0;
}

 2.赋值运算符只能重载成类的成员函数不能重载成全局函数

这个怎么理解呢?其实重载成类的成员函数和重载成全局函数有一个很大的不同点,就是成员函数还有一个潜在的this指针,而全局函数是没有这个东西,所以,如果要重载为全局函数的话,我们就需要给两个参数。

class Date
{
public:
	Date(int year = 1949, int month = 10, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

Date& operator=(Date& left, const Date& right)
{
	if (&left != &right)
	{
		left._year = right._year;
		left._month = right._month;
		left._day = right._day;
	}
	return left;
}

我们发现这个代码是会报错的, 原因是由于赋值运算符如果不显示实现,编译器会生成一个默认的。此时用户再在类外自己实现一个全局的赋值运算符重载,就和编译器在类中编译器自己生成的默认赋值运算符重载冲突了,故赋值运算符重载只能是类的成员函数。

用户没有显示实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝,注意:内置类型成员变量是直接赋值的,而自定义类型变量是需要调用对应类的赋值运算符重载完成赋值。

class Date
{
public:

	Date(int year = 2024, int month = 3, int day = 4)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _month;
	int _day;
	int _year;
};
int main()
{
	Date d1(2024, 5, 15);
	Date d2;
	d2 = d1;

	return 0;
}
#include<iostream>
using namespace std;
class Time
{
public:

private:
	int _hour = 1;
	int _second = 1;
	int _minute = 1;
};
class Date
{
public:
	void Print()
	{
		cout << "class Time" << endl;
	}
	Date(int year = 2024, int month = 3, int day = 4)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _month;
	int _day;
	int _year;
	Time _t;
};
int main()
{
	Date d1(2024, 5, 15);
	Date d2;
	d2 = d1;
	d1.Print();
	d2.Print();

	return 0;
}

C++入门系列-赋值运算符重载,第4张 

通过这个结果,我们可以很明显的得出上面的结论。

 C++入门系列-赋值运算符重载,第5张

C++入门系列-赋值运算符重载,第6张 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明原文出处。如若内容造成侵权/违法违规/事实不符,请联系SD编程学习网:675289112@qq.com进行投诉反馈,一经查实,立即删除!