C++中的 友元关系
- 在某些场合,一个完全无关的类由于某些特殊原因需要访问到某个 protected 成员,甚至某个 private 成员
- 如果所有的东西都声明成public 吧。这样固然可以,但这样就把原来我们想方设法要保护的方法或属性又暴漏了。
- 在 C++ 里,友元(Friend)是一种特殊的机制,它允许一个类或函数访问另一个类的私有成员和保护成员,这打破了类的封装性原则,但在某些特定场景下能提高代码的灵活性和效率。
- 声明一个友元关系的语法:只要在类声明里的某个地方加上一条 friend class ** 就行了。
- • 注:这条语句可以放在任何地方,放在 public,protected, private 段落里都可以。
1. 友元函数
友元函数是在类外部定义的普通函数,但在类内部将其声明为友元,这样该函数就能访问类的私有和保护成员。
#include <iostream>
class Rectangle {
private:
int width;
int height;
public:
Rectangle(int w, int h) : width(w), height(h) {}
// 声明友元函数
friend int calculateArea(const Rectangle& rect);
};
// 友元函数的定义
int calculateArea(const Rectangle& rect) {
return rect.width * rect.height;
}
int main() {
Rectangle rect(5, 3);
std::cout << "Area: " << calculateArea(rect) << std::endl;
return 0;
}
在这个例子中,calculateArea
是一个友元函数,它可以直接访问 Rectangle
类的私有成员 width
和 height
,从而计算矩形的面积。
2. 友元类
可以将一个类声明为另一个类的友元类,这样友元类的所有成员函数都可以访问该类的私有和保护成员。
#include <iostream>
class Rectangle {
private:
int width;
int height;
public:
Rectangle(int w, int h) : width(w), height(h) {}
// 声明友元类
friend class AreaCalculator;
};
class AreaCalculator {
public:
int calculateArea(const Rectangle& rect) {
return rect.width * rect.height;
}
};
int main() {
Rectangle rect(5, 3);
AreaCalculator calculator;
std::cout << "Area: " << calculator.calculateArea(rect) << std::endl;
return 0;
}
在这个例子中,AreaCalculator
是 Rectangle
类的友元类,所以 AreaCalculator
类的成员函数 calculateArea
可以直接访问 Rectangle
类的私有成员 width
和 height
。
3. 友元成员函数
除了将整个类声明为友元,还可以将另一个类的某个成员函数声明为友元。
#include <iostream>
class Rectangle; // 前向声明
class AreaCalculator {
public:
int calculateArea(const Rectangle& rect);
};
class Rectangle {
private:
int width;
int height;
public:
Rectangle(int w, int h) : width(w), height(h) {}
// 声明友元成员函数
friend int AreaCalculator::calculateArea(const Rectangle& rect);
};
// 友元成员函数的定义
int AreaCalculator::calculateArea(const Rectangle& rect) {
return rect.width * rect.height;
}
int main() {
Rectangle rect(5, 3);
AreaCalculator calculator;
std::cout << "Area: " << calculator.calculateArea(rect) << std::endl;
return 0;
}
在这个例子中,AreaCalculator
类的 calculateArea
成员函数被声明为 Rectangle
类的友元,因此它可以访问 Rectangle
类的私有成员。
4.友元关系的特点
- 非传递性:如果类 A 是类 B 的友元,类 B 是类 C 的友元,这并不意味着类 A 是类 C 的友元。
- 单向性:友元关系是单向的,即如果类 A 是类 B 的友元,并不意味着类 B 是类 A 的友元。
- 不具有继承性:友元关系不能被继承,即如果类 A 是类 B 的友元,类 C 是类 B 的派生类,这并不意味着类 A 是类 C 的友元。
5. 注意事项
- 友元机制破坏了类的封装性,过度使用会使代码的可维护性变差,因此应谨慎使用。
- 友元函数不属于类的成员函数,它没有
this
指针。
通过友元关系,可以在必要时让特定的函数或类访问类的私有和保护成员,从而实现更灵活的编程。
未完待续。。。