C++中的友元机制允许类的非公有成员被一个类或者函数访问,友元按类型分为三种:普通非类成员函数作为友元,类的成员函数作为友元,类作为友元。

1 友元的内容

友元包括友元的声明以及友元的定义。友元的声明默认为了extern,就是说友元类或者友元函数的作用域已经扩展到了包含该类定义的作用域,所以即便我们在类的内部定义友元函数也是没有关系的。

2 普通的非成员函数友元

这类友元函数通常是操作符,例如输入输出操作符.示例如下所示:

//OpeClass.h
#pragma once
class OpeClass
{friend int func(const OpeClass xx);
public:OpeClass(void);OpeClass(int x,int y);~OpeClass(void);
private:int width;int height;
};
//OpeClass.cpp
#include "OpeClass.h"OpeClass::OpeClass(void)
{width = 50;height = 50;
}OpeClass::OpeClass(int x,int y):width(x),height(y)
{
}OpeClass::~OpeClass(void)
{
}int func(const OpeClass xx)
{return xx.height * xx.width;
}
//main.cpp
#include "OpeClass.h"
#include <iostream>
using namespace std;void main()
{OpeClass XO;cout<<func(XO);system("pause");
}

3 类作为友元

类作为友元需要注意的是友元类和原始类之间的相互依赖关系,如果在友元类中定义的函数使用到了原始类的私有变量,那么就需要在友元类定义的文件中包含原始类定义的头文件。
但是在原始类的定义中(包含友元类声明的那个类),就不需要包含友元类的头文件,也不需要在类定义前去声明友元类,因为友元类的声明自身就是一种声明(它指明可以在类外找到友元类),示例程序如下所示:

//A.h
#pragma once
#include <iostream>
using namespace std;
class A
{friend class B;
public:~A(void);static void func(){cout<<"This is in A"<<endl;}
private:A(){};static const A Test;
};
//A.cpp
#include "A.h"
const A A::Test = A();
A::~A(void)
{
}
//B.h
#pragma once
#include "C.h"
class B
{
public:B(void);~B(void);void func(C& c);
};
//B.cpp
#include "B.h"
#include "A.h"
#include "C.h"
#include <iostream>
using namespace std;B::B(void)
{
}B::~B(void)
{
}void B::func(C& c)
{cout<<"This is in B"<<endl;A::Test.func();c.func(A::Test);
}
//C.h
#pragma once
class A;
class C
{
public:C(void);~C(void);void func(const A& a);
};
//C.cpp
#include "C.h"
#include <iostream>
using namespace std;C::C(void)
{
}C::~C(void)
{
}void C::func(const A& a)
{cout<<"This is in C"<<endl;
}
//main.cpp
#include "A.h"
#include "B.h"
#include "C.h"
#include <iostream>
using namespace std;void main()
{B b;C c;b.func(c);system("pause");
}

4 类成员函数作为友元函数

这个稍微有点复杂,因为你要类成员函数作为友元,你在声明友元的时候要用类限定符,所以必须先定义包含友元函数的类,但是在定义友元的函数时候,又必须事先定义原始类。通常的做法先定义包含友元函数的类,再定义原始类,这个顺序不能乱。(如果是友元类,则没有这种这种必须)如下面所示:

//B.h
#pragma once
class A;
class B
{
public:B(void);~B(void);int func(A xx);
};
//A.h
#pragma once
#include "B.h"
class A
{
friend int B::func(A xx);
public:A(void):mx(20),my(30){}~A(void){}
private:int mx;int my;
};
//B.cpp
#include "B.h"
#include "A.h"B::B(void)
{
}B::~B(void)
{
}int B::func(A xx)
{return xx.mx * xx.my;
}
//main.cpp
#include "A.h"
#include "B.h"
#include <iostream>
using namespace std;
void main()
{A a;B b;cout<<b.func(a)<<endl;system("pause");
}

5 友元不具有相互性,只具有单项性 若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。

6 友元不能被继承

B是A的友元类,C是B的子类,推不出C是A的友元

7 友元不具有传递性

B是A的友元,C是B的友元,推不出C是A的友元

8 相互为友元的类

这个其实没什么好注意的,下面是实例,类A,类B互为友元

//A.h
#pragma once
class A
{
friend class B;
public:A(void);~A(void);int funa(B& b);
private:int mx;int my;
};
//A.cpp
#include "A.h"
#include "B.h"A::A(void)
{mx = 10;my = 10;
}A::~A(void)
{
}int A::funa(B& b)
{return b.mb * b.mc;
}
//B.h
#pragma once
class B
{friend class A;
public:B(void);~B(void);int funb(A& a);
private:int mb;int mc;
};
//B.cpp
#include "B.h"
#include "A.h"B::B(void)
{mb = 20;mc = 20;
}B::~B(void)
{
}int B::funb(A& a)
{return a.mx *a.my;
}
//main.cpp
#include "A.h"
#include "B.h"
#include <iostream>
using namespace std;
void main()
{A a;B b;cout<<a.funa(b)<<endl;cout<<b.funb(a)<<endl;system("pause");
}

9 如果想要指定两个类都有成员函数作为对方的友元,那么必须第2个类是第一个类的友元

