← 学习库 C++程序设计教程 本册目录

第17章 友元

原书第 247 页

第17章 和谐友好、随意使用的成员——友元

家里的好东西、贵重物品一般是不轻易借给别人使用的,如电视机、计算机等,但好朋友例外。C++也是一样,在类里声明为保护或私有的成员都是不外借的,外部不能访问,也就是外部不能对这些保护、私有成员(包括数据成员和函数成员)进行赋值、修改、显示等所有操作。如果外部需要频繁地对这些保护、私有成员进行操作,而且还要兼顾保留一些其他性能时,就可以考虑设置友元函数(就像好朋友一样),这些友元函数就可以与保护或私有成员和谐友好地相处,即可以随意使用了。

怎样才能成为 C++ 的好朋友?又怎样体现和谐友好呢?和 C++ 做朋友吧,这样就能分享到其中的快乐了。

17.1 运用友元计算全班所有科目的总平均分的例题详解

【例 17-1】计算全班所有科目的总平均分,要求使用运算符重载、友元函数编程。

  1. 用心分析人想通,机随人行写提纲

大致与例 14-1 的设计思路相同,只不过把 display 成员函数声明为友元函数了。

  1. 对号入座写文章,头脑运行改文章
#include<iostream>
using namespace std;

class Ave
{
    protected:
        double ave;
        int s;
    public:
        Ave(double ave1,int s1);
        Ave operator+(Ave a);
        Ave avevalue(Ave b);
        friend void display(Ave c);//把 display 成员函数声明为友元函数
    };

    Ave::Ave(double ave1,int s1)
    {
        ave=avel;
        s=s1;
    }
}
原书第 248 页

Ave Ave::operator+(Ave a)

{
    ave=ave+a.ave;
    Ave result(ave,s);
    return result;
}

Ave Ave ::avevalue(Ave b)

{
    ave=b.ave/b.s;
    Ave result(ave,s);
    return result;
}

void display(Ave c)//定义友元函数,其格式参考表17-1及17.3节
{
    cout<<c.ave<<endl;
}

void main()
{
    Ave e1(80.6,2);
    Ave e2(87.9,2.0);
    Ave e3(0,2.0);
    e3=e1+e2;
    e3=e3.avevalue(e3);
    display(e3);
}
  1. C++帮助且裁判,人定胜机凯歌扬上机实验记录如表17-1所示。
表 17-1 上机实验记录表
出错现象出错原因解决办法
'Ace' : is not a class or namespace name因为在 display 函数前加了 Ace去掉 Ace,改为 Ave,此错纠正
'display' : is not a member of 'Ave'display 不是 Ave 的成员,那么它作为友元函数,就不属于 Ave 类了去掉 display 前的 Ave,此错纠正

运行结果:

84.25

结果正确。

原书第 249 页

17.2 勤奋实践,总结评分

17.2.1 习题
  1. 在商场购物时,只要在计算机上输入商品的名称,计算机就能输出该商品的现有数量和单价以供选择,请用类编写一个程序实现该操作。
  1. 有几个不同类型的用户共享一台打印机,使用时必须先调用一个检测程序,该检测程序用于检测打印机是否有人在使用,请用一个友元函数编写这个检测程序。

3.某商场通过运行商品自动销售情况统计软件来预计进货量,该软件能显示商品名称、销售时间、商品的销售量和商品的库存量,试编写程序实现。

  1. 把加法运算符重载为友元函数,该函数做复数相加的工作。
  1. 将第7章习题的第5题用友元函数编写程序。
  1. 将第7章习题的第6题用友元函数编写程序。
  1. 将第7章习题的第4题用友元函数编写程序。

8.试用友元函数编写一道程序,可以查询某校在校学生人数、教职工人数、学校面积、所设专业等学校的公开情况。

  1. 将第8章习题的第8题用友元函数编写程序。
  1. 将第7章习题的第10题用友元函数编写程序。
17.2.2 思考题

1.输入以2009年1月1日为基准的天数,编写一个程序计算出所输入天数对应的2009年的具体日期。

2.设想生活、工作等场合中的一些浏览、查询或打印公共数据的操作,用友元函数编写程序来实现。

17.2.3 总结评分,继续提高

浏览、体验了例题、习题和思考题之后,说说自己的体会和收获,并认真总结,按表 17-2 给自己评判一下可以得多少分。

表17-2 总结评分表
成绩ABCD不足的原因改进的方法备注
C++知识完全理解和会用基本理解和会用肤浅理解和会用基本不理解和不会用
程序原创(独立编程)的比例(%)≥9080~8960~79<60

