温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

C++友元与运算符重载怎么应用

发布时间:2022-04-24 16:15:41 来源:亿速云 阅读:202 作者:iii 栏目:开发技术

这篇文章主要讲解了“C++友元与运算符重载怎么应用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++友元与运算符重载怎么应用”吧!

友元

生活中你的家有客厅(Public),有你的卧室(Private),客厅所有来的客人都可以进去,但是你的卧室是私有的,也就是说只有你能进去,但是呢,你也可以允许你的好闺蜜好基友进去。

在程序里,有些私有属性也想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术。

友元的目的就是让一个函数或者类访问另一个类中私有成员。

友元的关键字为: friend

友元的三种实现:

  • 全局函数做友元

  • 类做友元

  • 成员函数做友元

1 全局函数做友元

class Building {	//告诉编译器 goodGay全局函数 是 Building类的好朋友,可以访问类中的私有内容	friend void goodGay(Building * building); public:	Building()	{	this->m_SittingRoom = "客厅";	this->m_BedRoom = "卧室";	} public:	string m_SittingRoom; //客厅 private:	string m_BedRoom; //卧室 }; void goodGay(Building * building) {	cout << "好基友正在访问: " << building->m_SittingRoom << endl;	cout << "好基友正在访问: " << building->m_BedRoom << endl; } void test01() {	Building b;	goodGay(&b); } int main(){	test01();	system("pause");	return 0; }

2 类做友元

class Building; class goodGay { public:	goodGay();	void visit(); private:	Building *building; }; class Building {	//告诉编译器 goodGay类是Building类的好朋友,可以访问到Building类中私有内容	friend class goodGay; public:	Building(); public:	string m_SittingRoom; //客厅 private:	string m_BedRoom;//卧室 }; Building::Building() {	this->m_SittingRoom = "客厅";	this->m_BedRoom = "卧室"; } goodGay::goodGay() {	building = new Building; } void goodGay::visit() {	cout << "好基友正在访问" << building->m_SittingRoom << endl;	cout << "好基友正在访问" << building->m_BedRoom << endl; } void test01() {	goodGay gg;	gg.visit(); } int main(){	test01();	system("pause");	return 0; }

3 成员函数做友元

class Building; class goodGay { public:	goodGay();	void visit(); //只让visit函数作为Building的好朋友,可以发访问Building中私有内容	void visit2();  private:	Building *building; }; class Building {	//告诉编译器  goodGay类中的visit成员函数 是Building好朋友,可以访问私有内容	friend void goodGay::visit(); public:	Building(); public:	string m_SittingRoom; //客厅 private:	string m_BedRoom;//卧室 }; Building::Building() {	this->m_SittingRoom = "客厅";	this->m_BedRoom = "卧室"; } goodGay::goodGay() {	building = new Building; } void goodGay::visit() {	cout << "好基友正在访问" << building->m_SittingRoom << endl;	cout << "好基友正在访问" << building->m_BedRoom << endl; } void goodGay::visit2() {	cout << "好基友正在访问" << building->m_SittingRoom << endl;	//cout << "好基友正在访问" << building->m_BedRoom << endl; } void test01() {	goodGay  gg;	gg.visit(); } int main(){	test01();	system("pause");	return 0; }

运算符重载

运算符重载概念:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型

1 加号运算符重载

作用:实现两个自定义数据类型相加的运算

class Person { public:	Person() {};	Person(int a, int b)	{	this->m_A = a;	this->m_B = b;	}	//成员函数实现 + 号运算符重载	Person operator+(const Person& p) {	Person temp;	temp.m_A = this->m_A + p.m_A;	temp.m_B = this->m_B + p.m_B;	return temp;	} public:	int m_A;	int m_B; }; //全局函数实现 + 号运算符重载 //Person operator+(const Person& p1, const Person& p2) { //	Person temp(0, 0); //	temp.m_A = p1.m_A + p2.m_A; //	temp.m_B = p1.m_B + p2.m_B; //	return temp; //} //运算符重载 可以发生函数重载  Person operator+(const Person& p2, int val)   {	Person temp;	temp.m_A = p2.m_A + val;	temp.m_B = p2.m_B + val;	return temp; } void test() {	Person p1(10, 10);	Person p2(20, 20);	//成员函数方式	Person p3 = p2 + p1;  //相当于 p2.operaor+(p1)	cout << "mA:" << p3.m_A << " mB:" << p3.m_B << endl;	Person p4 = p3 + 10; //相当于 operator+(p3,10)	cout << "mA:" << p4.m_A << " mB:" << p4.m_B << endl; } int main() {	test();	system("pause");	return 0; }

总结1:对于内置的数据类型的表达式的的运算符是不可能改变的

总结2:不要滥用运算符重载

2 左移运算符重载

作用:可以输出自定义数据类型

class Person {	friend ostream& operator<<(ostream& out, Person& p); public:	Person(int a, int b)	{	this->m_A = a;	this->m_B = b;	}	//成员函数 实现不了  p << cout 不是我们想要的效果	//void operator<<(Person& p){	//} private:	int m_A;	int m_B; }; //全局函数实现左移重载 //ostream对象只能有一个 ostream& operator<<(ostream& out, Person& p) {	out << "a:" << p.m_A << " b:" << p.m_B;	return out; } void test() {	Person p1(10, 20);	cout << p1 << "hello world" << endl; //链式编程 } int main() {	test();	system("pause");	return 0; }

总结:重载左移运算符配合友元可以实现输出自定义数据类型

3 递增运算符重载

作用: 通过重载递增运算符,实现自己的整型数据

class MyInteger {	friend ostream& operator<<(ostream& out, MyInteger myint); public:	MyInteger() {	m_Num = 0;	}	//前置++	MyInteger& operator++() {	//先++	m_Num++;	//再返回	return *this;	}	//后置++	MyInteger operator++(int) {	//先返回	MyInteger temp = *this; //记录当前本身的值,然后让本身的值加1,但是返回的是以前的值,达到先返回后++;	m_Num++;	return temp;	} private:	int m_Num; }; ostream& operator<<(ostream& out, MyInteger myint) {	out << myint.m_Num;	return out; } //前置++ 先++ 再返回 void test01() {	MyInteger myInt;	cout << ++myInt << endl;	cout << myInt << endl; } //后置++ 先返回 再++ void test02() {	MyInteger myInt;	cout << myInt++ << endl;	cout << myInt << endl; } int main() {	test01();	//test02();	system("pause");	return 0; }

总结: 前置递增返回引用,后置递增返回值

4 赋值运算符重载

c++编译器至少给一个类添加4个函数

