c++中的类具有封装性,类中的私有数据只有该类的成员函数可以访问,程序中访问类中的私有成员,必须通过对象来调用成员函数,但是频繁的调用会使运行效率降低。

为了解决上述问题,c++中加入友元机制,友元可以不通过调用成员函数直接访问类的私有数据来提高运行效率。

友元可以是函数(友元函数)也可以是类(友元类)

友元函数:

  • 类体内说明,加friend关键字,在类体外定义,定义格式和普通函数相同。
  • 友元函数是非成员函数,调用上和普通函数相同。
  • 友元函数可以直接访问类中私有成员。

全局或函数做友元函数:

 #include<iostream>
#include<cmath>
using namespace std;
class Point
{
public:
Point(double xx, double yy)
{
x = xx;
y = yy;
}
void Getxy();
friend double Distance(Point &a, Point &b);
private:
double x, y;
};
void Point::Getxy()
{
cout << "(" << x << "," << y << ")" << endl;
}
double Distance(Point &a, Point &b)
{
double dx = a.x -­‐ b.x;
double dy = a.y -­‐ b.y;
return sqrt(dx*dx + dy*dy);
}
int main(void)
{
Point p1(3.0, 4.0), p2(6.0, 8.0);
p1.Getxy();
p2.Getxy();
double d = Distance(p1, p2);
cout << "Distance is " << d << endl;
return ;
}

类成员函数做友元函数:

 #include<iostream>
#include<cmath>
using namespace std;
class Point;
//前向声明,是⼀一种不完全型声明,即只需提供类名(⽆无需提供类实现)即可。仅可⽤用 于声明指针和引
⽤用。
class ManagerPoint
{
public:
double Distance(Point &a, Point &b);
};
class Point
{
public:
Point(double xx, double yy)
{
x = xx;
y = yy;
}
void Getxy();
friend double ManagerPoint::Distance(Point &a, Point &b);
private:
double x, y;
};
void Point::Getxy()
{
cout << "(" << x << "," << y << ")" << endl;
}
double ManagerPoint::Distance(Point &a, Point &b)
{
double dx = a.x -­‐ b.x;
double dy = a.y -­‐ b.y;
return sqrt(dx*dx + dy*dy);
}
int main(void)
{
Point p1(3.0, 4.0), p2(6.0, 8.0);
p1.Getxy();
p2.Getxy();
ManagerPoint mp;
float d = mp.Distance(p1,p2);
cout << "Distance is " << d<< endl;
return ;
}

友元类:

  • 友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息
  • 格式;friend class 友元类名
  • 当说明一个类A是另一个类B的友元时,友元类A中所有成员函数都是另一个类B的友元函数
 #include <iostream>

 using namespace std;

 class X{
public:
friend class Y; //类Y 是类X 的友元类
void set(int i) { x=i; }
void display()
{
cout<<"x="<<x<<","<<"y="<<y<<endl;
}
private:
int x;
static int y; //静态数据说明
}; class Y
{
public:
Y(int i,int j);
void display();
private:
X a; //数据成员为类X的对象
}; int X::y=; //静态数据定义并初始化 Y::Y(int i,int j)
{
a.x=i; X::y=j;
} void Y::display()
{
cout<<"x="<<a.x<<","<<"y="<<X::y<<endl;
} int main()
{
X b;
b.set();
b.display();
Y c(,);
c.display();
b.display();
return ;
}

总结:

  1. 友元虽然提高了代码的运行效率,但是他破坏了类的封装性。
  2. 友元关系不可以被继承
  3. 友元关系是单向的,没有交换性
  4. 友元关系没有传递性

