一、开篇
友元的描述的对象是类和函数 ,函数可以是类的成员函数和非成员函数。当我们需要访问一个类的非公有成员时(private、protected),这时候友元就可以派上用场啦。
二、友元知识点
在实际使用中,友元可以是:函数和类。我们只需要使用friend 关键字在类中对他们进行声明即可。
友元声明只能出现在类定义的内部,可以在类定义中的任意位置进行友元声明。但是,在实际使用中,最好在类定义的开始或者结尾处集中进行友元的声明,这样比较规范!!!
友元的声明仅仅指定了访问的权限,但是本质上不是一个函数声明,所以,如果我们需要使类的用户(类示例、派生类)能够调用某个友元函数,那么就需要在友元声明之外再对在这里插入代码片 该函数进行一次声明。在实际使用中,通常把友元的声明和类本身放置在同一个头文件中 。
注意:许多编译器并没有强制限定友元函数必须在使用之前在类的外部进行声明。但是,在类的外部进行函数声明是一种比较保险的作用。
友元不是类的成员,所以,他不受所在区域访问控制级别的约束(public、private、protected对他无效)
三、友元的三种使用场景
友元存在三种使用场景:友元类 、友元成员函数 、友元非成员函数
(3-1)友元类
这这样一个场景:两个学生student_A和student_B,其中student_B是student_A的好朋友,所以希望能够访问student_A的私有数据,所以在设计中在student_A的类定义中将student_A声明为其友元类,这样则可以在student_B中访问student_A的私有数据成员。参考代码如下:
#include <iostream>
class student_B;
class student_A{
friend student_B;
private:
int m_age = 25;
std::string m_name = "xiaoZhang";
std::string getStudentAName()
{
return m_name;
}
int getStudentAAge()
{
return m_age;
}
};
class student_B{
public:
int getStudentInfo(student_A &stu)
{
std::cout<<"stu_A name:"<<stu.m_name<<"\r\n"<<"stu_A age : "<<stu.m_age<<std::endl;
}
private:
int m_age = 22;
std::string m_name = "xiaoLi";
};
int main() {
student_B stu_b;
student_A stu_a;
stu_b.getStudentInfo(stu_a);
return 0;
}
每个类负责控制自己的友元类和友元函数。友元关系不具有传递性。
(3-2)友元成员函数
可以在类中只把一个类的成员函数声明为友元函数。例如:有两个学生Student_A和Student_B,将Student_B的获取学生信息getInfo() 声明为Student_A学生的友元函数,那么Student_B的getInfo() 则可以访问Student_A学生的私有数据成员。参考代码如下:
#include <iostream>
class student_A;
int getStudentInfo(student_A &stu);
class student_B{
public:
int getStudentInfo(student_A &stu);
private:
int m_age = 22;
std::string m_name = "xiaoLi";
};
class student_A{
friend int student_B::getStudentInfo(student_A &stu);
private:
int m_age = 25;
std::string m_name = "xiaoZhang";
std::string getStudentAName()
{
return m_name;
}
int getStudentAAge()
{
return m_age;
}
};
int student_B::getStudentInfo(student_A &stu) {
std::cout<<"stu_A name:"<<stu.m_name<<"\r\n"<<"stu_A age : "<<stu.m_age<<std::endl;
return 0;
}
int main() {
student_B stu_b;
student_A stu_a;
stu_b.getStudentInfo(stu_a);
return 0;
}
在友元的三种使用方法中,将类的成员函数作为某一个类的友元函数,在程序的结构编写上需要格外注意代码的顺序,否则将会非常容易出错。以以上代码为例,必须按照如下的方式对代码进行结构上的处理:
-
首先定义student_B 类,其中声明getStudentInfo() 函数,但是不能定义该函数。除此之外,还需要在student_B 类定义之前先声明student_A 类,因为在getStudentInfo() 中使用到了student_A。 -
接着,定义student_A 类,在该类定义中先对student_B类的getStudentInfo() 进行友元声明。 -
最后定义getStudentInfo() 函数,这样才能在该函数中使用student_A的私有成员。
(3-3)友元非成员函数
可以在类中把一个非成员函数声明为友元函数,那么该函数可以访问该类中的私有成员。例如下列代码:
#include <iostream>
class student_A{
friend int getStudentInfo();
private:
int age = 25;
std::string name = "xiaoZhang";
std::string getStudentAName()
{
return name;
}
};
int getStudentInfo()
{
student_A a;
std::cout<<"student name:"<<a.getStudentAName()<<std::endl;
std::cout<<"student age:"<<a.age<<std::endl;
return -1;
}
int main() {
getStudentInfo();
return 0;
}
|