首页
登录 | 注册

C++友元函数

友元函数的基本概念

1、概念:可以在类A中通过关键字friend声明或定义某个独立函数另一个类B的某个成员函数另一个类B为类A的友元函数,友元函数可以无限制的存取类A的成员(包括私有、公有和保护成员)。

2、定义形式:friend 函数类型 函数所在类名::函数名(参数列表);

3、友元函数可在类中的私有或公有部分通过关键字friend说明或定义,但如在类中声明,而在类外定义,就不能再在类外使用friend关键字。友元函数作用域的开始点在它的说明点,结束点和类的作用域相同。

4、友元函数应被看作类的接口的一部分,使用它的主要目的是提高效率,因为它可以直接访问对象的私有成员,从而省去调用类的相应成员函数的开销。友元函数的另一个优点是:类的设计者不必在考虑好该类的各种可能使用情况之后再设计这个类,而是可以根据需要,通过使用友元来增加类的接口。

一、类外的独立函数作为类的友元函数

类外的独立函数作为类的友元函数,这个独立函数其实就是一个普通的函数,仅有的不同点是:它在类中被说明为类的友元函数,可以访问该类所有对象的私有成员。

【例1】使用友元函数计算两点距离的例子

#include <iostream>

#include <cmath>

using namespace std;

class Point {

  private:

   double X,Y;

  public:

   Point( double xi,double yi){X=xi,Y=yi;}      //类Point的构造函数

   double GetX( ){return X;}

   double GetY( ){return Y;}

   friend double distances( Point&, Point&);     //声明友元函数

};

double distances( Point& a, Point& b)

            //像普通函数一样定义友元函数,传引用的方式不会产生临时对象

{ double dx=a.X-b.X;    //因是友元函数,所以可以直接访问对象的私有数据成员

 double dy=a.Y-b.Y;    //因是友元函数,所以可以直接访问对象的私有数据成员

 return sqrt( dx*dx + dy*dy );

}

void main( ){

 Point p1(3.5,5.5),p2(4.5,6.5);

     //定义Point类的对象p1和p2,并调用Point类的构造函数对其初始化

 Cout<<"The distance is"<<distances(p1,p2)>>endl;

    //调用函数distances,实现dx、dy和两点距离的计算并返回后输出

} //程序结束,析构Point类的对象p1和p2。

二、类B的成员函数作为类A的友元函数

一个类的成员函数(包括构造函数和析构函数)可以通过使用friend说明为另一个类的友元函数。

【例2】类One的对象通过友元函数访问类Two的对象的私有数据

#include <iostream>

using namespace std;

class Two;             //先声明类Two,以便类One引用Two&

class One {

private:

  int x;

public:

  One(int a){x=a;}      //定义类One的构造函数

  int Getx( ){return x;}    //定义普通成员函数

  void func(Two&);     //声明本类的成员函数,参数为类Two的引用

};

class Two{

private:

  int y;

public:

  Two(int b){y=b;}      //定义类Two的构造函数

  int Gety( ){return y;}     //定义普通成员函数

  friend void One::func(Two&); //声明类One的成员函数为本类的友元函数

};

void One::func(Two& r) {r.y=x;} /*定义函数func,以类Two对象的引用为参数。因其是类One的成员函数,所以可自由存取所在类One的私有数据成员;因其在类Two中被声明为友元函数,所以可使用对象名存取类Two的私有数据成员(r.y=x即说明了这些)*/

void main( ){

  One Obj1(5);      //定义类One的对象Obj1并调用其构造函数初始化Obj1.x为5

  Two Obj2(8);      //定义类Two的对象Obj2并调用其构造函数初始化Obj2.y为8

  Cout<<Obj1.Getx( )<<" "<<Obj2.Gety( )<<endl; //输出:5 8

  Obj1.func(Obj2); /*调用函数func将Obj2的地址传给r,执行函数体内语句,将Ojb1的私有数据成员x的值赋给Obj2的私有数据成员y,y的值变为5,x的值不变仍为5*/

  Cout<<Obj1.Getx( )<<" "<<Obj2.Gety( )<<endl; //输出:5 5

}

//程序结束,调用类Two的默认析构函数析构对象Obj2,然后调用类One的默认析构函数析构对象Obj1。

三、将一个类说明为另一个类的友元

可以将一个类One说明为另一个类Two的友元,这时,整个类One的成员函数均是类Two的友元函数,声明语句简化为:friend class 类名;。

【例3】类One的对象可以通过任意一个成员函数访问类Two的对象的私有数据

#include <iostream>

using namespace std;

class Two{

   int y;         //默认为private

public:

   friend class One;   //声明类One为类Two的友元

};

class One{         //类One的成员函数均是类Two的友元函数

   int x;        //默认为private

public:

   One(int a,Two&r,int b){x=a;r.y=b;}    //利用类One的构造函数给本类及类Two的对象赋值

   void Display(Two&);           //声明类One的成员函数,它能访问类Two的成员

};

void One::Display(Two&r)           //定义类One的成员函数,输出类Two的的成员

  {cout<<x<<" "<<r.y<<endl;}

void main( ){

  Two Obj2;              // 定义类Two的成员obj2

  One Obj1(23,Obj2,55); /* 定义类One的成员obj1并调用One的构造函数给本类及类Two的对象赋值:obj1.x=23,obj2.y=55 */

  Obj1.Display(Obj2); /* 调用定义类One的成员函数Display输出Obj1的私有数据成员x的值和Obj2的私有数据成员y的值,输出:23 55 */

} //程序结束,先后执行类One和类Two的默认析构函数,析构对象Obj1和Obj2。


相关文章

  • 定义函数时,默认参数必须指向不变的对象 参数为可变对象时,正常调用的时候,结果没有问题,但是当使用默认参数的时候,结果就会和理想的有差距. In [78]: def add(L=[]): ...: L.append('END') ...: ...
  • 前言:最近一直在刷leetcode的题,用到isalnum函数,用man手册查找了一下,总共有13个相关函数如下: #include <ctype.h> int isalnum(int c); int isalpha(int c ...
  • 详解linux进程间通信-管道 popen函数 dup2函数
    前言:进程之间交换信息的唯一方法是经由f o r k或e x e c传送打开文件,或通过文件系统.本章将说明进程之间相互通信的其他技术—I P C(InterProcess Communication).今天将介绍半双工的管道. 一.匿名管 ...
  • 目录 什么是闭包?(掌握) 两种为函数传参的方式 闭包函数的应用(掌握) 回顾: 函数对象:可以将定义在函数内的函数返回到全局使用,从而打破函数的层级限制. 名称空间与作用域:作用域关系在函数定义阶段时就已经固定死了,与调用位置无关,即在任 ...
  • 页面性能优化-原生JS实现图片懒加载
         在项目开发中,我们往往会遇到一个页面需要加载很多图片的情况.我们可以一次性加载全部的图片,但是考虑到用户有可能只浏览部分图片.所以我们需要对图片加载进行优化,只加载浏览器窗口内的图片,当用户滚动时,再加载更多的图片.这种加载图片的 ...
  • 《k8s 源码分析》- Custom Controller 之 Informer
    Custom Controller 之 Informer 概述 架构概览 reflector - List & Watch API Server Reflector 对象 ListAndWatch watchHandler - ad ...

2019 cecdns.com webmaster#cecdns.com
12 q. 0.063 s.
京ICP备10005923号