C++中的友元小结
我们知道,在一个类总可以有公有的(public)成员和私有的(private)成员。在类外可以访问公用成员,只有本类中的函数可以访问本类的私有成员。
现在,我们学习一种新的情况——友元。
在C++中,这种关系以关键字friend声明。友元可以访问与其有好友关系的类中的私有成员。包括友元函数和友元类。
友元函数如果在本类意外的其他地方定义了一个函数(这个函数可以是不属于任何类的非成员函数,也可以是其他类的成员函数),在类体中用friend对该函数进行声明,此函数就称为本类的友元函数。一个类的友元函数可以访问这个类中的私有成员。
========通过程序1.1来了解友元函数的性质和作用============
分析:
display函数是一个在类外定义的非成员函数,它不属于任何一个类。如果在Time类的定义体中未声明display函数为friend函数,它是不能引用Time中的私有成员hour,minute和second的。
否则就会提示hour,minute和second是private函数,没有权限访问的错误。
由于我们在定义Time的时候,声明了display函数是其友元函数,Time所定义的所有的对象都会把dispaly函数作为自己的“朋友”,允许display函数引用其私有成员hour,minute和second.
但是要注意,我们在使用dispaly函数的时候,形参是对象的引用,实参是对象。
我们在友元函数中引用这些私有数据成员时,必须加上对象名,而不能写成:
分析:
为了在Time类的定义中,能够定义形参是Date类对象引用的函数display。我们在代码的第三行,提前声明了类Date。
然后,在定义类Date的时候,我们在程序的第18行代码中,声明了Time的成员函数display函数为Date的友元成员函数,以达到能够访问Date中的私有数据成员的目的。
因为dispaly是Time中的成员函数,所以该函数可以访问Time类对象的私有数据成员;又因为Date类在声明的时候,将display函数声明为了其友成员函数,所以display函数也可以访问Date中的私有数据成员。
所以在程序的第倒数第3行才可以顺利的输出日期和时间。
友元类不仅可以将一个函数声明为一个类的“朋友”,而且可以将一个类(例如类B)声明为另一个类(例如类A)的“朋友”。这是B类就是A类的友元类。友元类B中的所有函数都是A类的友元函数,可以访问A类中的所有成员。
在A类的定义体中用一下语句声明B类为其友元类:
#include<iostream>using namespace std;class Date;//对Date类的提前引用声明class Time {public:Time(int ,int ,int);void display(Date &);private:int hour;int minute;int second;};class Date{public:Date(int,int,int);friend class Time;//声明Time类为本类的友元类 private:int month;int day;int year; };Time::Time(int h,int m,int s)//定义类Time的构造函数{hour=h;minute=m;second=s;} /*display函数是Time类的成员函数;display函数是Date类的友元函数*/ void Time::display(Date &d)//display函数的作用是输出年月日和时分秒{cout<<d.year<<"/"<<d.month<<"/"<<d.day<<endl;//引用Date类对象中的私有成员cout<<hour<<":"<<minute<<":"<<second<<endl; } Date::Date(int y,int m,int d)//类Date的构造函数 {year=y;month=m;day=d;}int main(){Time t1(15,30,30);Date d1(2013,9,8);t1.display(d1);return 0;}
运行结果同示例代码1.2是一样的说明:
关于友元有两点需要说明:
(1)友元的关系是单向的,而不是双向的。如果只声明了B类是A类的友元类,则B中的成员函数可以访问A中的私有数据成员;而A中的成员函数是不可以访问B中的数据成员的。
如果想要实现A和B互为友元类的话,需要即在A的声明体中声明B是其友元类,又要在B的声明体中声明A是其友元类。
(2)友元类的关系不能传递。如果B是A的友元类,C是B的友元类,不等于C是A的友元类。
在实际工作中,除非有必须,一般并不把整个类声明为友元类,而只是将确实有需要的成员函数声明为友元函数,这样更加安全一些。
