一、友元函数

友元函数是一种特殊的函数,它需要在类体内进行说明,可以访问类的私有成员和保护成员,但又不是类的成员函数。友元函数的说明如下:

friend 数据类型函数名(参数)

其中,friend是说明友元函数的关键字,友元声明可以出现在类中的任何地方。通常,将友元声明成组地放在类定义的开始或结尾是个好主意。归纳起来,友元函数是一种能够访问类中私有成员的非类成员函数,友元函数在定义上和调用上与普通函数一样。友元的作用在于提高程序的运行效率,但是,它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。因此,只有在十分需要的时候才使用友元函数。 例如:分析下面程序的输出结果

#include

#include

using namespace std;

class TPoint

{

private:

double x,y; //私有数据成员

public:

TPoint(double a,double b) //构造函数

{

x=a,y=b;

cout<

}

friend double distanceoftwopoints(TPoint &a, TPoint &b) //友元函数

{

return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));

}

} ;

int main()

{

TPoint p1(2,2),p2(5,5);

cout<

return 0;

}

上述程序中,distaceoftwopoints()是类TPoint的友元函数,在其中可以直接使用a.x等,由于x等是类TPoint的私有成员,所以在普通函数中是不能这么使用的,但是在友元函数中则可以。下面是该程序的输出。

友元函数的一个重要特点是它可以是多个类的友元。例如,编写一个程序,求一个点到直线的距离。设计一个点类Point,它有两个私有数据成员x和y,表示点的坐标。另一个类为直线类Line,它有三个私有数据成员a,b和c,表示直线方程ax+by+c=0。这两个类中都说明了一个友元函数dist,用于计算一个点到直线的距离。点(x,y)到直线ax+by+c=0的距离d的计算公式如为:d=abs((ax+by+c)/sqrt(a* a+b*b)),其中abs是求绝对值函数,sqrt是求平方根函数。代码如下:

#include

#include

using namespace std;

class Line;//提前说明

class Point

{

int x,y;

public:

Point(int x1,int y1)

{

x=x1; y=y1;

}

friend double dist(Line l, Point p);//友元函数说明

} ;

class Line

{

int a,b,c;

public:

Line(int a1, int b1, int c1)

{

a=a1; b=b1; c=c1;

}

friend double dist(Line l, Point p);//友元函数说明

};

double dist(Line l, Point p)//注意:类内已经说明,因此函数前不要加friend

{

double d;

d = abs(l.a*p.x+l.b*p.y+l.c)/(sqrt(l.a*l.a+l.b*l.b));

return d;

}

int main()

{

Point p(10,10);

Line l(2,4,-3);

cout<

return 0;

}

下面是该程序的输出结果:上述程序中有两个类Point和Line,它们都说明了同一个友元函数:friend double dist(Line l, Point p)。由于在Point类中说明时尚未定义类Line,所以需要在前面用class Line语句进行提前说明。该程序的执行如下:

一个类A的成员 函数f()可以作为另一个类B的友元函数,在这种情况下,必须先定义A类,并且在B类中说明友元函数f()时,要加上成员函数所在类的类名,即:

class A

{

...

数据类型 f(参数表)

...

}

class B

{

...

friend 数据类型 A::f(参数表);

...

}

数据类型 A::f(参数表)

{

函数体;

}二、友元类

除了前面所讲过的友元函数外,友元还可以是一个类,即一个类可以作为另一个类的友元。当一个类作为另外一个类的友元时,就意味着这个类的所有成员函数都是另一个类的友元函数。例如,以下程序说明类B是类A的友元类:

class A

{

...

Public:

friend class B;//说明B是A的友元类

...

}

例如,有如下程序

#include

#include

using namespace std;

class A

{

int x;

public:

A() {x=5;}

friend class B;//说明B是A的友元类

};

class B

{

public:

void disp1(A tmp){

tmp.x++;

cout<

}

void disp2(A tmp){

tmp.x--;

cout<

}

};

int main()

{

A obj1;

B obj2;

obj2.disp1(obj1);

obj2.disp2(obj1);

return 0;

}

}

上述程序中,类B是类A的友元类,类B包括两个成员函数,这两个成员函数可以当成类A自己的友元函数一样使用,该程序执行结果如下:

友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。当希望一个类可以存取另一个类的私有成员时,可以将该类声明为另一类的友元类。关于友元类的注意事项:(1)友元关系不能被继承。(2)友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。(3)友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明。

三、习题解析

1.一个类的友元函数能够访问该类的( )。A.私有成员 B.保护成员 C.公有成员 D.所有成员

解析:一个类的友元函数对类成员的访问能力等同于类的成员函数,即能访问类的所有成员,选D。

2.下列的各类函数中,( )不是类的成员函数。A、 构造函数 B、析构函数 C、友元函数 D、拷贝初始化构造函数

答案:C

3.下列关于友元的描述中,错误的是( )A.友元函数可以访问该类的私有数据成员B.一个类的友元类中的成员函数都是这个类的友元函数C.类与类之间的友元关系可以继承D.友元可以提高程序的运行效率

解析:友元关系是不能被继承的,并且是单向的,不可交换的。

4.下列程序利用友元函数求2个点的距离,找出存在的错误(有2个错)。

#include

#include

class Tpoint

{ double x,y;

public:

Tpoint(double a,double b)

{ x=a; y=b; }

friend double distance(Tpoint &, Tpoint &);

};

