C++-Record28—友元函数及友元类

目录

友元函数

案例

友元类

案例

友元函数和友元类存在的意义?

总体代码


友元函数

友元函数是类的好朋友, 在这个友元函数里面,可以修改这个类的私有属性,严格来说,友元函数破坏了类的封装性,看上面的图中的代码段,在A类里面声明了一个友元函数,并且,这个友元函数还是个全局函数,要想在全局函数中去修改,某一个对象的私有属性,首先得先把这个对象给传进去吧!所以,友元函数一般的传入参数都包含,友元类的参数(一个类的指针或引用)和要进行修改的值。

说明语句位置与访问描述无关。就是说友元函数的声明可以写在"private"下或者"public"中都是可以的。友元函数通过对象参数访问私有数据成员:

案例

 定义一个类:

class A
{
public:
	//1 声明的位置 和 public private没有关系
	friend void modifyA(A *pA, int _a); //2 函数modifyA 是 类A的好朋友
	A(int a=0, int b=0)
	{
		this->a = a;
		this->b = b;
	}
	int getA()
	{
		return this->a;
	}

private:
	int a;
	int b;
};

再定义一个友元函数:

void modifyA(A *pA, int _a)
{
	//pA->a = 100;
	pA->a = _a;
}

 这样,"modifyA()"就可以更改A类中私有属性的参数了。这是因为在类中有了声明:

friend void modifyA(A *pA, int _a);

在主函数中进行调用:

void main2101()
{
	
	A a1(1, 2);
	cout<< a1.getA()<<endl;
	modifyA(&a1, 300);
	cout<< a1.getA()<<endl;

	
	cout<<"hello..."<<endl;
	system("pause");
	return ;
}

运行正常,可见友元函数的确可以修改类的私有属性。


友元类

  • 若B类是A类的友员类,则B类的所有成员函数都是A类的友员函数
  • 友员类通常设计为一种对数据操作或类之间传递消息的辅助类

友元类的应用场景比较复杂,大体上是通过B类可以直接修改A类的这种模式。

案例

接着上面的代码接着敲,定义一个class B:

class B
{
public:
	void Set(int a)
	{
		Aobject.a = a;
	}
	void printB()
	{
		cout<<Aobject.a <<endl;
	}
private:
	A Aobject;
};

声明B类是A类的好朋友,在A类中声明如下:

	friend class B;//B类 是 A的好朋友 ,在B中可以访问A类的私有成员 私有函数

 在主函中调用:

void main()
{
	B b1;
	b1.Set(300);
	b1.printB();
	system("pause");
}

运行正常,可见B类可以去修改A中的元素属性。 但话说回来,友元类的应用场景是很少的,掌握案例就可以,过于复杂的,遇到以后再探究。

友元函数和友元类存在的意义?

友元函数和友元类严格来讲,都是破坏了函数的封装性和私有属性的,但为什么要设计他们出现呢?这一点,和C语言有关系的。C++封装性是很好的,但在实际工程中,有时候我们的确是需要去拿出来类中的某些元素或者属性来修改的,如果没有友元就只能去汇编最底层去修改了,那样太可怕了,所以,C++大牛们,设计出友元,相当于给开了个后门,方便程序员有这个需求的时候,直接修改。

//为什么设计友元类函数
// 1.java--->1.class(字节码) ==》反射机制分析1.class 找到类对象。直接修改类的私有属性。。。
//反射机制 成为一种标准。。。。jdk ...sun 做成标准 。。。jdk 的 api函数中有体现 
//AOP
//2 1.cpp===>汇编
// 预编译 编译  连接  生成 。。gcc -E //gcc -s  -
//gcc -o 1.exe 1.c 
// 汇编往回找。。。。很难。。。。
//3 开了一个后门 。。。friend

/*
gcc -E hello.c -o hello.i(预处理)
gcc -S hello.i -o hello.s(编译)
gcc -c hello.s -o hello.o(汇编)
gcc hello.o -o hello(链接)
以上四个步骤,可合成一个步骤

gcc hello.c -o hello(直接编译链接成可执行目标文件)
gcc -c hello.c或gcc -c hello.c -o hello.o(编译生成可重定位目标文件)
*/

总体代码

dm21_友元函数和友元类.cpp


#include <iostream>
using namespace std;

class A
{
public:
	friend class B;//B类 是 A的好朋友 ,在B中可以访问A类的私有成员 私有函数
	//1 声明的位置 和 public private没有关系
	friend void modifyA(A *pA, int _a); //2 函数modifyA 是 类A的好朋友
	A(int a=0, int b=0)
	{
		this->a = a;
		this->b = b;
	}
	int getA()
	{
		return this->a;
	}

private:
	int a;
	int b;
};

//  

void modifyA(A *pA, int _a)
{
	//pA->a = 100;
	pA->a = _a;
}

//
class B
{
public:
	void Set(int a)
	{
		Aobject.a = a;
	}
	void printB()
	{
		cout<<Aobject.a <<endl;
	}
private:
	A Aobject;
};

//为什么设计友元类函数
// 1.java--->1.class(字节码) ==》反射机制分析1.class 找到类对象。直接修改类的私有属性。。。
//反射机制 成为一种标准。。。。jdk ...sun 做成标准 。。。jdk 的 api函数中有体现 
//AOP
//2 1.cpp===>汇编
// 预编译 编译  连接  生成 。。gcc -E //gcc -s  -
//gcc -o 1.exe 1.c 
// 汇编往会找。。。。很难。。。。
//3 开了一个后门 。。。friend

/*
gcc -E hello.c -o hello.i(预处理)
gcc -S hello.i -o hello.s(编译)
gcc -c hello.s -o hello.o(汇编)
gcc hello.o -o hello(链接)
以上四个步骤,可合成一个步骤

gcc hello.c -o hello(直接编译链接成可执行目标文件)
gcc -c hello.c或gcc -c hello.c -o hello.o(编译生成可重定位目标文件)
*/

 

void main()
{
	B b1;
	b1.Set(300);
	b1.printB();
	system("pause");
}
void main2101()
{
	
	A a1(1, 2);
	cout<< a1.getA()<<endl;
	modifyA(&a1, 300);
	cout<< a1.getA()<<endl;

	
	cout<<"hello..."<<endl;
	system("pause");
	return ;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值