友元的概念:
友元是一种定义在类外部的普通函数或类,但它需要在类体内进行说明,为了与该类的成员函数加以区别,在说明时前面加以关键字friend。友元不是成员函数,但是它可以访问类中的私有成员。
友元的背景:
类具有封装和信息隐藏的特性。只有 类的成员函数 才能访问类的私有成员,程序中的其他函数是无法访问私有成员的。非成员函数可以访问类中的公有成员,但是如果将 数据成员 都定义为公有的,这又破坏了隐藏的特性。另外,应该看到在某些情况下,特别是在对某些成员函数多次调用时,由于 参数传递 ,类型检查和安全性检查等都需要时间开销,而影响程序的运行效率。
为了解决上述问题,提出一种使用友元的方案。友元是一种定义在类外部的普通函数或类,但它需要在类体内进行说明,为了与该类的成员函数加以区别,在说明时前面加以关键字friend。友元不是成员函数,但是它可以访问类中的私有成员。友元的作用在于提高程序的运行效率,但是,它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。不过,类的访问权限确实在某些应用场合显得有些呆板,从而容忍了友元这一特别语法现象
友元的目的:
友元的目的就是让一个函数或者类访问另一个类内的私有成员
友元的关键字及其语法:
关键字:friend
语法: friend (数据类型 + 函数名) / 类名
友元的相关注意事项:
(1) 友元关系不能被继承。
(2) 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。
(3) 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明。
友元的三种用法:
全局函数做友元
类做友元
成员函数做友元
全局函数做友元:
#include <iostream>
#include <string>
using namespace std;
// 房屋类
class Building
{
// 告诉编译器 laoWang全局函数是 Building类 的好朋友,可以访问Building对象的私有成员
friend void NearDoor_Mr_wang1(Building *building);
friend void NearDoor_Mr_wang2(Building &building);
friend void NearDoor_Mr_wang3(Building building);
public:
Building()
{
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
}
string m_SittingRoom; // 客厅
private:
string m_BedRoom; // 卧室
};
//全局函数
void NearDoor_Mr_wang1(Building *building)
{
cout << "隔壁老王 全局函数 正在访问:(地址传递) " << building->m_SittingRoom << endl;
cout << "隔壁老王 全局函数 正在访问:(地址传递) " << building->m_BedRoom << endl;
}
void NearDoor_Mr_wang2(Building &building)
{
cout << "隔壁老王 全局函数 正在访问:(引用传递) " << building.m_SittingRoom << endl;
cout << "隔壁老王 全局函数 正在访问:(引用传递) " << building.m_BedRoom << endl;
}
void NearDoor_Mr_wang3(Building building)
{
cout << "隔壁老王 全局函数 正在访问:( 值传递 ) " << building.m_SittingRoom << endl;
cout << "隔壁老王 全局函数 正在访问:( 值传递 ) " << building.m_BedRoom << endl;
}
void test01()
{
Building building;
NearDoor_Mr_wang1(&building);
NearDoor_Mr_wang2(building);
NearDoor_Mr_wang3(building);
}
int main()
{
test01();
}
类做友元:
#include <iostream>
#include <string>
using namespace std;
// 类作友元
class Building;
class Mr_wang
{
public:
Mr_wang();
void visit(); //参观函数 访问Building中的属性
Building * building;
private:
};
// 房屋类
class Building
{
// 告诉编译器,LaoWang类是Building类的好朋友,可以访问Building类的私有成员
friend class Mr_wang;
public:
Building();
string m_SittingRoom; // 客厅
private:
string m_BedRoom; // 卧室
};
// 类外定义成员函数
Building::Building()
{
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
}
Mr_wang::Mr_wang()
{
// 创建建筑物对象
building = new Building;
}
void Mr_wang::visit()
{
cout << "隔壁老王Mr_wang类正在访问:" << building->m_SittingRoom << endl;
cout << "隔壁老王Mr_wang类正在访问:" << building->m_BedRoom << endl;
}
void test01()
{
Mr_wang w;
w.visit();
}
int main()
{
test01();
return 0;
}
成员函数做友元:
#include <iostream>
#include <string>
using namespace std;
class Building;
class Mr_wang
{
public:
Mr_wang();
void visit1(); //让visit1()函数 可以 访问Building中的私有成员
void visit2(); //让visit2()函数 不可以 访问Building中的私有成员
Building *building;
private:
};
class Building
{
// 告诉编译器,Mr_wang类下的visit1()函数是Building类的好朋友,可以访问Building的私有成员
friend void Mr_wang::visit1();
public:
Building();
string m_SittingRoom; //客厅
private:
string m_BedRoom; //卧室
};
Mr_wang::Mr_wang()
{
building = new Building;
}
void LaoWang::visit1()
{
cout << "隔壁老王Mr_wang类中的visit1()函数正在访问:" << building->m_SittingRoom << endl;
cout << "隔壁老王Mr_wang类中的visit1()函数正在访问:" << building->m_BedRoom << endl;
}
void LaoWang::visit2()
{
cout << "隔壁老王Mr_wang类中的visit2()函数正在访问:" << building->m_SittingRoom << endl;
//cout << "隔壁老王Mr_wang类中的visit2()函数正在访问:" << building->m_BedRoom << endl; //错误!私有属性不可访问
}
Building::Building()
{
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
}
void test01()
{
Mr_wang w;
w.visit1();
w.visit2();
}
int main()
{
test01();
return 0;
}