通过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. jQuery LigerUI V1.2.2

    jQuery LigerUI V1.2.2 (包括API和全部源码) 发布 前言 这次版本主要对树进行了加载性能上面的优化,并解决了部分兼容性的问题,添加了几个功能点. 欢迎使用反馈. 相关链接 AP ...

  2. 【Linux】CentOS 学习笔记之一(安装配制)

    如何打开命令窗口:应用程序>系统工具>终端 如何获取root 权限:在终端下,输入su 再输入密码(密码不显示在屏幕上) 如何将英文版转换成中文: [root@localhost ~]# ...

  3. get post 知多少

    GET与POST简介 POST和GET都属于http请求的方法,所以都包含开始行,头域,头域结束符,消息主体,但是,他们同样存在很多异同,为了更好的区别这两种请求,我们对他们的异同进行具体的分析. 表 ...

  4. mysql数据库 触发器简单实例

    触发器(trigger):监视某种情况,并触发某种操作. 触发器创建语法四要素:1.监视地点(table) 2.监视事件(insert/update/delete) 3.触发时间(after/befo ...

  5. 他们最先开发微信小程序,为何现在又退出了?

    1.当前现状 这几天大家又被微信小程序刷屏了,"得到"退出了小程序,"今日头条"暂停了服务,各种股票交易类的小程序也在证监会的要求下纷纷暂停服务.如果大家还不知 ...

  6. 0-ajax操作json(番外篇)

    [可以先看后边再看此文] get获取json 前端代码 <!DOCTYPE html> <html> <head> <meta charset="u ...

  7. gulp备忘

    // npm install gulp gulp-sourcemaps gulp-name gulp-notify del --save-dev // npm install gulp-ruby-sa ...

  8. [Bzoj]1012最大数maxnumber

    题目如上(线段树???),蒟蒻第二眼想法(其实这道题正解是单队的说,但蒟蒻刚学线段树,于是...就) 献上黑历史: RE是因为蒟蒻数组开太小:第一次开110000:第二次开200000:结果就………… ...

  9. shell-正则表达式

    证则表达式:在计算机科学中,是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串.在很多文本编辑器或其他工具里,正则表达式通常被用来检索和/或替换那些符合某个模式的文本内容.许多程序设计 ...

  10. selenium2使用记录

    安装 pip install selenium web phantomjs下载 :http://phantomjs.org/download.html 浏览器驱动下载:http://www.selen ...