  • 默认构造函数(无参,函数体为空)

  • 默认析构函数(无参,函数体为空)

  • 默认拷贝构造函数,对属性进行值拷贝

  • 赋值运算符 operator=, 对属性进行值拷贝

如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题

示例:

class Person { public:	Person(int age)	{	//将年龄数据开辟到堆区	m_Age = new int(age);	}	//重载赋值运算符 	Person& operator=(Person &p)	{	if (m_Age != NULL)	{	delete m_Age;	m_Age = NULL;	}	//编译器提供的代码是浅拷贝	//m_Age = p.m_Age;	//提供深拷贝 解决浅拷贝的问题	m_Age = new int(*p.m_Age);	//返回自身	return *this;	}	~Person()	{	if (m_Age != NULL)	{	delete m_Age;	m_Age = NULL;	}	}	//年龄的指针	int *m_Age; }; void test01() {	Person p1(18);	Person p2(20);	Person p3(30);	p3 = p2 = p1; //赋值操作	cout << "p1的年龄为:" << *p1.m_Age << endl;	cout << "p2的年龄为:" << *p2.m_Age << endl;	cout << "p3的年龄为:" << *p3.m_Age << endl; } int main() {	test01();	//int a = 10;	//int b = 20;	//int c = 30;	//c = b = a;	//cout << "a = " << a << endl;	//cout << "b = " << b << endl;	//cout << "c = " << c << endl;	system("pause");	return 0; }

5 关系运算符重载

**作用:**重载关系运算符,可以让两个自定义类型对象进行对比操作

示例:

class Person { public:	Person(string name, int age)	{	this->m_Name = name;	this->m_Age = age;	};	bool operator==(Person & p)	{	if (this->m_Name == p.m_Name && this->m_Age == p.m_Age)	{	return true;	}	else	{	return false;	}	}	bool operator!=(Person & p)	{	if (this->m_Name == p.m_Name && this->m_Age == p.m_Age)	{	return false;	}	else	{	return true;	}	}	string m_Name;	int m_Age; }; void test01() {	//int a = 0;	//int b = 0;	Person a("孙悟空", 18);	Person b("孙悟空", 18);	if (a == b)	{	cout << "a和b相等" << endl;	}	else	{	cout << "a和b不相等" << endl;	}	if (a != b)	{	cout << "a和b不相等" << endl;	}	else	{	cout << "a和b相等" << endl;	} } int main() {	test01();	system("pause");	return 0; }

6 函数调用运算符重载

  • 函数调用运算符 () 也可以重载

  • 由于重载后使用的方式非常像函数的调用,因此称为仿函数

  • 仿函数没有固定写法,非常灵活

示例:

class MyPrint { public:	void operator()(string text)	{	cout << text << endl;	} }; void test01() {	//重载的()操作符 也称为仿函数	MyPrint myFunc;	myFunc("hello world"); } class MyAdd { public:	int operator()(int v1, int v2)	{	return v1 + v2;	} }; void test02() {	MyAdd add;	int ret = add(10, 10);	cout << "ret = " << ret << endl;	//匿名对象调用  	cout << "MyAdd()(100,100) = " << MyAdd()(100, 100) << endl; } int main() {	test01();	test02();	system("pause");	return 0; }

感谢各位的阅读,以上就是“C++友元与运算符重载怎么应用”的内容了,经过本文的学习后,相信大家对C++友元与运算符重载怎么应用这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

c++
AI