目录
友元函数
友元函数是类的好朋友, 在这个友元函数里面,可以修改这个类的私有属性,严格来说,友元函数破坏了类的封装性,看上面的图中的代码段,在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 ;
}