友元函数
-----------------siwuxie095
在C++ 中,存在着一种朋友关系,这种朋友关系如果体现在函数上,
就称之为 友元函数,如果体现在类上,就称之为 友元类
这里介绍 友元函数
友元函数
就定义函数的情形来说,一种是将其定义为全局函数,另一种
是将其定义在类中,使它成为类的成员函数
当把全局函数声明为友元函数,就称之为友元全局函数,当把
成员函数声明为另一个类的友元函数,就称之为友元成员函数
友元全局函数
看如下实例:
定义一个坐标类:Coordinate
如果想要定义一个友元函数,就要使用关键字:friend
使用方法:通过关键字friend 接友元函数
友元函数其实就是一个函数的声明,声明的最后以分号结尾,同时一定
要传入当前类的对象或引用或指针,总之,要能通过该函数访问到对象
中私有的数据成员或保护的数据成员
友元函数的使用方法:
printXY() 即 打印横纵坐标,需要传入一个 Coordinate 的引用,
访问时,可以直接访问私有数据成员
如果没有将printXY() 声明为 Coordinate 的友元,那么直接访
问私有数据成员,编译器就会报错
注意:传入引用或指针,传递效率更高,执行速度更快,提倡
传入引用或指针,而不提倡直接传入对象
在main() 函数中调用 printXY() 时,需要先实例化一个 Coordinate
的对象,然后将该对象传递进去即可
友元成员函数
看如下实例:
此时仍然使用关键字:friend,但注意后面的写法:
使用的函数仍然是printXY(),但此时 printXY() 并不是一个全局函数,
而是Circle 类中的成员函数,如果要将 Circle 类的 printXY() 声明为
Coordinate 类的友元函数,需要将 Circle 写出来,后面接 ::,后面再
接 printXY()
在使用时:
Circle 类中 printXY() 的实现方法和前面的实现方法基本相同
友元给我们带来方便的同时,也带来了一些风险:
当在Coordinate 类中将 Circle 类的 printXY() 声明为它的友元之后,
也就破坏了Coordinate 类的封装性。破坏了封装性之后,对于数据
的直接访问虽然是方便了,但是如果不小心改变了数据的值,也不易
察觉
所以,风险和方便往往是相互矛盾的。除非有特殊的需要,否则一般
情况下,不建议处处使用友元,把友元当做自己知识的一种炫耀
程序:
Match.h:
#ifndef MATCH_H #define MATCH_H
#include <iostream> using namespace std;
class Time;//注意这里要声明 class Match { public: //声明printTime2()时要用到 Time //所以必须要在 Match 的上面通过 Time 声明一下, //有这样一个类,后面的时候会定义 void printTime2(Time &t); };
#endif |
Match.cpp:
#include"Match.h" #include"Time.h"
void Match::printTime2(Time &t) { cout << t.m_iHour << ":" << t.m_iMinute << ":" << t.m_iSecond << endl; } |
Time.h:
#ifndef TIME_H #define TIME_H
#include"Match.h"//这里要加上Match的头文件 #include <iostream> using namespace std;
class Time { //作为友元函数来说,位置并没有约束,写在哪里都行, //即 friend 的友元声明,与访问限定符并不形成交叉关系 // //建议写在类的最前边,因为对于类来说,对外如何进行暴露是非常重要的 //把重要的信息放在前边有助于编程过程中减小犯错的概率 friendvoid printTime1(Time &t);//友元全局函数 friendvoid Match::printTime2(Time &t);//友元成员函数
public: Time(int hour, int min, int sec); private: int m_iHour; int m_iMinute; int m_iSecond; };
#endif |
Time.cpp:
#include"Time.h"
Time::Time(int hour, int min, int sec) { m_iHour = hour; m_iMinute = min; m_iSecond = sec; } |
main.cpp:
#include"stdlib.h" #include"Time.h" #include"Match.h"
//提倡把函数的声明写在前面,定义写在后面 void printTime1(Time &t);
int main(void) { Time t(6, 34, 25); printTime1(t); Match m; m.printTime2(t); system("pause"); return0; }
//通过声明友元,就能使得传入进来的对象 //去访问它私有的数据成员和成员函数 void printTime1(Time &t) { cout << t.m_iHour << ":" << t.m_iMinute << ":" << t.m_iSecond << endl; } |
【made by siwuxie095】