采用类的机制后实现了数据的隐藏与封装,类的数据成员一般定义为私有成员,成员函数一般定义为公有的,依此提供类与外界间的通信接口。

但是,有时需要定义一些函数,这些函数不是类的一部分,但又需要频繁地访问类的数据成员,这时可以将这些函数定义为该函数的友元函数。除了友元函数外,还有友元类,两者统成为友元。友元的作用是提高了程序的运行效率(即减少了类型检查和安全性检查等都需要时间开销),但它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。

友元函数:

友元函数是可以直接访问类的私有成员的非成员函数。它是定义在类外的普通函数,它不属于任何类,但需要在类的定义中加以声明,声明时只需在友元的名称前面加上关键字friend,其格式如下:

Friend 类型  函数名(形式参数);

友元函数的声明可以放在类的私有部分,也可以放在公有部分,它们是没有区别的,都说明是该类的一个友元函数。

一个函数可以是多个类的友元函数,只需要在各个类中分别声明。

友元函数的调用与一般函数的调用方式和原理一致。

友元类:

友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。

当希望一个类可以存取一个类的私有成员时,可以将该类声明为另一类的友元类。定义友元类的语句格式如下:

Friend  class  类名;

其中:friend和class是关键字,类名必须是程序中的一个已定义过的类。

例如,以下语句说明类B是类A的友元类:

Class A

{

…..

Public:

Friend class B;

};

经过以上说明后,类B的所有成员函数都是类A的友元函数,能存取类A的私有成员和保护成员。

使用友元类时注意:

(1)       友元关系不能被继承。

(2)       友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。

(3)       友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明。

Windows环境多线程编程原理与应用 中解释:

如果将类的封装比喻成一堵墙的话,那么友元机制就像墙上了开了一个门,那些得到允许的类或函数允许通过这个门访问一般的类或者函数无法访问的私有属性和方法。友元机制使用类的封装性得到消弱,所以使用时一定要慎重。

友元类的说明:

将外界的某个类在本类别的定义中说明为友元,那么外界的类就成为本类的“朋友”,那个类就可以访问本类的私有数据了。

Class Merchant

{

Private:

Int m_MyMoney;

Int m_MyRoom;

Public:

Friend class Lawyer;

Int getmoney();

…..

};

Class Lawyer

{

Private:

….

Public:

….

};

只有你赋予某个类为你的友元时,那个类才有访问你的私有数据的权利。

说明一个函数为一个类的友元函数则该函数可以访问此类的私有数据和方法。定义方法是在类的定义中,在函数名前上加上关键字friend

《挑战30天C/C++》这样解释:

在说明什么是友元之前,我们先说明一下为什么需要友元与友元的缺点:

通常对于普通函数来说,要访问类的保护成员是不可能的,如果想这么做那么必须把类的成员都声明成public(公用的),然而这带来的问题便是任何外部函数都可以毫无约束的访问它操作它,c++利用friend修饰符,可以让一些你设定的函数能够对这些保护数据进行操作,避免把类成员全部设置成public,最大限度的保护数据成员的安全。

友元函数能够使得普通函数直接访问类的保护数据,避免了类成员函数的频繁调用,可以节约处理器开销,提高程序的效率,但所矛盾的是,即使是最大限度大保护,同样也破坏了类的封装特性,这即是友元的缺点,在现在cpu速度越来越快的今天我们并不推荐使用它,但它作为c++一个必要的知识点,一个完整的组成部分,我们还是需要讨论一下的。

在类里声明一个普通数学,在前面加上friend修饰,那么这个函数就成了该类的友元,可以访问该类的一切成员。

#include <iostream>

Using namespace std;

Class internet

{

Public:

Internet(char *name,char*address)//改为:internet(const char *name,const char * address)

{

Strcpy(Internet::name,name);

Strcpy(Internet::address,address);

}

Friend void showN(Internet &obj);//友元函数的声明

Public://改为;private

Char name[20];

Char address[20];

};

Void showN(Internet &obj)//函数定义,不能写成,void Internet::ShowN(Internet &obj)

{

Cout<<obj.name<<endl;//可访问internet类中的成员

}

Void main()

{

Internet a(“中国软件开发实验室”,”www.cndev-lab.com”);

ShowN(a);

Cin.get();

}

上面的代码通过友元函数的定义,我们成功的访问了a对象的保护成员name,友元函数并不能看做是类的成员函数,它只是个被声明为友元的普通函数,所以在类外部函数的定义部分不能够写成void Internet::ShowN(Internet &obj),这一点要注意

实例:

分别定义一个类A和类B,各有一个私有整数成员变量通过构造函数初始化:类A有一个成员函数Show(B &b)用来打印A和B的私有成员变量,请分别通过友元函数和友元类来时间此功能。

用友元类与友元函数做出来的

#include <iostream>

using namespace std;

class B;

class A;

void Show(A &,B&);

class B

