在 C++ 语言中 , " 友元类 " 是 一个类 与 另外一个类 的 特殊类关系累 ,
在 类 A 的 " 友元类 " B 中 , 可以直接访问 A 类 的 私有成员 和 受保护成员 ;
声明一个 类 B 是 另一个类 A 的 友元类 , 可以 在类 A 中使用 friend 关键字来声明 ;
代码示例 :
class Student
{
private:
// 声明 StudentCaculate 类是 Student 类的友元类
// 在 StudentCaculate 类中可以访问 Student 类中的私有成员
friend class StudentCaculate;
}
友元类单向性 :
友元类关系是单向的 , 声明一个类 B 是 另一个类 A 的 友元类 ,
B 可以访问 A 的 所有成员 ,
但是 A 不是 B 的友元类 , A 不能访问 B 的私有和保护成员 ;
友元类 关系不具有继承性 , 即 子类不能直接继承父类的友元类 ;
友元类主要作用 :
友元类 和 友元函数 会破坏 C++ 面向对象 的封装性 , 那么为什么还会出现该机制呢 ?
有些编程场景 , 需要破坏类的封装性 , 需要访问类的私有属性 ;
Java 类编译成 class 字节码后 , 可以通过 反射 字节码 的方式 访问 类的私有属性 ;
反射机制 在 特定领域开发 中应用广泛 , 如 SDK , 开发框架 , 逆向 等领域中 ;
反射机制 是 面向切面编程 AOP 的基础 ;
反射机制 成为一种编程标准 ;
C 代码 和 C++ 代码 , 编译成 so 动态库 或 a 静态库 , 需要如下步骤 :
最终的 函数库 中 都是汇编指令 , 机器码指令 , 如果要从指令中查找指定的类的私有属性 , 该操作难度很大 ;
在 Student 类中 , 定义了友元类 StudentCaculate ,
// 声明 StudentCaculate 类是 Student 类的友元类
// 在 StudentCaculate 类中可以访问 Student 类中的私有成员
friend class StudentCaculate;
在 StudentCaculate 中 , 定义了 Student 类型成员变量 , 可以访问 Student 对象的所有成员 , 包括 私有成员 和 保护成员 ;
代码示例 :
#include "iostream"
using namespace std;
class Student
{
public:
// 带参构造函数
Student(int age = 1, int height = 1)
{
this->age = age;
this->height = height;
cout << "执行 Student 的构造函数" << endl;
}
~Student()
{
cout << "执行 Student 的析构函数" << endl;
}
public:
// 打印类数据
void print()
{
cout << " age = " << age << " , height = " << height << endl;
}
private:
// 声明 StudentCaculate 类是 Student 类的友元类
// 在 StudentCaculate 类中可以访问 Student 类中的私有成员
friend class StudentCaculate;
// 声明友元函数
friend void changeAge(Student* s, int age);
private:
int age; // 年龄
int height; // 身高
};
class StudentCaculate
{
public:
void fun()
{
cout << "age + height = " << student.age + student.height << endl;
};
public:
// 此处会自动调用默认的构造函数
// 默认值都为 1
Student student;
};
// 在友元函数中 访问 age 私有属性
void changeAge(Student* s, int age)
{
s->age = age;
}
int main() {
// 声明 Student 友元类 StudentCaculate 对象
StudentCaculate sc;
// 调用 sc 对象中的 fun , 其中调用了 Student 的私有成员
sc.fun();
// 为 StudentCaculate 设置一个非默认值
sc.student = Student(10, 120);
// 调用 sc 对象中的 fun , 其中调用了 Student 的私有成员
sc.fun();
// 控制台暂停 , 按任意键继续向后执行
system("pause");
return 0;
}
执行结果 :
执行 Student 的构造函数
age + height = 2
执行 Student 的构造函数
执行 Student 的析构函数
age + height = 130
请按任意键继续. . .