通过friend关键字,我们可以将不属于当前类的一个函数在当前类中加以声明,该函数便可以成为当前类的友元函数。

例1:

#include<iostream>
using namespace std;

class book
{
public:
book(){}
book(char* a, double p);
friend void display(book &b);
private:
double price;
char * title;
};

book::book(char* a, double p)
{
title = a;
price = p;
}

void display(book &b)
{
cout<<"The price of "<<b.title<<" is $"<<b.price<<endl;
}

int main()
{
book Alice("Alice in Wonderland",29.9);
display(Alice);
book Harry("Harry potter", 49.9);
display(Harry);
return 0;
}

在本例中,display是一个顶层函数,在book类中,我们借助friend关键字将其声明为友元函数,结果,在display函数体内,我们就能访问private属性的title和price成员变量。这就是友元函数的作用。友元函数可以访问这个类中的私有成员。如果这个display函数不是book类的友元函数,则在函数体中还必须调用public属性的成员函数。在此例中需要注意的是友元函数的形参是类对象的引用,同时在访问私有成员变量时必须要加上对象名。

除了顶层函数可以被定义为友元函数之外,其它类的成员函数同样可以声明为本类的友元函数,如例2所示。

例2:

#include<iostream>
using namespace std;

class time;

class date
{
public:
date(int y,int m,int d);
void display(time &t);
private:
int year;
int month;
int day;
};

class time
{
public:
time(int s,int m,int h);
friend void date::display(time & t);
private:
int second;
int minute;
int hour;
};

time::time(int s,int m,int h)
{
second = s;
minute = m;
hour = h;
}

date::date(int y,int m,int d)
{
year = y;
month = m;
day = d;
}

void date::display(time &t)
{
cout<<"The time is:"<<endl;
cout<<year<<"/"<<month<<"/"<<day<<" ";
cout<<t.hour<<":"<<t.minute<<":"<<t.second<<endl;
}

int main()
{
date d(2015,1,16);
time t(20,2,30);
d.display(t);
return 0;
}

在本例中定义了两个类time和date,在time类中有hour、minute和second三个成员变量,分别代表时分秒,在date类中有year、month和day三个成员变量,分别代表年月日信息。为了能够共同显示年月日时分秒信息,我们在date类中声明了一个display函数,并且将该函数设置为time类的友元函数,如此一来,该函数既能访问date类中的私有成员变量,同时又能访问time类中的私有成员变量,打印时间自然不在话下。

这个例子有几点需要注意一下。首先要注意的是date类的定义必须出现在time类之前,这么做是为了使得display函数的函数声明能够在声明为友元函数之前。其次,display函数的形参为time类对象的引用,而time类又必须定义在date类之后,如此一来只能先将time类声明在date类之前了,如class time;这一语句即是为了声明time类。第三点就是需要将display函数的定义放到time类定义的后面,这是因为display函数中必须用到time类中的私有成员变量,因此在使用之前,这些成员变量必须先声明出来。这三个需要注意顺序的地方需要大家特别关注一下,顺序一定不能搞错了,否则都是无法通过编译的。

无论是类的成员函数还是顶层函数,它们都是可以被多个类声明为友元函数的,如此一来就可以访问多个类中的私有成员变量,但是为了保证数据的安全,友元函数的使用宁缺毋滥。

除了可以利用friend关键字声明友元函数之外,我们还可以将其它类声明为当前类的友元类。友元类声明的语法非常简单,即为“friend 类名;”。

例3:

#include<iostream>
using namespace std;

class time;
class date
{
public:
date(int y,int m,int d);
void display(time &t);
private:
int year;
int month;
int day;
};

class time
{
public:
friend date;
time(int s,int m,int h);
private:
int second;
int minute;
int hour;
};

time::time(int s,int m,int h)
{
second = s;
minute = m;
hour = h;
}

date::date(int y,int m,int d)
{
year = y;
month = m;
day = d;
}

void date::display(time &t)
{
cout<<"The time is:"<<endl;
cout<<year<<"/"<<month<<"/"<<day<<" ";
cout<<t.hour<<":"<<t.minute<<":"<<t.second<<endl;
}

int main()
{
date d(2015,1,16);
time t(20,2,30);
d.display(t);
return 0;
}

在本例中,我们将date类声明为time类的友元类,则此时date类中的所有成员函数都将转化为time类的友元函数,可以访问time类中的所有成员。毫无疑问,date类中display函数同样也会成为time类的友元,因此利用time类对象t的引用便可以访问time类的私有成员变量了。此函数中类的声明及定义、函数的声明及定义位置同样需要注意。