不论得分多少,大家都要总结经验,扬长避短,勤奋努力,不断提高。

最后浏览一下本章的第4节,可以先考考自己,然后再浏览,以便使重点知识掌握得更牢固。

原书第 250 页

17.3 友元知识

怎样才能与 C++ 成为好朋友,好朋友之间又如何相处呢?且往下观赏体验。

17.3.1 在什么情况下用到友元

当需要频繁使用类中的保护或私有成员,想提高程序的运行效率,使得编程更方便,但又对这些成员的某些操作还保留其保护或私有的权限(即对类的整体操作性和程序的封装性不会有完全性的破坏)时,可以考虑用友元函数。

例如,在商场货物的类中,把商品的名称、型号、规格、数量、单价等设置为私有或保护成员,顾客查询商品的操作用友元函数,而将对商品的其他操作设计为函数成员,这样就基本上符合上述应用友元的原则了。

注意:不要滥用友元函数。有的人在程序编写或调试中碰到困难时,就乱用友元函数,虽然可能程序能运行了,但带来的副作用却可能让你得不偿失。

17.3.2 关于友元

首先了解一下友元,再看看友元怎样与 C++ 成为好朋友。

1. 什么是友元

友元是一种函数,它能访问类中的全部成员。

但友元并不是类的成员函数(即使放在类中声明),它是类的朋友,是友元函数。这很容易理解,就像一个人不能既是某个家庭中的成员,又是这个家庭的朋友。

但友元函数又不是普通函数,因为普通函数不能访问类中的所有成员。

2. 友元函数的声明及定义

(1) 友元函数的声明

反元函数的声明与成员函数的声明方法基本一样,只是在原有的成员函数前加上关键字friend,且友元函数只能放在类的内部声明,在类中的任何区域声明均可(如保护、私有、公有区域均可)。

【例 17-2】请声明一个显示类 Ave 的数据的友元函数。

friend void display(Ave c);//把显示(display)成员函数声明为友元函数

(2) 友元函数的定义

反元函数的定义与普通函数的定义方法一样,二者均放在类的外部定义。但反元函数的定义一般放在声明它的类成员函数的外部定义区。

【例 17-3】请定义一个显示类 Ave 的数据的友元函数。

void display(Ave c)//定义显示类 Ave 的数据的友元函数,并定义了类的对象 c 作为形参
{
    cout<<c.ave<<endl;//显示对象 c 的数据成员 ave 的值
}

注意:友元函数的定义的第一行就不要写 friend、类名及类的作用域区分符 “::” 了,用普通函数的格式书写即可。

原书第 251 页

3. 友元函数的使用方法

当声明和定义了友元函数之后,就可以使用友元函数了。

其使用方法与普通函数的使用方法一样,必须加上对象名来引用类中的成员。

17.3.3 如何运用友元

要在满足要求、又不违反友元函数使用原则的前提下,设计好在何处使用友元函数。使用时按照友元函数的书写格式声明和定义,使用方法与以前所讲的普通函数的使用方法一样,因为友元还是函数,只不过可以友好地使用类中的所有成员罢了。切记:不要滥用友元函数,程序中不一定非要有友元函数。

要根据 C++ 的规则用友元函数与 C++ 交朋友,还要成为好朋友。编写、调试和运行程序时都要看看友元函数有没有触犯 C++ 交朋友的规则,有没有伤害程序的整体性能等。如果有则加以修改,直到它们和谐友好地成为好朋友。

17.4 友元的亮点

1. 在什么情况下用友元的亮点

当需要频繁使用类中的保护或私有成员,想提高程序的运行效率,使得编程更方便,但又对这些成员的某些操作还保留其保护或私有的权限(即对类的整体操作性和程序的封装性不会有完全性的破坏)时,可以考虑用友元函数。

2. 友元具体知识的亮点

1)友元是一种函数,它能访问类中的全部成员。

2)友元不是类的成员函数。

3)友元函数也不是普通函数。

4)友元函数的声明与成员函数的声明方法基本一样,只是在原有的成员函数前加上关键字 friend,且友元函数只能放在类的内部声明。友元函数的定义与普通函数的定义方法一样,二者均放在类的外部定义。但友元函数的定义一般放在声明它的类成员函数的外部定义区。

5)使用友元函数的方法是:与普通函数的使用方法一样,必须加上对象名来引用类中的成员。

3. 运用友元的亮点

1)要在满足要求、又不违反友元函数使用原则的前提下,设计好在何处使用友元函数。

2)使用时按照友元函数的书写格式声明和定义,使用方法与以前所讲的普通函数一样。

← 第16章 动态存储第18章 输入与输出 →