一、友元函数
在不放弃私有函数安全性的情况下,使得一个普通函数或者类的成员函数可以访问到封装于某一类的信息(包括:公有、私有、保护成员),在c++中用友元作为实现这个要求的辅助手段。
1.1友元函数基本知识
友元函数既可以是不属于任何类的非成员函数,也可以是另一个类的成员函数。友元函数不是当前类的程序成员。
- 格式
friend 函数类型 函数名称(参数)
- 访问:访问类内数据时,通过作为入口参数传递进来的对象名(或对象指针、对象引用)来访问该对象的数据成员。
访问静态数据或全局变量无需传参。 - 友元函数的优缺点:
优点:效率较高,表达清晰简单,易操作。
缺点:破坏了封装机制。
1.2友元函数的基本使用
1.将非成员函数声明为友元函数
类外函数作为友元函数访问类内数据,需要在类内声明
我们以参观为例子:
#include<iostream>
#include<string>
using namespace std;
class House{
private:
string bedroom;
string livingroom;
public:
House(string m_b,string m_l);
friend void visiting(House &m_h);
/***只是声明visiting函数为本类的友元函数,但visiting函数
并不为本类的类内函数。***/
};
House::House(string m_b,string m_l){
cout<<"创建房间....."<<endl;
bedroom=m_b;
livingroom=m_l;
}
void visiting(House &m_h){ // 传入形参
cout<<"好朋友参观我家"<<endl;
cout <<"好朋友进了"<<m_h.bedroom<<endl;
cout<<"好朋友进了"<<m_h.livingroom<<endl;
}
int main(){
House my_house("我的卧室","我的客厅");
visiting(my_house);
return 0;
}
运行结果如下:
这是讨论友元函数可访问内容的例子:
#include<iostream>
#include<string>
using namespace std;
class House{
protected:
string bedroom;
private:
string livingroom;
public:
House(string m_r,string m_b,string m_l);
friend void visiting(House &m_h);
string room;
};
House::House(string m_r,string m_b,string m_l){
cout<<"创建房间....."<<endl;
room=m_r;
bedroom=m_b;
livingroom=m_l;
}
void visiting(House &m_h){
cout<<"好朋友走进我家"<<endl;
cout<<"好朋友进入门关"<<m_h.room<<endl;访问公有成员
cout <<"好朋友进了卧室"<<m_h.bedroom<<endl;访问保护成员
cout<<"好朋友进了客厅"<<m_h.livingroom<<endl;访问私有成员
}
int main(){
House my_house("我的门关","我的卧室","我的客厅");
visiting(my_house);
return 0;
}
2.一个类的成员函数作为另一个类的友元
将友元函数放在X类中,去访问(Y)中的类内数据
特点:
- 提前声明
- 在需要被访问的友元类中,声明友元函数要标明来来自哪一类。
#include<iostream>
#include<string>
using namespace std;
class House; 要提前声明
class mymate{
public:
void visiting(House & m_h);
};
class House{
private:
string livingroom;
string bedroom;
string room;
public:
House(string m_r,string m_b,string m_l);
*friend void mymate::visiting(House & m_h);* 要注明函数
};
House::House(string m_r,string m_b,string m_l){
cout<<"创建房间....."<<endl;
room=m_r;
bedroom=m_b;
livingroom=m_l;
}
void mymate::visiting(House & m_h){
cout<<"好朋友走进我家"<<endl;
cout<<"好朋友进入了"<<m_h.room<<endl;
cout <<"好朋友进了"<<m_h.bedroom<<endl;
cout<<"好朋友进了"<<m_h.livingroom<<endl;
}
int main(){
mymate mm;
House my_house("我的门关","我的卧室","我的客厅");
mm.visiting(my_house);
return 0;
}
二、友元类
2.1友元类的概念
将一个类(Y类)声明为另一个类(X类)的友元。因此Y类就是x的友元类。
一般形式为:
friend 类名;
例如:
#include<iostream>
using namespace std;
class Y{
.......
};
class X{
.....
friend Y;声明Y为X的友元类
};
当一个类(Y类)被说明成另一个类(X类)的友元类时,它的所有成员函数都成为另一个类的友元函数,这意味着Y类的成员函数可以访问X类中的所有成员。
2.2友元类的基本应用
#include<iostream>
#include<string>
using namespace std;
class House;
class mymate{
public:
void visiting(House & m_h);
};
class House{
private:
string livingroom;
string bedroom;
string room;
public:
House(string m_r,string m_b,string m_l);
friend mymate;与前面“将一个类的成员函数作为另一个函数的友元”的
例子相同,只不过发生变化。
};
House::House(string m_r,string m_b,string m_l){
cout<<"创建房间....."<<endl;
room=m_r;
bedroom=m_b;
livingroom=m_l;
}
void mymate::visiting(House & m_h){
cout<<"好朋友走进我家"<<endl;
cout<<"好朋友进入了"<<m_h.room<<endl;
cout <<"好朋友进了"<<m_h.bedroom<<endl;
cout<<"好朋友进了"<<m_h.livingroom<<endl;
}
int main(){
mymate mm;
House my_house("我的门关","我的卧室","我的客厅");
mm.visiting(my_house);
return 0;
}
需要注意的几点:
- 友元函数是单向的。
例如:类Y为类X的友元类,类Y中的类内函数可访问类X的类内数据,但,类X并不能访问类Y中的数据。 - 友元关系是不可传递的。
例如:类A是类B及类C的友元类。但类B的类内函数不能访问类C的类内数据。需要声明才能继续操作。