</pre></p><pre name="code" class="cpp">
友元有友元类,友元成员函数,友元函数三种。
1、什么是友元?
官方解释:允许一个类将对其非公有成员的访问权授予指定的类或函数(分别是友元类和C++友元函数)。
自己解释:①友元从“友”字看出这个关系,友元类就是A类是B类的朋友,B类就充分了解A类,所以能访问A类中的成员变量与成员函数(B类若跟A类没关系,这样原本是不可以的,C++为了保护数据,隐藏细节,连返回类中的数据成员都要封装成一个函数,就是怕你直接访问内部数据乱搞,当然直接访问也是可以的,只是一般不这么做!现在B成了A的朋友,所以B能直接访问A)。注意,指定了A是B的朋友,不代表B是A的朋友,也就是说B的情况A是不了解的(生活就是这么现实!!)②友元成员函数,跟友元类相比,可访问范围变小了。我们指定的是A中的某个成员函数是B类的朋友,所以B类就能访问A类的所指定的成员函数(包括私有权限的成员函数)。③友元函数,这个从字面上看没有任何跟类有关的字眼(既不是类,也不是成员),它是类的非成员函数!这个非成员函数其实就是学C语言的时候所定义过的函数,总之就不是类里的。而同样加上了友元的字眼,这个函数就能访问它所指定的类的私有数据。具体怎么指定,请往下看!
2、如何使用友元?
使用关键字 friend,就可以到处找好基友了~~~
示例1、使用友元类
//----mytime.h
#ifndef MYTIME_H_
#define MYTIME_H_
class MyTime
{
<span> </span>//friend void Remote::setTime(MyTime &otime,MyTime &ntime);<span> </span>//使用友元成员函数
<span> </span>
<span> </span>friend class Remote;<span> </span>//使用友元类
<span> </span>private:
<span> </span>int hours;
<span> </span>int minutes;
<span> </span>int seconds;
<span> </span>public:
<span> </span>MyTime (int h=0,int m=0,int s=0){hours=h;minutes=m;seconds=s;};
<span> </span>MyTime (MyTime &time) {hours=time.hours;minutes=time.minutes;seconds=time.seconds;};
<span> </span>~MyTime(){};
<span> </span>
//<span> </span>bool setTime(int h,int m,int s){hours=h;minutes=m;seconds=s;};
<span> </span>void showtime(){std::cout<<"hours : "<<hours<<"minutes : "<<minutes << std::endl;};
<span> </span>
<span> </span>MyTime operator *(const int &t) const;
<span> </span>friend MyTime operator *(int k,const MyTime &t);<span> </span>//使用友元函数<span> </span>
};
class Remote<span> </span>//遥控类,可以设置时间
{
<span> </span>public:<span> </span>//构造函数一定要在前面加public 否则默认都是private
<span> </span>Remote (int m){i=m;};<span> </span>
<span> </span>~Remote(){};
<span> </span>void setTime(MyTime &otime,MyTime &ntime){ntime.hours=otime.hours;ntime.minutes=otime.minutes;ntime.seconds=otime.seconds;};
<span> </span>private:
<span> </span>int i;
};
MyTime MyTime::operator *(const int &t) const
{
<span> </span>MyTime result;
<span> </span>long totalminutes = hours*t*60+minutes*t;
<span> </span>result.hours = totalminutes/60;
<span> </span>result.minutes = totalminutes%60;
<span> </span>return result;
}
MyTime operator *(int k,const MyTime &t)
{
<span> </span>return t*k;
}
#endif
</pre><p></p><div>示例2、使用友元成员函数:</div><p></p><p></p><pre name="code" class="cpp"><pre name="code" class="cpp">
//----mytime.h
#ifndef MYTIME_H_
#define MYTIME_H_
class MyTime;<span style="white-space:pre"> </span>//前置声明
class Remote<span> </span>//遥控类,可以设置时间
{
<span> </span>public:<span> </span>//构造函数一定要在前面加public 否则默认都是private
<span> </span>Remote (int m){i=m;};<span> </span>
<span> </span>~Remote(){};
<span> </span>void setTime(MyTime &otime,MyTime &ntime);
<span> </span>private:
<span> </span>int i;
};
class MyTime
{
<span> </span>friend void Remote::setTime(MyTime &otime,MyTime &ntime);<span> </span>//使用友元成员函数
<span> </span>
<span> </span>//friend class Remote;
<span> </span>private:
<span> </span>int hours;
<span> </span>int minutes;
<span> </span>int seconds;
<span> </span>public:
<span> </span>MyTime (int h=0,int m=0,int s=0){hours=h;minutes=m;seconds=s;};
<span> </span>MyTime (MyTime &time) {hours=time.hours;minutes=time.minutes;seconds=time.seconds;};
<span> </span>~MyTime(){};
<span> </span>
//<span> </span>bool setTime(int h,int m,int s){hours=h;minutes=m;seconds=s;};
<span> </span>void showtime(){std::cout<<"hours : "<<hours<<"minutes : "<<minutes << std::endl;};
<span> </span>
<span> </span>MyTime operator *(const int &t) const;
<span> </span>friend MyTime operator *(int k,const MyTime &t);<span> </span>//使用友元函数<span> </span>//const型成员函数,const型对象只能访问const型成员函数
};
void Remote::setTime(MyTime &otime,MyTime &ntime)
{
<span> </span>ntime.hours=otime.hours;
<span> </span>ntime.minutes=otime.minutes;
<span> </span>ntime.seconds=otime.seconds;
}
MyTime MyTime::operator *(const int &t) const
{
<span> </span>MyTime result;
<span> </span>long totalminutes = hours*t*60+minutes*t;
<span> </span>result.hours = totalminutes/60;
<span> </span>result.minutes = totalminutes%60;
<span> </span>return result;
}
MyTime operator *(int k,const MyTime &t)
{
<span> </span>return t*k;
}
#endif
成员函数的已经包括在这里面了
<span style="font-family: Arial, Helvetica, sans-serif;"> </span><span style="font-family: Arial, Helvetica, sans-serif;">friend MyTime operator *(int k,const MyTime &t);</span><span style="font-family: Arial, Helvetica, sans-serif;"> </span><span style="font-family: Arial, Helvetica, sans-serif;">//使用友元函数</span><span style="font-family: Arial, Helvetica, sans-serif;"> </span>
就是这句
测试代码:
//--------mytime.cpp
#include <iostream>
#include "mytime.h"
int main()
{
MyTime time(1,1,2);
MyTime time2 =2*time;
time2.showtime();
Remote remote(1);
remote.setTime(time,time2);
time.showtime();
return 0;
}
输出:
3、实际应用
友元运算符重载:
class X{ //运算符重载 ——友元函数
private:
int x;
public:
X(int m){x=m;};
X(X &y){x=y.get();};
~X(){};
int get(){return x;};
void set(int y){x=y;};
friend std::ostream & operator << (X &x1,std::ostream &os){os<<"friend 1os:"<<x1.x;return os; };<span style="white-space:pre"> </span>//第一个友元函数<span style="white-space:pre"> </span>//友元函数,不是类的成员函数
friend std::ostream & operator << (std::ostream &os,X &x1){os<<"friend 2os:"<<x1.x;return os; }
};
int main()
{ X x(1);
//x.operator<<(y,std::cout); //重载<<的一些尝试
<span style="white-space:pre"> </span>std::cout<<x;<span style="white-space:pre"> </span>//调用第二个
<span style="white-space:pre"> </span>x<<std::cout;<span style="white-space:pre"> </span>//调用第一个
return 0;
}
测试输出:
<pre name="code" class="cpp">
可以看出
std::cout<<x;
调用的是
friend std::ostream & operator << (std::ostream &os,X &x1){os<<"friend 2os:"<<x1.x;return os; }
至于为什么是这样,我也没找到答案,但是直观看就应该是这样,估计是编译器的事了!
就像为什么重载 << 要用 operator << 这样做为约定一样!
<pre name="code" class="cpp">