1.什么是友元
在一个类A中,将类B声明为友元类,则类B可以访问类A的私有成员和保护成员。另外,也可以将函数声明为友元函数。

2.什么时候用到友元
若不同的类之间某些共享数据成员,可以使用友元,简化类的设计。

3.友元类
友元类的声明:friend class 类名
示例如下:
对于电视和遥控器来说,都共享频道数据成员和开关操作,这时可以将遥控器声明为电视的友元类,则遥控器可以直接访问电视的数据成员,且一个遥控器可以控制多台电视,这则例子很好的体现了友元的特点。

tv.h

#ifndef TV_H_
#define TV_H_
class Tv
{
public :
friend class Remote;
enum State{off,on}; Tv(int s=off,int mc=):state(s),maxchannel(mc),channel(){} void onoff(){state=(state==on)?off:on;}
void chanup();
void chandown();
void settings() const;
private:
int state;
int maxchannel;
int channel;
};
class Remote{
public:
Remote(){};
void onoff(Tv &t){t.onoff();};
void chanup(Tv &t){t.chanup();};
void chandown(Tv &t){t.chandown();};
void set_chan(Tv &t,int c){t.channel=c;};
};

tv.cpp

#include<iostream>
#include "tv.h"
void Tv::chanup()
{
if(channel<maxchannel){
channel++;
}
else{
channel = ;
}
}
void Tv::chandown()
{
if(channel>){
channel--;
}
else{
channel = maxchannel;
}
}
void Tv::settings() const
{
using std::cout;
using std::endl;
cout<<"Tv is "<<(state==on?"on":"off")<<endl;
if(state==on)
{
cout<<"channel:"<<channel<<endl;
}
}

use_tv.cpp 可使用同一个遥控器控制多台不同的电视

#include<iostream>
#include "tv.h"
int main()
{
using std::cout;
using std::endl;
Tv s42;
cout<<"Initing Tv s42......"<<endl;
s42.settings();
s42.onoff();
s42.chanup();
cout<<"adjusted Tv s42....."<<endl;
s42.settings(); Remote control;
control.set_chan(s42,);
control.volup(s42);
cout<<"settings after using remote......"<<endl;
s42.settings();
getchar();
return ;
}

示例可以看出,若不使用友元,则必须将Tv类的私有部分设置为共有的,或者创建一个大型类来包含电视和遥控器。这种解决方法也无法反应,一个遥控器可以用于多台电视。

4.友元函数
从上例可以看出,Remote类只有set_chan方法使用到了Tv类的私有成员,因此我们可以让Remote::set_chan()成为Tv类的友元函数,而不必让整个类成为友元。

tvfm.h

#ifndef TV_H_
#define TV_H_
class Tv;
class Remote{
public :
enum State{off,on};
private:
int mode;
public:
Remote(){};
void onoff(Tv &t);
void chanup(Tv &t);
void chandown(Tv &t);
void set_chan(Tv &t,int c);
};
class Tv
{
public :
friend void Remote::set_chan(Tv &t,int c);
enum State{off,on}; Tv(int s=off,int mc=):state(s),maxchannel(mc),channel(){} void onoff(){state=(state==on)?off:on;}
void chanup();
void chandown();
void settings() const;
private:
int state;
int maxchannel;
int channel;
}; inline void Remote::onoff(Tv &t){t.onoff();}
inline void Remote::chanup(Tv &t){t.chanup();}
inline void Remote::chandown(Tv &t){t.chandown();}
inline void Remote::set_chan(Tv &t,int c){t.channel=c;}
#endif

5.共同的友元
多个类需要访问同一个函数,则可以在这些类中将这个函数声明为友元函数。例如:有一个计数器函数counter,两个类A和B同时调用这个函数,则可以在类A和B中将函数counter声明为友元函数。

void counter()
{
//....
}
class A
{
friend int counter();
}
class B
{
friend int counter();
}

6.使用友元类时注意:
1) 友元关系不能被继承。
2)友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元。
3) 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元

参考资料:《C++ Primer.Plus》 pp.602-610

C++友元详解的更多相关文章

  1. 14.C++-二阶构造模式、友元(详解)

    首先回顾以前所学的构造函数 类的构造函数用于对象的初始化 构造函数与类同名并且没有返回值 构造函数在定义时被自动调用 由于构造函数没有返回值不能判断执行结果,所以不能保证初始化对象能否成功 比如: c ...

  2. C++中友元详解

    问题的提出 我们已知道类具备封装和信息隐 藏的特性.只有类的成员函数才能访问类的私有成员,程式中的其他函数是无法访问私有成员的.非成员函数能够访问类中的公有成员,但是假如将数据成员都定义 为公有的,这 ...

  3. 《挑战30天C++入门极限》入门教程:实例详解C++友元

        入门教程:实例详解C++友元 在说明什么是友元之前,我们先说明一下为什么需要友元与友元的缺点: 通常对于普通函数来说,要访问类的保护成员是不可能的,如果想这么做那么必须把类的成员都生命成为pu ...

  4. C++ Namespace 详解

    命名空间的定义格式为:(取自C++标准文档) named-namespace-definition: namespace identifier { namespace-body } unnamed-n ...

  5. C++:虚函数的详解

    5.4.2 虚函数详解 1.虚函数的定义 虚函数就是在基类中被关键字virtual说明,并在派生类重新定义的函数.虚函数的作用是允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问 ...

  6. STL priority_queue 常见用法详解

    <算法笔记>学习笔记 priority_queue 常见用法详解 //priority_queue又称优先队列,其底层时用堆来实现的. //在优先队列中,队首元素一定是当前队列中优先级最高 ...

  7. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  8. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

  9. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

随机推荐

  1. ubuntu终止进程的方法

    在ubuntu中,终止一个进程或终止一个正在运行的程序,一般是通过 kill .killall.pkill.xkill 等进行. 先看两个例子: 例子一:结束某个程序,如Firefox  键入命令: ...

  2. IntelliJ IDEA 2017.2.2 的破解 有效期 2116年

      破解三部曲 下载破解文件 JetbrainsCrack-2.6.6-release-enc.jar http://idea.lanyus.com/jar/JetbrainsCrack-2.6.6- ...

  3. linux 系统文件的特殊权限

    文件权限与归属 Linux系统中的一切都是文件,但每个文件的类型不尽相同,并且Linux系统会用不同的符号来加以区分,常见的包括有 -:普通文件,d:目录文件,l:链接文件,b:块设备文件,c:字符设 ...

  4. Android利用温度传感器实现带动画效果的电子温度计

    概述 Android利用温度传感器实现带动画效果的电子温度计. 详细 代码下载:http://www.demodashi.com/demo/10631.html 一.准备工作 需要准备一部带有温度传感 ...

  5. HDUOJ --2544最短路(基础)

    输入包括多组数据.每组数据第一行是两个整数N.M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几 ...

  6. HDUOJ---1996汉诺塔VI

    汉诺塔VI Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Subm ...

  7. 工作总结 public DateTime? CollectionTime 可空类型 Code First

    数据库生成就对应生成  可以为空 的字段

  8. DataTime? 的 GetValueOrDefault() 方法

    DataTime? 转换为 DataTime类型 就可以调用 ToString()  自定义格式 @item.CreateDate.GetValueOrDefault().ToString(" ...

  9. OAF_OAF编译代码至应用详解(案例)

    201-06-01 Created By BaoXinjian

  10. OGG_GoldenGate数据迁移三进程Extract / Dump / Relicat(案例)

    2014-03-04 Created By BaoXinjian