一、友元函数
1.1 友元函数的定义
类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。
1.2 友元函数的特点
- 友元函数破坏了类的私有性
- 友元函数是一个全局函数
- 友元函数形式:一般情况下都包含类的指针或引用
- 友元函数在public之下或者是private下都无所谓
1.3 友元函数使用例子
友元函数的调用与一般函数的调用方式和原理一致。
#include <iostream>
using namespace std;
class A
{
public:
//声明的位置和public private没有关系
//友元函数的声明
friend void modifyA(A *pA,int _a);//函数modifyA是类的好朋友
A(int a,int b) {
this->a = a;
this->b = b;
}
~A() {
cout << "~A()" << endl;
}
void getA() {
cout << "a: " << this->a << endl;
}
private:
int a,b;
};
void modifyA(A *pA,int _a) {
//通过友元函数访问A的私有属性
pA->a = _a;
}
int main()
{
A a1(1,2);
a1.getA();
modifyA(&a1, 100);
a1.getA();
system("pause");
return 0;
}
二、友元类
2.1 友元类的定义
友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。友元类的应用场景比较死板,通常都是:B是A的好朋友,在B里面组合了一个A的对象,通过B可以直接修改A。A其实就只是一个辅助的类,用来传递消息。
2.2 友元类的特点
- 若B类是A类的友元类,则B类的所有成员函数都是A泪的友元函数
- 友元类通常涉及为一种对数据操作或类之间传递消息的辅助类
2.3 友元类例子
#include <iostream>
using namespace std;
class A
{
public:
//声明的位置和public private没有关系
//B是A的友元类
friend class B;//在B类中可以访问A类的私有成员,或者是私有函数
friend void modifyA(A *pA,int _a);//函数modifyA是类的友元函数
A(int a=0,int b=0) {
this->a = a;
this->b = b;
}
~A() {
cout << "~A()" << endl;
}
void getA() {
cout << "a: " << this->a << endl;
}
private:
int a,b;
};
void modifyA(A *pA,int _a) {
pA->a = _a;
}
class B
{
public:
void set(int a) {
object.a = 100;
}
void printB() {
cout << object.a << endl;
}
private:
A object; //B中有A,A是B的子类
};
void objectPlay01() {
A a1(1, 2);
a1.getA();
modifyA(&a1, 100);
a1.getA();
}
void objectPlay02() {
B b1;
b1.set(300);
b1.printB();
}
int main()
{
//objectPlay01();
objectPlay02();
system("pause");
return 0;
}
2.4 友元类的注意事项
- 友元关系不能被继承。
- 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。
- 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应
2.5 为什么要设计友元类
一般我们所写的.cpp文件会转成为汇编语言,假设没有友元类的情况下。当我们要访问类的私有成员变量的时候,就需要从汇编倒推回去。然而有的时候我却是需要访问私有变量,不能做每时每刻通过汇编这样去找,所以我们做了一个友元函数友元类。等于开了个后门、不然我们就要通过汇编倒推回去
拓展:Java中时通过字节码去找到类对象的。
三、参考链接
https://blog.csdn.net/fanyun_01/article/details/79122916