C++友元函数和友元类(入门必读)
C++ 是面向对象的编程语言,封装是 C++ 重要的特性之一,用于隐藏对象的内部实现细节。然而在某些情况下,我们可能需要突破封装的界限,本节要讲的友元函数和友元类就是这样一种机制。
所谓友元(friend),简单理解就是允许特定的非成员函数访问一个类的私有成员(private 和 protected 修饰的成员)。友元机制允许一个类将其非公有成员的访问权限授予指定的函数或类。
友元的声明以关键字 friend 开始,它只能出现在类定义的内部。友元声明可以出现在类中的任何地方,并且友元不受其声明出现部分的访问控制的影响。
举个简单的例子:
举个简单的例子:
当然,如果不需要类中所有的成员函数都具有这个特权,可以只为类中的某几个函数设置友元关系。
例如修改上面的程序,只将 Rectangle 类中的 area() 成员函数设置为 Square 的友元,即将第 13 行代码修改为:
所谓友元(friend),简单理解就是允许特定的非成员函数访问一个类的私有成员(private 和 protected 修饰的成员)。友元机制允许一个类将其非公有成员的访问权限授予指定的函数或类。
友元的声明以关键字 friend 开始,它只能出现在类定义的内部。友元声明可以出现在类中的任何地方,并且友元不受其声明出现部分的访问控制的影响。
友元函数
友元函数不是类的成员函数,但它可以访问类的私有成员。举个简单的例子:
#include <iostream> class Circle { private: double radius; public: Circle(double r) : radius(r) {} // 声明友元函数 friend double calculateArea(Circle c); }; // 友元函数的实现 double calculateArea(Circle c) { return 3.14159 * c.radius * c.radius; } int main() { Circle circle(5); std::cout << "Area of circle: " << calculateArea(circle) << std::endl; return 0; }运行结果为:
Area of circle: 78.5397
在这个例子中,calculateArea() 函数虽然不是 Circle 类的成员,但第 11 行将它指定为 Circle 类的友元,所以它可以访问 Circle 类的私有成员 radius。友元类
除了普通函数,类和类之间也可以指定友元关系。如果一个类需要访问另一个类的私有成员,可以使用友元类。举个简单的例子:
#include <iostream> class Rectangle; class Square { private: int side; public: Square(int s) : side(s) {} // 声明友元类 friend class Rectangle; }; class Rectangle { private: int width, height; public: Rectangle(Square s) { width = s.side; // 可以访问 Square 类的私有成员 height = s.side; } int area() { return width * height; } }; int main() { Square square(4); Rectangle rectangle(square); std::cout << "Area of rectangle: " << rectangle.area() << std::endl; return 0; }运行结果为:
Area of rectangle: 16
在这个例子中,Rectangle 类是 Square 类的友元,那么 Rectangle 类中的所有成员函数都可以访问 Square 类的私有成员。当然,如果不需要类中所有的成员函数都具有这个特权,可以只为类中的某几个函数设置友元关系。
例如修改上面的程序,只将 Rectangle 类中的 area() 成员函数设置为 Square 的友元,即将第 13 行代码修改为:
friend int Rectangle::area();此时会发现,编译器提示 Rectangle 类的构造函数无法访问 Square 类的私有成员。
完整实例
定义了一个简单的类 A,A 有一个私有的成员 id。Manager 类中的 adjustID() 成员函数和运算符 << 通过友元声明来访问 A 的私有成员。#include <iostream> // 前置声明 class A; // 定义 Manager 类 class Manager { public: void adjustID(A& a); }; // 定义 class A class A { private: int id; public: // 声明 Manager类中的 adjustID() 成员函数为友元函数 friend void Manager::adjustID(A& a); // 声明 << 运算符为友元函数 friend std::ostream& operator<<(std::ostream& out, const A& a); }; void Manager::adjustID(A& a) { static int index = 0; a.id = index; index++; } // 重载 << 运算符 std::ostream& operator<<(std::ostream& out, const A& a) { out << "ID : " << a.id << std::endl; return out; } int main() { A a1, a2, a3, a4; Manager mgr; mgr.adjustID(a1); mgr.adjustID(a2); mgr.adjustID(a3); mgr.adjustID(a4); std::cout << a1 << a2 << a3 << a4; return 0; }运行结果为:
ID : 0
ID : 1
ID : 2
ID : 3