一、前言:
有时候,普通函数需要直接访问一个类的私有或者保护成员。如果没有友元机制的话,那么只有把这些成员的权限设置为公共的,从而,任何函数都可以无拘束的访问它了。为了同时可以保护类的私有成员,又可以实现数据共享,所以就可以使用友元机制了。
二、友元通常使用场景
- 运算符重载某些地方,使用友元(后面博客会讲这方面的内容)
- 两个类数据共享的时候,使用友元
三、友元的使用
注意事项:
- 如果访问类的非静态成员时,需要友元提供一个对象作为参数,才可以访问
如果访问类的静态成员时,不需要参数
普通友元函数
目的:使用普通函数,就可以访问类的私有成员。
例子:
#include<iostream>
#include<string>
using namespace std;
class Student
{
private:
string name;
int age;
static int num;
public:
Student(string s, int a)
{
name = s;
age = a;
}
friend void print_no_static(const Student &); //通过友元函数,打印出所有的非静态成员
friend void print_static(); //通过友元函数,打印出所有的静态成员
};
int Student::num = 10;
void print_no_static(const Student & s)
{
cout << "非静态成员:" << endl;
cout << "name: " << s.name << endl;
cout << "age: " << s.age << endl;
}
void print_static()
{
cout << "静态成员:" << endl;
cout << "num= " << Student::num << endl;
}
void main()
{
Student s("Ouyang", 21);
print_no_static(s);
print_static();
system("pause");
}
输出结果:
作为普通函数,其实现是在类的外部,调用则是直接按照正常的函数调用。
- 类成员中的一个成员函数,作为另外一个类的友元函数
目的:该函数需要访问另外一个类的私有或者保护成员,比对其进行一些操作。现实生活中的一个例子就是:老师类需要对学生的成绩进行修改。
例子:
#include<iostream>
#include<string>
using namespace std;
class Student;
class Teacher
{
public :
void change_student_grade(Student & s); //定义一个成员函数
};
class Student
{
private:
int grade;
string name;
public:
Student(string s, int g)
{
grade = g;
name = s;
}
friend void Teacher::change_student_grade(Student & s); //声明该成员函数为Student的友元函数
void print()
{
cout << "name= " << name << endl;
cout << "grade= " << grade << endl;
}
};
void Teacher::change_student_grade(Student & s) //实现该友元函数
{
s.grade = 95;
}
int main()
{
Student s("Ouyang", 100);
Teacher t;
cout << "修改前:" << endl;
s.print();
t.change_student_grade(s);
cout << "修改后:" << endl;
s.print();
system("pause");
return 0;
}
输出结果:
一个类的成员函数作为另外一个类的成员函数时,函数的声明在类内,实现还是在类外。
- 友元类
目的:使用单个声明使Y类的所有函数成为类X的友元,它提供一种类之间合作的一种方式,使类Y的对象可以具有类X和类Y的功能。
例子:
#include<iostream>
#include<string>
using namespace std;
class Student;
class Teacher
{
public :
void print(Student & s);
};
class Student
{
private:
int age;
string name;
friend Teacher; //声明Teacher为Student的友元类
public :
Student(string s, int a)
{
name = s;
age = a;
}
};
void Teacher::print(Student & s)
{
cout << "name: " << s.name << endl;
cout << "age: " << s.age << endl;
}
int main()
{
Student s("Ouyang", 21);
Teacher t;
t.print(s);
system("pause");
return 0;
}
输出结果:
四、友元函数和类成员函数的区别
- 成员函数有this指针,而友元函数没有this指针。
- 友元函数是不能被继承的,就像父亲的朋友未必是儿子的朋友。