//A.h
#pragma once// class B is a friend class of A
class A
{friend class B;
public:A(void):ma(10),mb(20){}~A(void){}int funa(B& b);
private:int ma;int  mb;
};
//B.h
#pragma once
#include "A.h"// A's function funa is a friend function of B
class B
{friend int A::funa(B& b);
public:B(void);~B(void);int funb(A& a);int func(A& a);
private:int mx;int my;
};
//A.cpp
#include "A.h"
#include "B.h"int A::funa(B& b)
{return  b.mx * b.my;
}
//B.cpp
#include "B.h"B::B(void):mx(12),my(15)
{
}B::~B(void)
{
}int B::funb(A& a)
{return a.ma + a.mb;
}int B::func(A& a)
{return a.ma * a.mb;
}
//main.cpp
#include "A.h"
#include "B.h"
#include <iostream>
using namespace std;
void main()
{A a;B b;cout<<a.funa(b)<<endl;cout<<b.funb(a)<<endl;cout<<b.func(a)<<endl;
}

C++ friend 用法总结相关推荐

  1. c语言中external,static关键字用法

    static用法: 在C中,static主要定义全局静态变量.定义局部静态变量.定义静态函数. 1.定义全局静态变量:在全局变量前面加上关键字static,该全局变量变成了全局静态变量.全局静态变量有 ...

  2. Pandas_transform的用法

    先来看一个实例问题. 如下销售数据中展现了三笔订单,每笔订单买了多种商品,求每种商品销售额占该笔订单总金额的比例.例如第一条数据的最终结果为:235.83 / (235.83+232.32+107.9 ...

  3. Python中yield和yield from的用法

    yield 后面接的是 future 对象 调用方 委托生成器 yield from 直接给出循环后的结果 yield from 委托者和子生成器直接通信 yield from 直接处理stopIte ...

  4. pytorch学习 中 torch.squeeze() 和torch.unsqueeze()的用法

    squeeze的用法主要就是对数据的维度进行压缩或者解压. 先看torch.squeeze() 这个函数主要对数据的维度进行压缩,去掉维数为1的的维度,比如是一行或者一列这种,一个一行三列(1,3)的 ...

  5. python yield 和 yield from用法总结

    #例1. 简单输出斐波那契數列前 N 个数 #缺点:该函数可复用性较差,因为 fab 函数返回 None,其他函数无法获得该函数生成的数列 #要提高 fab 函数的可复用性,最好不要直接打印出数列,而 ...

  6. tf.nn.embedding_lookup()的用法

    函数: tf.nn.embedding_lookup( params, ids, partition_strategy='mod', name=None, validate_indices=True, ...

  7. OpenMP用法大全

    OpenMP基本概念 OpenMP是一种用于共享内存并行系统的多线程程序设计方案,支持的编程语言包括C.C++和Fortran.OpenMP提供了对并行算法的高层抽象描述,特别适合在多核CPU机器上的 ...

  8. Dorado用法与示例

    Dorado用法与示例 dorado用后总结 一.dorado概念 dorado的产品全名是"dorado展现中间件".从产品形态上dorado由两部分组成,第一部分是一个具有AJ ...

  9. TensorFlow用法

    TensorFlow用法 什么是TensorFlow TensorFlow是一个开源软件库,用于使用数据流图进行数值计算.图中的节点表示数学运算,而图的边缘表示流动的多维数据数组(张量).这种灵活的体 ...

  10. TensorFlow Keras API用法

    TensorFlow Keras API用法 Keras 是与 TensorFlow 一起使用的更高级别的作为后端的 API.添加层就像添加一行代码一样简单.在模型架构之后,使用一行代码,可以编译和拟 ...

最新文章

  1. 鑫哥新作品《工资呀》
  2. 创立创造创建的区别_【干货|知识分享】Solidworks与Rhino有什么区别呢?
  3. python安装了运行不了_python详细安装教程
  4. OpenStack 高性能虚拟机之大页内存
  5. 【Verilog HDL】第三章 reg和net及其一组类型的区别——充分运用实验思维
  6. __proto__ 和 prototype 到底有什么区别
  7. JSTL标签使用说明
  8. c语言及程序设计基础 pdf,《C语言程序设计基础》.pdf
  9. IEEE access参考文献的添加
  10. 关于linux打包以及解压到指定目录的简单操作demo
  11. 微型计算机原理与接口技术
  12. 泛函分析 06.01 线性算子的谱理论 - 谱集和正则点集
  13. 大大学校园计算机市场分析,Acer笔记本计算机营销策略分析以大学生市场为例.doc...
  14. MATLAB 线性拟合
  15. 国际贸易基础(三)商检
  16. 《统计学习方法》(李航)的学习体会(一)
  17. 计算机网络公网ip,怎么查看电脑的公网IP地址
  18. Java 与或非 判断
  19. JavaScript基础-数组
  20. TSRC靶场赛-writeup

热门文章

  1. 时代产业变迁与时代产业创新:如何重构人与产业的链接
  2. 零基础学前端系列教程 | 和前端谈恋爱的第003天——电影海报
  3. python3 解析文件类型filetype
  4. 通过修改注册表优化win7性能
  5. utools 效率桌面工具
  6. jsharer验证码识别的c#实现
  7. sensor曝光量和曝光行的区别_阿里巴巴里的曝光量是什么意思?
  8. 让Windows Media Player和MP3播放器一样可以显示歌词
  9. MFC窗口的GetDC()/ReleaseDC()有bug会造成内存泄露
  10. 金融项目-注册和实名功能