C++中的友元小结
我们知道,在一个类总可以有公有的(public)成员和私有的(private)成员。在类外可以访问公用成员,只有本类中的函数可以访问本类的私有成员。
现在,我们学习一种新的情况——友元。
在C++中,这种关系以关键字friend声明。友元可以访问与其有好友关系的类中的私有成员。包括友元函数和友元类。
友元函数
如果在本类意外的其他地方定义了一个函数(这个函数可以是不属于任何类的非成员函数,也可以是其他类的成员函数),在类体中用friend对该函数进行声明,此函数就称为本类的友元函数。一个类的友元函数可以访问这个类中的私有成员。
将普通函数声明为友元函数
========通过程序1.1来了解友元函数的性质和作用============
#include<iostream>
using namespace std;
class Time
{
public:
Time(int,int,int);//声明构造函数
friend void display(Time &);//声明display函数为Time类的友元
private:
int hour;
int minute;
int second;
};
Time::Time(int h,int m,int s)//定义构造函数,完成初始化工作
{
hour=h;
minute=m;
second=s;
}
void display(Time &t)//友元函数,形参t是Time类对象的引用
{
cout<<t.hour<<"/"<<t.minute<<"/"<<t.second<<endl;
}
int main()
{
Time t1(10,13,56);
display(t1);
return 0;
}
运行结果:
分析:
display函数是一个在类外定义的非成员函数,它不属于任何一个类。如果在Time类的定义体中未声明display函数为friend函数,它是不能引用Time中的私有成员hour,minute和second的。
否则就会提示hour,minute和second是private函数,没有权限访问的错误。
由于我们在定义Time的时候,声明了display函数是其友元函数,Time所定义的所有的对象都会把dispaly函数作为自己的“朋友”,允许display函数引用其私有成员hour,minute和second.
但是要注意,我们在使用dispaly函数的时候,形参是对象的引用,实参是对象。
我们在友元函数中引用这些私有数据成员时,必须加上对象名,而不能写成:
cout<<hour<<"/"<<minute<<"/"<<second<<endl;
因为display函数不是Time类的成员函数,不能默认引用Time类的数据成员,必须指定要访问的对象。
友元成员函数
friend函数不仅可以是一般函数(非成员函数),而且可以是另一个类中的成员函数。
在举这个例子之前,我们需要先了解“类的提前引用声明”
在C++中允许对类做“提前引用”的声明,即在正式声明一个类之前,先声明一个类名,表示此类将在稍后声明。
函数的提前引用声明,只包含类名,不包含类体。
class Date;//对Date类做提前声明
类的提前声明的使用范围是有限的,在对一个类作了提前引用声明后,可以用该类的名字去定义指向该类型对象的指针变量或对象的引用。
这是因为指针变量和引用本身的大小是固定的,与它所指定的类对象的大小无关。
然后,只有在正式声明一个类之后才能用它去定义类对象。因为在正式声明类之前就去定义对象的话,编译系统并不知道对象的结构,也就没有办法给对象分配空间,所以不能定义对象。
================示例代码1.2==============================
#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 void Time::display(Date &);//声明Time类中的display函数为本类的友元函数
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;
}
运行结果:
分析:
为了在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类为其友元类:
friend class B;
声明友元类的一般形式:
friend class B;
例如,我们可以将程序1.2中的Time类声明为Date类的友元类,这样Time中的所有函数都可以访问Date类中的数据成员。
修改代码如下
===============示例代码2.1============================
#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的友元类。
在实际工作中,除非有必须,一般并不把整个类声明为友元类,而只是将确实有需要的成员函数声明为友元函数,这样更加安全一些。
C++中的友元小结的更多相关文章
- MVC图片上传详解 IIS (安装SSL证书后) 实现 HTTP 自动跳转到 HTTPS C#中Enum用法小结 表达式目录树 “村长”教你测试用例 引用provinces.js的三级联动
MVC图片上传详解 MVC图片上传--控制器方法 新建一个控制器命名为File,定义一个Img方法 [HttpPost]public ActionResult Img(HttpPostedFile ...
- C++中的友元函数和友元类
C++中的友元函数主要应用于以下场景: 友元函数 第一种场景 代码中有一个全局函数,该函数想要去访问某个类的成员变量(该类的成员变量是private的,且该类并未提供任何获取获取私有成员变量的publ ...
- 180531-Spring中JavaConfig知识小结
原文链接:Spring中JavaConfig知识小结/ Sring中JavaConfig使用姿势 去掉xml的配置方式,改成用Java来配置,最常见的就是将xml中的 bean定义, scanner包 ...
- [转] SpringBoot RESTful 应用中的异常处理小结
[From] https://segmentfault.com/a/1190000006749441 SpringBoot RESTful 应用中的异常处理小结 永顺 2016年08月29日发布 赞 ...
- hiredis中异步的实现小结
hiredis中异步的实现小结 原文: http://blog.csdn.net/l1902090/article/details/3858... 时间: 2014-08-15 前言 一般情况下我们使 ...
- C#不用union,而是有更好的方式实现 .net自定义错误页面实现 .net自定义错误页面实现升级篇 .net捕捉全局未处理异常的3种方式 一款很不错的FLASH时种插件 关于c#中委托使用小结 WEB网站常见受攻击方式及解决办法 判断URL是否存在 提升高并发量服务器性能解决思路
C#不用union,而是有更好的方式实现 用过C/C++的人都知道有个union,特别好用,似乎char数组到short,int,float等的转换无所不能,也确实是能,并且用起来十分方便.那C# ...
- C#中实现C++中的友元类
最近做一个小程序,一个类A(负责显示处理)需要大量调用类B(负责数据处理)的函数,我最先想到的C++中的友元概念,因为类B中的这些函数并不希望public,它只是允许类A调用监测. 网上搜索了一下,没 ...
- 04 c++中的友元
c++中的类具有封装性,类中的私有数据只有该类的成员函数可以访问,程序中访问类中的私有成员,必须通过对象来调用成员函数,但是频繁的调用会使运行效率降低. 为了解决上述问题,c++中加入友元机制,友元可 ...
- 关于C++中的友元函数的总结
1.友元函数的简单介绍 1.1为什么要使用友元函数 在实现类之间数据共享时,减少系统开销,提高效率.如果类A中的函数要访问类B中的成员(例如:智能指针类的实现),那么类A中该函数要是类B的友元函数.具 ...
随机推荐
- 左侧图片 右侧块的实现方法---解决3像素bug的一种解决方案,不用浮动用绝对定位和margin-left
google的实现方式是: <div class="mw"> <a href="/" id="mlogo"> &l ...
- C++写和读文件
1.写: /*C++写文件和读文件*/ #include <stdio.h> #include <stdlib.h> int main() { FILE * fp; fp = ...
- node.js+express+jade系列一:session的使用
此出只介绍内存session的配置好使用 1:打开app.js文件,添加下面红色内容,一定要注意位置在router前面 app.use(express.methodOverride()); sessi ...
- [深入学习C#]C#实现多线程的方式:使用Parallel类
简介 在C#中实现多线程的另一个方式是使用Parallel类. 在.NET4中 ,另一个新增的抽象线程是Parallel类 .这个类定义了并行的for和foreach的 静态方法.在为 for和 f ...
- django学习笔记(四)表单
1.若用户刷新一个包含POST表单的页面,那么请求将会重新发送造成重复. 这通常会造成非期望的结果,比如说重复的数据库记录.如果用户在POST表单之后被重定向至另外的页面,就不会造成重复的请求了.我们 ...
- docker 安装过程
- ACM学习历程—HDU 3092 Least common multiple(数论 && 动态规划 && 大数)
Description Partychen like to do mathematical problems. One day, when he was doing on a least common ...
- iOS奇怪的问题,键盘偏移异常
现象描述: 点击UITextView,键盘会弹出.然后点击添加图片,弹出了ActionSheet,键盘自动收缩.接着关闭ActionSheet,发现键盘又弹出了,接着点击Done,想要隐藏键盘,却发现 ...
- 使用Visual Studio进行单元测试-Part2
写在开头:Coding ain't done until all the tests run. No unit test no BB. 另外有童鞋在上一篇博文留言说找不到Add Fake Assemb ...
- Poj 1973 Software Company(二分+并行DP)
题意:软件公司接了两个项目,来自同一个合同,要一起交付.该公司有n个程序猿来做这两个项目A和B,每个项目都被分为m个子项目,给定每个程序猿做一个A中的子项目需要的时间Xi秒,和做B中的子项目所需时间Y ...