什么是友元?
**友元(friend)** 就是让一个类"开个后门",允许别的函数或者别的类访问自己的私有成员(private)和保护成员(protected)。
正常情况下,类的私有成员只有自己内部的成员函数才能访问,外部函数和其他类都不行。但有时候,我们确实需要让某个外部函数或另一个类来访问这些私有数据,这时候就用友元。
友元的两种形式
1. 友元函数
把一个普通函数声明为某个类的友元,这个函数就能访问该类的私有成员。
cpp
#include <iostream>
using namespace std;
class Box {
private:
double width;
public:
Box(double w) : width(w) {}
// 声明友元函数
friend void printWidth(Box b);
};
// 友元函数的定义
void printWidth(Box b) {
// 可以直接访问私有成员 width
cout << "宽度 = " << b.width << endl;
}
int main() {
Box box(10.5);
printWidth(box); // 输出:宽度 = 10.5
return 0;
}
2. 友元类
把一个类声明为另一个类的友元,那么这个类的所有成员函数都能访问对方的私有成员。
cpp
class A {
private:
int secret;
public:
A(int s) : secret(s) {}
friend class B; // 声明B是A的友元类
};
class B {
public:
void showSecret(A a) {
// B可以访问A的私有成员
cout << "秘密数字: " << a.secret << endl;
}
};
重要注意事项
-
友元关系不能传递
A是B的友元,B是C的友元,不代表A是C的友元。就像你朋友的朋友不一定是你的朋友。
cpp
#include <iostream>
using namespace std;
class C; // 前置声明
class A {
private:
int secretA;
public:
A(int s) : secretA(s) {}
friend class B; // A把B设为友元
void showC(C c); // 后面再实现
};
class B {
private:
int secretB;
public:
B(int s) : secretB(s) {}
friend class C; // B把C设为友元
void showA(A a) {
// ✅ B是A的友元,可以访问A的私有成员
cout << "A的秘密: " << a.secretA << endl;
}
};
class C {
private:
int secretC;
public:
C(int s) : secretC(s) {}
void showB(B b) {
// ✅ C是B的友元,可以访问B的私有成员
cout << "B的秘密: " << b.secretB << endl;
}
void showA(A a) {
// ❌ 编译错误!C不是A的友元,不能访问A的私有成员
// cout << "A的秘密: " << a.secretA << endl;
cout << "C不能访问A的私有成员!" << endl;
}
};
// 现在来实现A::showC
void A::showC(C c) {
// ❌ A也不是C的友元,不能访问C的私有成员
// cout << "C的秘密: " << c.secretC << endl;
cout << "A也不能访问C的私有成员!" << endl;
}
int main() {
A a(100);
B b(200);
C c(300);
b.showA(a); // ✅ 输出:A的秘密: 100
c.showB(b); // ✅ 输出:B的秘密: 200
c.showA(a); // ❌ 编译报错
a.showC(c); // ❌ 编译报错
return 0;
}
2.友元关系是单向的
A把B设为友元,但B并没有把A设为友元,所以A不能访问B的私有成员。
cpp
#include <iostream>
using namespace std;
class B; // 前置声明
class A {
private:
int moneyA;
public:
A(int m) : moneyA(m) {}
friend class B; // ✅ A说:B是我的好朋友,可以看我的钱
void showBmoney(B b); // 声明,后面实现
};
class B {
private:
int moneyB;
public:
B(int m) : moneyB(m) {}
// ⚠️ 注意:B没有把A设为友元!
// 没有这行:friend class A;
void showAmoney(A a) {
// ✅ B是A的友元,可以访问A的私有成员
cout << "B看到了A的钱: " << a.moneyA << "元" << endl;
}
};
// 在类外实现A的成员函数
void A::showBmoney(B b) {
// ❌ A不是B的友元,不能访问B的私有成员
// cout << "A想看B的钱: " << b.moneyB << "元" << endl;
cout << "A看不到B的钱,因为B没把A当朋友!" << endl;
}
int main() {
A a(1000);
B b(500);
b.showAmoney(a); // ✅ 输出:B看到了A的钱: 1000元
a.showBmoney(b); // ❌ 编译错误
return 0;
}
3.友元不是类的成员
它只是一个"特权通行证",不属于类本身。
4.友元会破坏封装性
能用成员函数解决的问题尽量不用友元,只在确实需要时才使用
什么时候用友元?
-
运算符重载时经常用到(比如
<<输出运算符) -
两个类需要紧密合作时
-
某些性能敏感场景,避免频繁调用公有接口
有帮助的话留下小小的赞感谢!