C++ 笔记(面向对象):友元
在 C++ 面向对象的封装特性中,类会将私有成员(private)和保护成员(protected)隐藏起来,仅允许类自身的成员函数访问 。但在实际开发中,我们有时需要让外部的函数或其他类 ,直接访问一个类的非公有成员 ------ 这就是友元(friend) 的作用。
友元是 C++ 提供的一种突破封装的机制,它允许外部函数或类访问另一个类的私有 / 保护成员。本文将从概念、分类、用法、优缺点四个维度,全面讲解友元的使用。
一、友元基础概念
1. 核心定义
友元 :使用 friend 关键字声明的外部函数 或外部类,可以直接访问当前类的所有成员(包括 private、protected)。
2. 核心特点
友元不是类的成员,只是被类 "授权" 的外部对象;
友元可以是普通全局函数 ,也可以是其他类的成员函数 ,甚至是整个类;
友元单向性:A 是 B 的友元,≠ B 是 A 的友元;
友元不传递:A 是 B 的友元,B 是 C 的友元,≠ A 是 C 的友元。
3. 友元的作用场景
让两个关联类高效共享数据;
重载运算符时(如 <<、>>),需要访问类的私有成员;
让工具函数直接操作类的内部数据,提升效率。
二、友元的三种分类
友元分为三类:友元全局函数 、友元成员函数 、友元类。
1. 友元全局函数
将普通全局函数声明为某个类的友元,该函数可直接访问类的私有成员。
代码示例
cpp
#include <iostream>
using namespace std;
class Person {
// 声明全局函数 showAge 为 Person 类的友元
friend void showAge(Person& p);
private:
int age = 20; // 私有成员
};
// 友元全局函数:可以直接访问 Person 的私有成员 age
void showAge(Person& p) {
cout << "年龄:" << p.age << endl;
}
int main() {
Person p;
showAge(p); // 调用友元函数
return 0;
}
关键点
友元声明写在类内部任意位置(public/protected/private 都可以);
函数本身是全局函数,不属于类。
2. 友元成员函数
将另一个类的成员函数声明为友元,该成员函数可访问当前类的私有成员。
代码示例
cpp
#include <iostream>
using namespace std;
// 提前声明 Person 类
class Person;
class Student {
public:
// 声明为 Person 的友元成员函数
void showPersonAge(Person& p);
};
class Person {
// 声明 Student 的 showPersonAge 为友元
friend void Student::showPersonAge(Person& p);
private:
int age = 22;
};
// 实现友元成员函数
void Student::showPersonAge(Person& p) {
cout << "Person的年龄:" << p.age << endl;
}
int main() {
Person p;
Student s;
s.showPersonAge(p);
return 0;
}
关键点
必须提前声明类,否则编译器无法识别;
只有这一个成员函数有权限,不是整个类。
3. 友元类
将整个类 声明为友元,该类的所有成员函数都可以访问当前类的私有成员。
代码示例
cpp
#include <iostream>
using namespace std;
class Person {
// 声明 Student 整个类为友元
friend class Student;
private:
int age = 23;
string name = "小明";
};
class Student {
public:
// 可以访问 Person 所有私有成员
void show(Person& p) {
cout << "姓名:" << p.name << endl;
cout << "年龄:" << p.age << endl;
}
};
int main() {
Person p;
Student s;
s.show(p);
return 0;
}
关键点
- 友元类的所有成员函数都能访问私有成员;
- 写法:
friend class 类名;
三、友元的优缺点
优点
- 灵活方便:快速实现外部访问私有成员;
- 效率更高:避免频繁调用公有接口函数;
- 适配运算符重载 :如
cout << 对象必须用友元。
缺点
- 破坏封装性:类的私有成员不再安全;
- 降低代码可维护性:外部代码可直接修改内部数据;
- 耦合度变高:类与类、类与函数关联性太强。
四、使用建议
- 能不用就不用:优先用公有成员函数访问;
- 必须用时再用:运算符重载、紧密关联的类;
- 最小权限原则 :优先用友元函数 ,少用友元类。
总结
- 友元 是
friend声明的外部函数 / 类,可访问类的私有成员; - 三类友元:友元全局函数 、友元成员函数 、友元类;
- 特点:单向、不传递、不是类成员;
- 优点:灵活高效;缺点:破坏封装,谨慎使用。