一般来说,类的私有成员只能在类的内部访问,类之外是不能访问它们的。但如果将其他类/函数设置为类的友元,那么友元类/函数就可以在前一个类的类定义之外访问其私有成员了。用friend关键字声明友元。
将类比作一个家庭,类的 private
成员相当于家庭的秘密,一般的外人当然不允许探听这些秘密的,只有 friend
才有资格探听这些秘密。
友元的三种形式:普通函数、成员函数、友元类
友元之普通函数形式
1 2 3 4 5 6 7 8 9 10 11 12 13
| class Student { public: Student(int age,const string& name):m_age(age),m_name(name){} private: int m_age; string m_name; };
void access() { Student stu(12, "xy");
}
|
普通函数 access 创建 stu 对象,但由于成员为私有,导致无法访问。
在 Student 类中将该函数的定义放入其中,就可以成功访问到了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Student { friend void access(); public: Student(int age,const string& name):m_age(age),m_name(name){} private: int m_age; string m_name; };
void access() { Student stu(12, "xy"); cout << "age = " << stu.m_age << " name = " << stu.m_name << endl; }
|
友元之成员函数形式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Student { public: Student(int age,const string& name):s_age(age),s_name(name){} private: int s_age; string s_name; };
class Teacher { public: Teacher(int age, const string& name) :t_age(age), t_name(name) {} void accessStu() { Student stu(13, "xy"); } private: int t_age; string t_name; };
|
类 Teacher 企图访问另一个类 Student
的私有成员,同样不可能访问成功。
将类 Teacher 的成员函数 accessStu 声明为 类 Student
友元成员函数即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Teacher { public: Teacher() = default; void accessStu(); };
class Student { friend void Teacher::accessStu(); public: Student(int age,const string& name):s_age(age),s_name(name){} private: int s_age; string s_name; };
void Teacher::accessStu() { Student stu(13, "xy"); cout << "age = " << stu.s_age << " name = " << stu.s_name << endl; }
|
友元类
类 Teacher 要访问 类 Student,需要由类 Student 在其中将 类
Teacher声明为自己的友元类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Student { friend class Teacher; public: Student(int age,const string& name):s_age(age),s_name(name){} private: int s_age; string s_name; };
class Teacher { public: Teacher() = default; void accessStu() { Student stu(13, "xy"); cout << "age = " << stu.s_age << " name = " << stu.s_name << endl; } };
|
友元的特点
- 友元不受类中访问权限的限制——可访问私有成员
- 友元破坏了类的封装性,不能滥用友元
- 友元是单向的——A类是B类的友元类,则A类成员函数中可以访问B类私有成员;但并不代表B类是A类的友元类,如果A类中没有声明B类为友元类,此时B类的成员函数中并不能访问A类私有成员
- 友元不具备传递性——A是B的友元类,B是C的友元类,无法推断出A是C的友元类
- 友元不能被继承——因为友元破坏了类的封装性,为了降低影响,设计层面上友元不能被继承