1. 友元函数
1.1 友元函数的概念
友元函数是一个非成员函数,它被类声明为“友元”,从而能够访问类的私有成员和保护成员。正常情况下,类的外部函数是不能访问类的私有成员的,而友元函数打破了这一限制。
class MyClass {
private:
int x;
public:
MyClass() : x(10) {}
friend void showX(MyClass obj); // 友元函数声明
};
// 友元函数定义
void showX(MyClass obj) {
cout << "The value of x: " << obj.x << endl; // 访问私有成员
}
1.2 大白话解释为什么
类的私有成员本来是为了保护数据不被外部随意访问,确保类的封装性。然而,有时我们确实需要让外部的非成员函数访问类的私有数据(例如做一些特定操作或性能优化)。这时,我们通过friend
关键字声明友元函数,让它“破例”访问类的私有成员,但这种访问是有限制的——友元函数不属于类,不能直接访问类的其他成员。
1.3 实际使用
1.3.1示例:友元函数访问私有数据
#include <iostream>
using namespace std;
class Box {
private:
int width;
public:
Box(int w) : width(w) {} // 构造函数
// 友元函数声明
friend void printWidth(Box box);
};
// 友元函数定义
void printWidth(Box box) {
cout << "Box width: " << box.width << endl; // 直接访问私有成员
}
int main() {
Box box(10);
printWidth(box); // 通过友元函数访问私有成员
return 0;
}
1.3.2代码解释:
Box
类中有一个私有成员width
,普通的成员函数不能直接访问它。- 通过
friend
关键字,printWidth
函数成为了Box
类的友元函数,它可以访问Box
类的私有成员width
。 - 这段代码的执行结果会输出
Box width: 10
,显示width
的值。
1.3.3注意事项:
- 友元函数并不属于类,类外的普通函数通过
friend
关键字可以访问类的私有数据,但它并不能访问类的成员函数或其他私有成员。 - 友元函数的访问权限仅限于类的私有和保护成员。
- 友元函数在类内声明,在类外定义。
2. 友元类
2.1 友元类的概念
友元类是指一个类允许另一个类访问它的私有成员。通过friend
关键字,我们可以让一个类成为另一个类的友元类,从而让这个类的所有成员函数访问另一个类的私有成员。
class Car; // 提前声明类
class Engine {
public:
void showCarSpeed(Car& car); // 成员函数,访问Car的私有数据
};
class Car {
private:
int speed;
public:
Car(int s) : speed(s) {} // 构造函数
// 声明Engine为友元类
friend class Engine; // Engine是Car的友元类
};
// Engine类的成员函数可以访问Car的私有成员
void Engine::showCarSpeed(Car& car) {
cout << "Car speed: " << car.speed << endl; // 直接访问Car的私有成员
}
int main() {
Car car(100);
Engine engine;
engine.showCarSpeed(car); // Engine通过友元关系访问Car的私有成员
return 0;
}
2.2 大白话解释为什么
有时候两个类之间的功能紧密相关,需要彼此直接访问对方的私有数据。直接暴露所有的私有成员可能破坏封装性,但通过友元类,可以让一个类“授权”另一个类访问它的私有成员,而不暴露给外界。这让两个类能够协同工作,同时又不破坏类的封装性。
2.3 实际使用
2.3.1示例:友元类之间的合作
#include <iostream>
using namespace std;
class Engine; // 提前声明
class Car {
private:
int speed;
public:
Car(int s) : speed(s) {}
// 声明Engine类为友元类
friend class Engine; // Engine可以访问Car的私有成员
};
class Engine {
public:
void showCarSpeed(Car car) {
cout << "Car speed: " << car.speed << endl; // 访问Car类的私有成员
}
};
int main() {
Car car(120);
Engine engine;
engine.showCarSpeed(car); // Engine访问Car的私有成员
return 0;
}
2.3.1代码解释:
Car
类包含一个私有成员speed
,我们希望Engine
类能够访问它。- 通过
friend class Engine;
,我们让Engine
类成为Car
类的友元类,因此Engine
类的成员函数能够直接访问Car
的私有成员speed
。 - 在
main
函数中,创建了一个Car
对象,并通过Engine
类访问其私有成员。
2.3.3注意事项:
- 友元类能够访问被声明为友元的类的所有私有成员。
- 友元类不是继承关系,它只是被授权访问类的私有数据,因此它不具有类之间的继承功能。
- 如果多个类需要访问彼此的私有成员,可以将它们互相声明为友元类。
- 友元类也是在类内声明,在类外定义。
3. 总结
3.1 友元函数总结
- 友元函数是非成员函数,但被允许访问类的私有成员。
- 通过
friend
关键字声明友元函数,它可以访问类的私有数据。 - 友元函数并不是类的成员,它只能访问类的私有和保护成员,而不能访问类的其他成员函数或成员变量。
- 友元函数的访问权限仅限于该类的私有和保护成员。
3.2 友元类总结
- 友元类是允许访问另一个类私有成员的类。
- 通过
friend class
关键字声明友元类,使得友元类的成员函数能够访问被声明类的私有数据。 - 友元类和继承关系不同,它只是授权给一个类访问另一个类的私有成员,不会影响类的继承关系。
- 友元类是双向授权的,即一个类可以将另一个类声明为友元类,反之亦然。