04 c++中的友元的更多相关文章

  1. 在ubuntu 16.04系统环境中搭建NAS(samba/iscsi/nfs)

    在ubuntu 16.04系统中搭建NAS环境 一.基本配置1:设置静态IPvi /etc/network/interfaces#iface ens32 inet dhcpiface ens32 in ...

  2. 在Ubuntu 12.04系统中安装配置OpenCV 2.4.3的方法

    在Ubuntu 12.04系统中安装配置OpenCV 2.4.3的方法   对于,在Linux系统下做图像识别,不像在windows下面我们可以利用Matlab中的图像工具箱来实现,我们必须借助Ope ...

  3. ubuntu14.04系统中virtualbox安装Oracle VM VirtualBox Extension Pack包

    ubuntu14.04系统中virtualbox默认不支持usb设备,需要安装Oracle VM VirtualBox Extension Pack才行,但必须安装以下版本才可以安装成功: Oracl ...

  4. 记录在Ubuntu 18.04系统中安装Apache, MySQL和PHP环境

    虽然我们在Linux VPS.服务器安装WEB环境比较方便,可以选择面板或者一键包,但是有些我们需要深入学习的网友不会选择一键安装,而是会尝试编译安装.这样可以学到一些内在的技术.一般我们较为习惯选择 ...

  5. C++中的友元函数和友元类

    C++中的友元函数主要应用于以下场景: 友元函数 第一种场景 代码中有一个全局函数,该函数想要去访问某个类的成员变量(该类的成员变量是private的,且该类并未提供任何获取获取私有成员变量的publ ...

  6. Ubuntu16.04系统中不同版本Python之间的转换

    Ubuntu系统自带的版本是2.7.12 安装好python3.6之后,改变一下Python的优先级(需要root权限). 在使用下面这个命令查看电脑里面有几个Python版本 update-alte ...

  7. 31. Ubuntu15.04系统中如何启用、禁用客人会话

    https://jingyan.baidu.com/article/046a7b3edf9639f9c27fa995.html 31. Ubuntu15.04系统中如何启用.禁用客人会话 听语音 | ...

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

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

  9. Ubuntu 18.04系统中不能ssh外网远程

    前言 今天我不小心动了电插板,导致服务器断电,用远程命令开机,居然很长时间没反应,索性就亲自按电源键重启.服务器正常开机启动,ssh可以内网访问,远程命令内网有效果,就是外网不行.经过分析排查,是不是 ...

随机推荐

  1. NOI2019 Fe

    NFLS XY NOI2019 Fe Orz zsy,zhf,wqy,zjc,bly! Goodbye OI!

  2. springboot集成mybatisplus小例子

    集成mybatisplus后,简单的CRUD就不用写了,如果没有特别的sql,就可以不用mapper的xml文件的. 目录 pom.xml文件 <?xml version="1.0&q ...

  3. springboot热部署JRebel插件

    激活参考:https://www.52pojie.cn/thread-906163-1-1.html 最后设置为离线,不然每次启动要重新激活 环境idea是2018.1.1版本 JRebel是最新版2 ...

  4. ref,out,int参数复习

    ref 结构是值类型,按值传递.通过关键字ref,也可以通过引用传递结构. public static void ChangeA(ref A a) { a.X = ; } //如果A是结构类型,就添加 ...

  5. Java字符串无意识的递归

    Java中的每个类基本上都继承自Object,标准容器类自然也不例外.因此容器类都有toString()方法,并且重写了该方法,使得它生成的String结果能够表达容器本身,以及容器所包含的对象.例如 ...

  6. Java设计模式--代理模式+动态代理+CGLib代理

    静态代理 抽象主题角色:声明真实主题和代理主题的共同接口. 代理主题角色:代理主题内部含有对真实主题的引用,从而在任何时候操作真实主题对象:代理主题提供一个与真实主题相同的接口,以便在任何时候都可以代 ...

  7. [Oracle] - 查看数据库中每个表占用空间大小,及进行表压缩

    查询用户创建的表 select * from user_tab_comments; -- 查询本用户的表,视图等. select * from user_col_comments; -- 查询本用户的 ...

  8. TZOJ5697: 数据结构实验:归并排序

    #include<stdio.h> #include<stdlib.h> void merge(int a[], int start,int mid,int end) { )) ...

  9. logrus 剖析之 formatter

    使用 logrus 通过 formatter 来定义输出日志的格式,具体例子如下: package main import ( log "github.com/Sirupsen/logrus ...

  10. change事件传值方式 data-set 以及复杂数据类型 可以动态创建对象push到数组里面

    <template>   <div>     <!-- <div class="banner">       <a-breadcru ...