C++学习笔记之——友元

来源:互联网 发布:java 适配器设计模式 编辑:程序博客网 时间:2024/06/05 18:39

我们知道类具有封装和信息隐藏的特性。只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问私有成员的。非成员函数可以访问类中的公有成员。有时候我们又需要其他非成员函数访问类的成员,并且对于该成员我们不希望它是公有的(有可能这是危险的操作,我们希望它只针对某些操作可见),如果将它定义为公有的明显不符合我们的期望并且破坏了隐藏的特性。另外,应该看到在某些情况下,特别是在对某些成员函数多次调用时,由于参数传递,类型检查和安全性检查等都需要时间开销,而影响程序的运行效率。

为了解决上述问题,提出一种使用友元的方案。友元是一种定义在类外部的普通函数或类,但它需要在类体内进行说明,为了与该类的成员函数加以区别,在说明时前面加以关键字friend。友元不是成员函数,但是它可以访问类中的私有成员。友元的作用在于提高程序的运行效率,但是,它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。不过,类的访问权限确实在某些应用场合显得有些呆板,从而容忍了友元这一特别语法现象。

友元的作用:友元提供了不同类的成员函数之间、类的成员函数与一般函数之间进行数据共享的机制。通过友元,一个不同函数或另一个类中的成员函数可以访问类中的私有成员和保护成员。c++中的友元为封装隐藏这堵不透明的墙开了一个小孔,外界可以通过这个小孔窥视内部的秘密。


友元的特点:友元的正确使用能提高程序的运行效率,但同时也破坏了类的封装性和数据的隐藏性,导致程序可维护性变差。


友元的分类:类可以把一个普通函数定义成友元,也可以把其他类定义成友元,还可以把类的成员函数定义成友元。


下面,我们会具体了解友元的使用场景。我们以手机中常见的功能——便签做为例子来说明,在这里只是为了说明使用友元的情况,可能和实际有出路(我们并没有给出具体的实现,只是借这个例子说明情况)。

假设,我们的便签的管理上有一个专门的类CNoteMng,它负责管理所有的记录。

#ifndef __NOTE_MNG_H__#define __NOTE_MNG_H__#include <vector>#include <iostream>#include "Note.h"class CNoteMng{friend void DisplayNoteSum(void);public:explicit CNoteMng();~CNoteMng();//TODO:这里面有其他的一些实现private://TODO:这里面有其他的一些实现void ClearAllNote();std::vector<CNote> m_vecNote;};void DisplayNoteSum(void){std::cout << "DisplayNoteSum : " << m_vecNote.size() << std::endl;}#endif//#ifndef __NOTE_MNG_H__

我们能从类似资源管理器的软件中看的便签的统计。为此,我们的例子CNoteMng将统计便签数量的普通函数定义为友元。这就是类可以把一个普通函数定义成友元。

具体的一条记录的实现可能类似下面的实现:

#ifndef __NOTE_H__#define __NOTE_H__#include <string>class CNode{friend void CNoteMng::ClearAllNote();public:explicit CNode();~CNode();//TODO:这里还有其他的实现。private:void clear();//TODO:这里还有其他的实现std::string strTitle;//标题std::string strCreatTime;//创建日期std::string strContent;//内容};#endif//#ifndef __NOTE_H__
我们希望CNoteMng能实现一个功能,该功能能清除掉所有的便签记录,为此我们在CNote中增加一个接口,可能实现为清除磁盘上的记录。并且我们希望这个接口被保护起来,为此我们声明为私有的。但我们为了在CNoteMng中的ClearAllNote()能使用这个私有接口,为此我们类成员函数定义为友元。这就是类可以把其他类的成员函数定义成友元

如果我们还需要增加一项功能,该功能是,根据标题,创建日期,内容进行检索,并显示检索到的记录(我们可能需要遍历所有的记录,并进行比较,这样就需要操作到具体类CNode的私有成员)。为此,我们就需要在类CNode中定义CNoteMng为友元类。这就是类可以把其他类定义为友元类

#ifndef __NOTE_MNG_H__#define __NOTE_MNG_H__#include <vector>#include <iostream>#include <string>#include "Note.h"class CNoteMng{friend void DisplayNoteSum(void);public:explicit CNoteMng();~CNoteMng();//TODO:这里面有其他的一些实现void SearchTitleAndPlay(std::string &strTitle);private://TODO:这里面有其他的一些实现void ClearAllNote();std::vector<CNote> m_vecNote;};void DisplayNoteSum(void){std::cout << "DisplayNoteSum : " << m_vecNote.size() << std::endl;}#endif//#ifndef __NOTE_MNG_H__
#ifndef __NOTE_H__#define __NOTE_H__#include <string>class CNode{friend CNoteMng;public:explicit CNode();~CNode();//TODO:这里还有其他的实现。private:void clear();//TODO:这里还有其他的实现std::string strTitle;//标题std::string strCreatTime;//创建日期std::string strContent;//内容};#endif//#ifndef __NOTE_H__


0 0
原创粉丝点击