11从汇编的角度深入理解c++_为什么要友元?

c++中封装是思想是:里面的成员变量都是私有的,如果外边想访问,可以提供一些函数,来使用类里面的变量。(即把属性暴露出去了,比人想怎么用就怎么用,不可控,因此要私有)

需求:

  有1个函数(方法),想使用对象里面的成员。

class Person{
private:
	int x;
	int y;
public:
	Person(int x,int y){
		this->x = x;
		this->y = y;
	}
}
void Print(Person p)
{
	printf("%d,%d\n",p->x,p->y);
}

产生的问题1:例子里面的类,成员很少,如果类里面的成员很多的情况呢,比如说有几千个属性,这样使用对象传递参数的时候,反汇编参数传递是各种复制传递到函数内部,这样代码执行速度就很慢,因此想到使用指针来提高效率。

修改为指针传递:

class Person{
private:
	int x;
	int y;
public:
	Person(int x,int y){
		this->x = x;
		this->y = y;
	}
}
void Print(Person* p)
{
	printf("%d,%d\n",p->x,p->y);
}

产生的问题2:我这个函数,里面使用指针的代码很多,函数能修改对象中的属性的值,万一不小心把对象地址给改掉了,怎么办,使用引用。

class Person{
private:
	int x;
	int y;
public:
	Person(int x,int y){
		this->x = x;
		this->y = y;
	}
}
void Print(Person& p)
{
	printf("%d,%d\n",p.x,p.y);
}

产生的问题3:我这个类,由于访问的人太多,不允许改里面的属性,只可以读,加const的引用,只能读对象中的属性,不能改对象里面的属性。

class Person{
private:
	int x;
	int y;
public:
	Person(int x,int y){
		this->x = x;
		this->y = y;
	}
};
void Print(const Person& p)
{
		printf("%d,%d\n",p.x,p.y);
		p.x = 3;//编译器报错,禁止修改
		p.y = 4;//编译器报错,禁止修改
}

 产生的问题4:我这个函数放在类外边,由于x和y是私有的,就是想访问对象里面的属性,怎么办?

        或者我之前定义了1个类,这个类已经使用很久了,也有很多人使用,现在也不能随便改变类中的内容,现在在类的外边急需要访问类里面的私有成员,怎么办?

       好办:我重新给编译器定义一个,能在外边访问类里面的私有成员的不就解决问题了,声明为类的朋友,叫做友元。

#include "stdafx.h"

class Person{
private:
	int x;
	int y;
public:
	Person(int x,int y){
		this->x = x;
		this->y = y;
	}
	friend void Print(const Person& p);
};

void Print(const Person& p)
	{
		printf("%d,%d\n",p.x,p.y);

	}
int _tmain(int argc, _TCHAR* argv[])
{
	Person p(3,4);
	Print(p);

	getchar();
	return 0;
}

 反汇编代码:

01261420 55                   push        ebp  
01261421 8B EC                mov         ebp,esp  
01261423 81 EC D0 00 00 00    sub         esp,0D0h  
01261429 53                   push        ebx  
0126142A 56                   push        esi  
0126142B 57                   push        edi  
0126142C 8D BD 30 FF FF FF    lea         edi,[ebp+FFFFFF30h]  
01261432 B9 34 00 00 00       mov         ecx,34h  
01261437 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
0126143C F3 AB                rep stos    dword ptr es:[edi]  
0126143E 6A 04                push        4  
01261440 6A 03                push        3  
01261442 8D 4D F4             lea         ecx,[ebp-0Ch]  
01261445 E8 C0 FB FF FF       call        0126100A  
0126144A 8D 45 F4             lea         eax,[ebp-0Ch]  
0126144D 50                   push        eax  
0126144E E8 8D FD FF FF       call        012611E0  

1、发现友元函数和普通函数是一样的,没有this指针。

2、友元函数是不能被继承的,就像父亲的朋友不一定是儿子的朋友。

  运算符重载会用到友元。

  其实对于学习底层来说,不管友元函数还是私有成员,只有对编译器才有区别,编译器自己加的限制,对于我们来说,没有区别,因为我们可以使用很多办法突破编译器的限制。

还有一种情况,友元函数的加强版,如果一个类想访问一个另一个类中的私有属性怎么办?友元类

友元类:

//友元类
class A{
public:
	void SetAge(int age)
	{
		this->age = age;
	}
	//friend class B;
private:
	int age;
}
class B{
public:
	void ShowAge(A a)
	{
		printf("%d\n",a.age);
	}
}

友元类是:为了访问1个对象中的私有成员,这个类有个函数,函数的参数是另一个类的对象、指针、引用类型(访问私有成员)。

只有声明为朋友之后,编译器才不会报错。  

  友元使用:

  1、2个类共享数据

  2、运算符重载

posted @ 2023-09-20 18:37  一日学一日功  阅读(22)  评论(0)    收藏  举报