通过之前所学内容,我们知道,在c++中,由于类具有的封装性和信息隐藏的特性,所以我们访问私有成员时通常以类的成员函数作为接口,因为程序中的其他函数是无法访问类中的私有成员的;那么如果就是想要不采用这种方式,还有什么办法可以访问到类的私有成员呢?这就引出了本篇博客所讲的重点:友元
(一)友元函数
首先来看下面一段代码:
#include<iostream>
using namespace std;
#include<stdlib.h>
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
:_year(year)
, _month(month)
, _day(day)
{
cout << "Date()" << endl;
}
private:
int _year;//年
int _month;//月
int _day;//日
};
//友元函数
//友元类
void Print(const Date&d)
{
cout << d._year << "-" << d._month << "-" << d._day << endl;
}
int main()
{
Date d1;
Print(d1);
system("pause");
return 0;
}
此段代码中,我们在类外定义了Print()函数,试图通过它来访问类中的私有成员,由之前知识所学,显然这是编译不通过的。
这里就不得不提到“友元”;
要点一:友元的概念--->
友元是一种说明在类体内的非成员函数,为了与该类的成员函数加以区别,在说明时前面加上关键字friend。
要点二:
1 . 友元函数不是类的成员函数。
2 . 友元函数可以通过对象访问所有成员,私有和保护成员也一样。
要点三:友元的两大分类--->
1.友元函数
2.友元类
综上,这里要想编译通过,我们可以在类中声明Print()是友元函数,即
friend void Print(const Date&d);
(二)友元类
首先来看下面一段代码:
class Time
{
//friend class Date;
private:
int _hour;
};
class Date
{
friend void Print(const Date&d);
public:
Date(int year = 1900, int month = 1, int day = 1)
:_year(year)
, _month(month)
, _day(day)
{
cout << "Date()" << endl;
}
void Display()
{
cout << _year << "-" << _month << "-" << _day << endl;
cout << _t._hour << endl;
}
private:
int _year;//年
int _month;//月
int _day;//日
Time _t;
};
//友元函数
//友元类
void Print(const Date&d)
{
cout << d._year << "-" << d._month << "-" << d._day << endl;
}
int main()
{
Date d1;
Print(d1);
return 0;
}
在此段代码中,我们定义了两个类:分别为Time类和Date类,并且在Date类中的Display函数试图去访问Time类中的私有成员_hour;显然是不成功的
同样,要想在Date类中访问Time类中的私有成员,必须在Time类中声明Date类是其的友元类,即:
class Time
{
friend class Date;
private:
int _hour;
};
----------------------------------------------------------------------------------------------------------------------------------------------------
下来我们再来看一个问题:输入,输出运算符的重载(还是以上面的代码为例,只不过在main函数中稍作改动,试图输出对象d1中的所有成员变量:_year、_month、_day、_hour)事实证明这样是不可行的
int main()
{
Date d1(2016,12,31);
d1.Display();
cout << d1<<endl;;//d1.operator(cout);
return 0;
}