c++友元函数和友元类详解
来源:互联网 发布:数据库设计大作业 编辑:程序博客网 时间:2024/04/28 08:56
我们在设计类时,一般将数据成员设计成私有的,体现面向对象的信息隐藏和封装性;这些私有的数据成员只能由类成员函数所访问,类外函数不能访问;当在某些情况下,我们可能又需要访问类对象的私有成员,那我们应该怎么办呢?
为了能够访问类私有成员,我们可以采用友元函数,在c++中以关键字friend加以声明,友元可以包括友元函数和友元类;友元函数又可以分为友元函数和友元成员函数;其一般形式分别如下:
友元函数:
friend 函数返回类型 函数名(形参列表)
形如:friend void Display(const CMyTime& time)
友元成员函数:
friend 函数返回类型 类型名::函数名(形参列表)
形如:friend void CMyDate::Display(const CMyTime& time)
友元类:
friend 类型名
形如friend CMyDate
友元函数
友元函数就是将类外的函数,并在本类中加以friend关键字声明,那么这个函数就是本类的友元函数;
下面就将普通函数声明为友元函数;
class CMyTime{public: CMyTime(int hour,int minute, int second); //全局函数Display是本类的友元函数,可以访问其私有数据成员 friend void Display(const CMyTime& time);private: int m_Hour; int m_Minute; int m_Second;};CMyTime::CMyTime(int hour,int minute, int second){ this->m_Hour = hour; this->m_Minute = minute; this->m_Second = second;}
在这个例子中,Display函数是一个全局的普通函数,不属于任何类,没有this指针;我们将其设置为友元函数后就能访问CMyTime类的私有成员了,否则Display函数将会报错;
需要注意的是,为了能够引出类的成员函数,这个友元函数的形参一般是类对象的引用或者指针;
友元函数如下:
void Display(const CMyTime& time){ //因为Display函数没有this指针,引用这些私有成员数据,需要指定对象 cout << time.m_Hour << ":" << time.m_Minute << ":" << time.m_Second << "\n" << endl;}
测试代码如下:
int _tmain(int argc, _TCHAR* argv[]){ CMyTime time(12,13,14); Display(time); return 0;}
运行结果:12:13:14
友元成员函数
通常情况下,类和类之间是相互隔离的,但有可能一个类中的成员函数需要访问另一个类中的私有成员,我们则可将类成员函数设置为友元函数,则可以到达这个目的;
比如 有一个日期类(CMyDate)对象和一个时间类(CMyTime)对象,要求一次性输出其中的日期和时间;
现在先设计一个CMyDate类,用成员函数Display完成输出日期和时间,具体实现如下:
//提前引用声明,表示存在CMyTime类名,类的具体内容后续再声明//在没有具体声明CMyTime类的内容时,不允许定义对象和引用函数名//比如在引用声明class CMyTime之后,添加对象定义CMyTime time 编译器将报错;class CMyTime; class CMyTime* pTime = NULL;//class CMyTime time; error class CMyDate{public: //构造函数 CMyDate(int year,int month, int day); //成员函数,输出具体时间和日期 void Display(const CMyTime& time) const; private: int m_Year; int m_Month; int m_Day;};CMyDate::CMyDate(int year,int month, int day){ this->m_Year = year; this->m_Month = month; this->m_Day = day;}class CMyTime{public: CMyTime(int hour,int minute, int second); //将CMyDate类中Display函数是CMyTime的友元成员函数 friend void CMyDate::Display(const CMyTime& time) const;private: int m_Hour; int m_Minute; int m_Second;};//CMyDate::Display函数实现需要放在类CMyTime声明之后,否则不清楚CMyTime类有哪些成员void CMyDate::Display(const CMyTime& time) const{ cout << m_Year << "/" << m_Month << "/" << m_Day << " " ; cout << time.m_Hour << ":" << time.m_Minute << ":" << time.m_Second << "\n" << endl;}
测试代码如下:
int _tmain(int argc, _TCHAR* argv[]){ CMyTime time(12,12,12); CMyDate date(2017,7,16); //time对象作为实参,输出时间,Display是CMyDate类成员函数,有this指针,作为日期的输出源; date.Display(time); return 0;}
运行结果:2017/7/17 12:12:12
这里需要特别说明c++允许对类作“提前引用”的声明,即只先声明类名,不包含类体;
若在当前函数中需要先引用(不是指引用符&)某个类对象作为形参,但这个类还未声明;我们可以在文件开头先进行类名声明,不声明类体,类体声明稍后再给出,如上述代码中的 class CMyTime
;
在对一个类作了“提前引用声明”后,可以用该类的名字去定义指向该类型对象的指针或者引用,因为定义一个指针变量和引用与这个类大小没有关系,但是不能用于定义对象,定义对象需要声明类体后才行,如上述代码中的class CMyTime* pTime = NULL和Display的形参;
友元类
在c++中我们还可以将一个类设置为另一个类的友元类,这样友元类中的函数都可以访问另一个类的所有成员数据,并且友元类是单向的且不具备传递性,比如类A是类B的友元类,类B是类C的友元类,不能推出类A是类C的友元类,以及类B是类A的友元类;
友元类使用如下:
class CMyDate{public: //构造函数 CMyDate(int year,int month, int day); //成员函数 void Display(const CMyTime& time) const; private: int m_Year; int m_Month; int m_Day;};class CMyTime{public: CMyTime(int hour,int minute, int second); //友元类, CMyDate是CMyTime的友元类 friend CMyDate;private: int m_Hour; int m_Minute; int m_Second;};
测试代码如下:
int _tmain(int argc, _TCHAR* argv[]){ CMyTime time(12,12,12); CMyDate date(2017,7,16); //time对象作为实参,输出时间,Display是CMyDate类成员函数,有this指针,作为日期的输出源; date.Display(time); return 0;}
运行结果:2017/7/17 12:12:12
如果没有了friend关键字声明,在Display函数中将会报如下错误:
error C2248: “CMyTime::m_Hour”: 无法访问 private 成员
error C2248: “CMyTime::m_Minute”: 无法访问 private 成员
error C2248: “CMyTime::m_Second”: 无法访问 private 成员
友元利弊分析
面向对象程序设计的一个基本原则就是封装性和信息隐蔽,而友元函数和友元类却可以访问其他类的私有成员,在一定程度上这是封装性的小破坏;
因此进行类设计时,不推荐将整个类设置为友元类,只将必要成员函数或者普通函数设置为友元类;
由于友元有助于数据共享,使代码更加简洁,但又违背封装性和信息隐蔽,因此进行代码开发时需要做好权衡;
- C++: 友元函数和友元类详解
- c++友元函数和友元类详解
- C++之友元:友元函数和友元类详解
- 【C++】友元类和友元函数(转)
- 『C/C++』友元函数和友元类
- C++——友元函数和友元类
- [c++] 友元详解
- 友元函数和友元类
- 友元函数和友元类
- 友元类和友元函数
- 友元函数和友元类
- 友元函数和友元类
- 友元函数和友元类
- 友元函数和友元类
- 友元函数和友元类
- 友元函数和友元类
- 友元函数和友元类
- 友元函数和友元类
- wdcp安装多种php版本共存
- 卷积神经网络的一些事儿
- Java常用类之基础数据类型包装类
- hdu2768 Cat vs. Dog【最大独立集】
- CentOS查看yum的日志和历史记录
- c++友元函数和友元类详解
- HDU3853:LOOPS(概率dp & 期望)
- 一张图说明softmax layer是什么
- 前端JS知识要点总结(2)
- 输入输出流
- learning之外观模式
- 虚拟机WMware 、Centos、JDK 安装使用
- XGBoost 入门使用方法
- Linux--FTP服务器搭建