{

Private:

Int tt;

Friend class A;

Friend void Show(A&,B&);

Public:

B(int temp=100):tt(temp){}

Void Show(B &b)

{

Cout<<value<<endl;

Cout<<b.tt<<endl;

}

};

Void Show(A& a,B&b)

{

Count<<a.value<<endl;

Count<<b.tt<<endl;

}

Int main()

{

A a;

B b;

  1. show(b);

show(a,b);

return 0;

}

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

  1. C#中实现C++中的友元类

    最近做一个小程序,一个类A(负责显示处理)需要大量调用类B(负责数据处理)的函数,我最先想到的C++中的友元概念,因为类B中的这些函数并不希望public,它只是允许类A调用监测. 网上搜索了一下,没 ...

  2. Java中的访问控制权限

    简介 Java中为什么要设计访问权限控制机制呢?主要作用有两点: (1)为了使用户不要触碰那些他们不该触碰的部分,这些部分对于类内部的操作时必要的,但是它并不属于客户端程序员所需接口的一部分. (2) ...

  3. delphi 的一些注意点和知识点

    关于Delphi中产生的文件    编辑阶段: pas/单元文件,dpk/组件包文件,dpr/工程文件,dfm/窗体文件    编译阶段: dcu/单元编译文件,dcp/Delphi Compile ...

  4. c/c++ 友元基本概念

    友元基本概念: 1,把一个一般函数声明为一个类的友元函数 2,把一个类A的某几个成员函数声明为某个类B的友元函数 3,把一个类A声明为一个类B的友元类. 友元的作用:可以访问类B里所有的成员变量和成员 ...

  5. C++学习笔记之友元

    一.引言 C++控制对类对象私有部分(private)的访问,通常只能通过公有的(public)类方法去访问.但是有时候这种限制太严格,不适合特定的问题,于是C++提供了另外一种形式的访问权限:友元. ...

  6. C++重载(主要介绍使用友元函数重载)

    重载限制 多数C++运算符都可以用下面的方式重载.重载的运算符不必是成员函数,但必须至少有一个操作数是用户自定义的类型.下面详细介绍C++对用户定义的运算符重载的限制. 1 重载后的运算符必须至少有一 ...

  7. C++学习笔记(十六):友元

    问题的提出: 我们已知道类具备封装和信息隐 藏的特性.只有类的成员函数才能访问类的私有成员,程式中的其他函数是无法访问私有成员的.非成员函数能够访问类中的公有成员,但是假如将数据成员都定义 为公有的, ...

  8. Effective C++ 第二版 17)operator=检查自己 18)接口完整 19)成员和友元函数

    条款17 在operator=中检查给自己赋值的情况 1 2 3 class  X { ... }; X a; a = a;  // a 赋值给自己 >赋值给自己make no sense, 但 ...

  9. 深入浅出Win32多线程程序设计之基本概念

    一.深入浅出Win32多线程程序设计之基本概念[转] 引言 从单进程单线程到多进程多线程是操作系统发展的一种必然趋势,当年的DOS系统属于单任务操作系统,最优秀的程序员也只能通过驻留内存的方式实现所谓 ...

随机推荐

  1. deepin下安装python的Tkinter库

    在Linux下,如果需要编写界面应用,并且此界面应用对性能的要求不是很高,一般可以使用Python解决.Python中可以使用自带的Tkinter库或者是第三方的Wxpython库,当然Tkinter ...

  2. OpenFiler configuration

    5.OpenFiler configuration   登录Openfiler   步骤1:安装 FireFox   步骤2:通过FireFox以HTTPS://server-ip:446 远程访问O ...

  3. Mysql 变量讲解

    set语句的学习: 使用select定义用户变量的实践将如下语句改成select的形式: set @VAR=(select sum(amount) from penalties);我的修改: sele ...

  4. apple touch icon 大小总结

    <!-- For Chrome for Android: --> <link rel="icon" sizes="192x192" href= ...

  5. Mybatis学习手记(二)

    要点一.如果字段名与类的属性名不一致,要在*Mapper.xml文件中,新建resultMap 配置对应关系,如下图:

  6. VMware Workstation网卡不启动

    故障原因:虚拟机安装完成后,默认网络配置为”NAT”,对应真机的系统服务为“VMware NAT Service”默认情况下该服务启动类型为自动,状态为启动,若该服务未能正常启动则会导致如上报错,手动 ...

  7. jQuery EasyUI的各历史版本和应用

    from:http://blog.sina.com.cn/s/blog_b8be6dc40102xpe6.html 各历史版本下载地址: http://www.jeasyui.com/download ...

  8. sedna进行xquery查询

    有一个文件book.xml: <books> <book> <name>The Call Of Wild</name> <author>Ja ...

  9. Android开发:fragment将事件传递回activity

    fragment触发事件后传递会给activity,可以通过在fragment中定义一个接口,让activity实现这个接口. 具体代码如下 public class AAFragment exten ...

  10. LightOJ1089

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=26806 题目大意:略 题目思路:前缀和与离散化 可用线段树做,但是 ...