double Tpoint::distance(Tpoint &p1,Tpoint &p2)

{ double dist;

dist=sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));

return dist;

}

int main()

{ Tpoint p1(2,2),p2(5,6);

cout<

return 0;

}四、小结

在需要允许某些特定的非成员函数访问一个类的私有成员(及受保护成员),而同时仍阻止一般的访问的情况下,友元是可用的。

优点:可以灵活地实现需要访问若干类的私有或受保护的成员才能完成的任务;便于与其他不支持类概念的语言(如C语言、汇编等)进行混合编程;通过使用友元函数重载可以更自然地使用C++语言的IO流库,便于实现运算符的重载等功能。

缺点:一个类将对其非公有成员的访问权限授予其他函数或者类,会破坏该类的封装性,降低该类的可靠性和可维护性。

参考书目

《C++ Primer》,《C++语言习题与解析》等

c语言的友元函数的用法,C++友元函数和友元类概念解析相关推荐

  1. c语言count函数的用法,java count函数用法

    java count函数用法 [2021-02-11 06:55:28]  简介: 在excel中count函数的功能是:计算数字的个数,对给定数据集合或者单元格区域中数据的个数进行计数.COUNT函 ...

  2. c语言string函数的用法_同一个函数的五六个版本,C++string insert函数详解

    前言 string 类的成员函数有很多,同一个名字的函数也常会有五六个重载的版本.篇幅所限,不能将这些原型一一列出并加以解释.这里仅对insert函数做以介绍,并直接给出应用的例子,通过例子,读者可以 ...

  3. C语言strcpy_s 和strncpy_s的用法,以及函数实现的方法

    //strcpy_s 和strncpy_s的用法,以及函数实现的方法 #include<stdio.h> #include<stdlib.h> #include<stri ...

  4. C语言自定义s函数,C语言strcpy_s 和strncpy_s的用法,以及函数实现的方法

    //strcpy_s 和strncpy_s的用法,以及函数实现的方法 #include#include#include//用strcpy_s的方法将str2的内容存入str3 //int main() ...

  5. select函数fdwrite用法_NumPy 分段函数

    简单分段,可以使用嵌套where()函数的办法: 分段数较多,可以用select()函数: NumPy提供了piecewise()专门用于计算分段函数. where()的函数的用法参见: 怎么理解nu ...

  6. zip函数的用法python_Python zip函数 python zip函数的用法

    python 当中的zip( )函数到底是干嘛的? zip([1,2,3],['a','b','c']) 结果是 [(1, 'a'), (2, 'b'), (3, 'c')] 就是依次取出每一个数组的 ...

  7. python decode函数的用法_oracle decode函数使用方法

    以下是一个简单测试,用于说明Decode函数的用法: SQL> create table t as select username,default_tablespace,lock_date fr ...

  8. python decode函数的用法_Oracle DECODE函数的用法详解

    Oracle DECODE函数 使用方法: 1.比较大小 select decode(sign(变量1-变量2),-1,变量1,变量2) from dual; --取较小值 sign()函数根据某个值 ...

  9. linux中stat函数的用法,os.stat()函数的用法

    os.stat() 函数会给出一个文件或文件描述符(file descriptor)的各种状态信息,如权限,大小,所属用户和组,修改时间等.这个函数实际上是调用OS的系统调用stat()来实现功能,对 ...

最新文章

  1. JMeter接口测试通过企业微信API记录(二)创建审批接口并测试
  2. Vista Media Center 开发之深入浅出 (二) --Vista Media Center 程序的新建及部署
  3. 强迫用户升Win10?旧版Windows放弃对新CPU更新支持
  4. 如何debug 右键菜单执行逻辑 - Test BSP Application page implementation
  5. 使用docker搭建redis主从
  6. DNS的一些相关基础知识
  7. 2021,我的年终总结......
  8. 可视化,别把简单内容复杂化
  9. ubuntu下安装配置java8
  10. LoadRunner压力测试案列
  11. centos7.5安装
  12. 国内外期货、外汇、股指期货 交易时间(转载)
  13. 群同态和群同构的区别_同构和同态有什么区别,它们可以用在哪些方面?
  14. android获取apk版本号,android 获取apk的版本信息
  15. android bea拷贝,从Android开发中学到一些东西
  16. java基本语法——helloword
  17. WVS使用教程(Web Vulnerability Scanner)
  18. 电路基本原理和加法器的实现---计算机组成原理学习心得04
  19. 蝴蝶效应,鳄鱼法则,罗森塔尔效应,帕金森定律,手表定律,破窗理论,晕轮效应 ,霍桑效应,二八定律,木桶理论,马太效应,踢猫效应…………
  20. 广和通5G模组FM650-CN在Win11下的短信和通话演示

热门文章

  1. Python Pytest自动化测试 断言失败后续代码继续执行
  2. 北京dns服务器ip地址_什么是DNS? 域名系统,DNS服务器和IP地址概念介绍
  3. 如何在面试中找到优秀的程序员(转载)
  4. CSS 标签元素:nth-child、first-child、last-child
  5. 技术学习之路漫漫其修远兮,奋力勤学吾辈将上下而求索
  6. AMBA AHB面试题连载(一)
  7. 准备Android面试?Android开发真等于废人?复习指南
  8. 行人重识别Deep person reid源码测试(Torchreid)(一)
  9. C++中类的成员函数(方法)
  10. 尝试opencv裂缝检测