关于友元还有几点需要注意:

    • 例3中我们将date类声明为time类的友元类,此时date类中的所有函数都将成为time类的友元函数。
    • date类是time类的友元类,但是time类不是date类的友元类。友元关系是单向的,而不是双向的。如果需要将time类也声明名为date类的友元类,则需要另外在date类中声明。
    • 友元关系不能传递,假设A类是B类的友元类,B类是C类的友元类,这两点并不能得出A类是C类的友元类。
    • 友元类会破坏数据的安全性,使用时宁缺毋滥。如果不是能够极大提高程序运行效率的情况,最好不要用友元。

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

  1. C++的友元类和友元函数实例

    #include <math.h> #include<iostream> using namespace std; class Point { public: Point(do ...

  2. C++学习笔记 构造&析构 友元 new&delete

    构造&析构函数 构造函数 定义:与类同名,可以有参可以无参,主要功能用于在类的对象创建时定义初始化的状态,无返回值,也不能用void修饰,构造函数不能被直接调用,必须通过new运算符在创建对象 ...

  3. c++友元函数

    c++友元函数分两类: 一://友员全居函数 /*#include <iostream>using namespace std;class aaa{    friend void prin ...

  4. 重载运算符:类成员函数or友元函数

    类成员函数: bool operator ==(const point &a)const { return x==a.x; } 友元函数: friend bool operator ==(co ...

  5. C++之友元

    友元提供了不同类的成员函数之间.类的成员函数与一般函数之间进行数据共享的机制.通过友元,一个不同函数或另一个类中的成员函数可以访问类中的私有成员和保护成员.C++中的友元为封装隐藏这堵不透明的墙开了一 ...

  6. 不可或缺 Windows Native (20) - C++: 友元函数, 友元类

    [源码下载] 不可或缺 Windows Native (20) - C++: 友元函数, 友元类 作者:webabcd 介绍不可或缺 Windows Native 之 C++ 友元函数 友元类 示例演 ...

  7. InternalsVisibleToAttribute——把internal成员暴露给指定的友元程序集

    友元程序集简介 我们知道一个类中被定义为internal的成员(包括类型.方法.属性.变量.事件)是只能在同一个程序集中被访问到的(当然了,我这里说的是正常的方式,不包括通过反射来访问).这个规则在. ...

  8. c++ 操作符重载和友元

    操作符重载(operator overloading)是C++中的一种多态,C++允许用户自定义函数名称相同但参数列表不同的函数,这被称为函数重载或函数多态.操作符重载函数的格式一般为: operat ...

  9. [Reprint]C++友元函数与拷贝构造函数详解

    这篇文章主要介绍了C++友元函数与拷贝构造函数,需要的朋友可以参考下   一.友元函数 1.友元函数概述: (1)友元函数是定义在一个类外的普通函数.友元函数和普通函数的定义一样;在类内必须将该普通函 ...

  10. C++——友元、异常和其他

    一.友元 类并非只能拥有友元函数,也可以将类作为友元.在这种情况下,友元类的所有方法都可以访问原始类的私有成员和保护成员.另外,也可以做更严格的限制,只将特定的成员函数指定为另一个类的友元.哪些函数. ...

随机推荐

  1. CKEditor4.x部署和配置

    CKEditor4.x && JSP 官网下载CKEditor,可选Basic, Standard, Full 解压放置其WebRoot下 JSP中引入以下文件: <script ...

  2. IOS中KVO模式的解析与应用

    IOS中KVO模式的解析与应用 最近老翁在项目中多处用到了KVO,深感这种模式的好处.现总结如下: 一.概述 KVO,即:Key-Value Observing,它提供一种机制,当指定的对象的属性被修 ...

  3. Archives for the category: Fisheye/Crucible

    Archives for the category: Fisheye/Crucible Introducing FishEye and Crucible 3.0 – Search, visualize ...

  4. jquery ready方法实现原理 内部原理

    jquery ready方法实现原理 内部原理 今天闲来无事研究研究jquery.ready()的内部实现,看JQ的源码一头雾水,由于自己很菜了,于是翻了翻牛人的播客,讲述详细,收获颇多. 先普及一下 ...

  5. STL迭代器与部分算法学习笔记

    迭代器是类似指针的对象,分为5种,输入,输出,前向,双向和随机访问 输入迭代器(InputIterator) 输入迭代器并不是指某种类型,而是指一系列类型 举例 template<class I ...

  6. 百度地图在某架构下找不到符号.a文件的问题

    1.现象: 就是说找不到符号给i386的架构(就是模拟器).或者找不到符号给arm架构(真机). ld: warning: ignoring file /Users/pufang/xcode/demo ...

  7. 交流希望希望能得到一些大神的指点,加QQ群:249627436 java技术交流群

    查了好多资料,发现还是不全,干脆自己整理吧,至少保证在我的做法正确的,以免误导读者,也是给自己做个记录吧! 本人学习java,1年多,对一些基本技巧已掌握.为了使自己能力晋升建了一个QQ群:java交 ...

  8. vsftpd配置seccomp_sandbox=NO

    在ubuntu14.04 配置vsftp时如果不加上seccomp_sandbox=NO这一句会出现莫名的530错误

  9. windows下使用命令查看端口占用情况

    使用下面的命令查看端口占用情况: 比如查看3000端口的占用情况 netstat -ano|findstr 3000 运行后,结果如下: 可以看到进程号为9692的占用了该端口,使用下面的命令查看是哪 ...

  10. ETL的经验总结

    ETL的考虑        做数据仓库系统,ETL是关键的一环.说大了,ETL是数据整合解决方案,说小了,就是倒数据的工具.回忆一下工作这么些年来,处理数据迁移.转换的工作倒还真的不少.但是那些工作基 ...