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. Linux中find命令的用法汇总

    Linux中find命令的用法汇总 https://www.jb51.net/article/108198.htm

  2. Python Enum 枚举 用法汇总

    Python Enum 枚举 用法汇总 import os import sys if sys.version_info.major + sys.version_info.minor * 0.1 &l ...

  3. C#中DllImport用法汇总

    最近使用DllImport,从网上google后发现,大部分内容都是相同,又从MSDN中搜集下,现将内容汇总,与大家分享. 大家在实际工作学习C#的时候,可能会问:为什么我们要为一些已经存在的功能(比 ...

  4. Hibernate 注解中CascadeType用法汇总

    这两天,参加一个课程设计,同时这个项目又作为一个模块镶嵌到其他项目中,考虑如此,应与原先的架构相同,因牵扯到留言和相互@功能,故数据库之间OneToOne,OneToMany,ManyToMany之风 ...

  5. BeanShell用法汇总(部分摘抄至网络)【转】

    说明:本文部分资料摘抄至 来源: http://www.cnblogs.com/puresoul/p/4915350.html 来源: http://www.cnblogs.com/puresoul/ ...

  6. 正则表达式常用用法汇总 __西科大C语言

    正则表达式,又称正规表示法.常规表示法.(英语:Regular Expression,在代码中常简写为regex.regexp或RE),计算机科学的一个概念.正则表达式使用单个字符串来描述.匹配一系列 ...

  7. XStream 用法汇总

            XStream是一家Java对象和XML转换工具,很好很强大.它提供了所有的基本型.排列.收集和其他类型的支持,直接转换.因此XML在数据交换经常使用.对象序列化(和Java对象的序列 ...

  8. 常用php时间函数用法汇总

    1.设置时区的方法: php5后都要自己设置时区,要么修改php.ini的设置,要么在代码里修改. 在PHP.INI中设置时区 date.timezone = PRC 在代码中设置时区 1 date_ ...

  9. PHP中foreach()用法汇总

    这篇文章主要给大家详细介绍了PHP中foreach()用法以及相关的示例,十分的细致,有需要的小伙伴可以参考下. PHP 4 引入了 foreach 结构,和 Perl 以及其他语言很像.这只是一种遍 ...

  10. js中typeof的用法汇总[转载]

    http://www.jb51.net/article/43187.htm JavaScript中的typeof其实非常复杂,它可以用来做很多事情,但同时也有很多怪异的表现.本文列举出了它的多个用法, ...

随机推荐

  1. 动态Lambda进阶一

    直接上代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; using S ...

  2. 【原创】纯OO:从设计到编码写一个FlappyBird (三)

    第二部分请点这里 下面首先来实现Bing接口! 实现Bing接口的类取名SimpleBing. 容易发现,SimpleBing类总的来说要向下,但点击一下又得向上,向上到了一定界限又得向下,但我们又只 ...

  3. Android 开发环境搭建之——ADT-Bundle for Windows

    ADT-Bundle for Windows 是由Google Android官方提供的集成式IDE,已经包含了Eclipse,你无需再去下载Eclipse,并且里面已集成了插件,它解决了大部分新手通 ...

  4. javascript从定义到执行 js引擎 闭包

    javascript从定义到执行,JS引擎在实现层做了很多初始化工作,因此在学习JS引擎工作机制之前,我们需要引入几个相关的概念:执行环境 栈.全局对象.执行环境.变量对象.活动对象.作用域和作用域链 ...

  5. c语言 int (*p)[5] 类型分析

    #include<stdio.h> int main() {     int i;     int  b[5]={1,3,5,7,9};     int  (*a)[5] = &b ...

  6. WPF技术触屏上的应用系列(六): 视觉冲击、超炫系统主界面、系统入口效果实现

    原文:WPF技术触屏上的应用系列(六): 视觉冲击.超炫系统主界面.系统入口效果实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7操作系统,54寸大屏电脑电视一体 ...

  7. WebService 用户名密码验证

    原文:WebService 用户名密码验证 在项目开发的过程中,WebService是经常要用的,当调用WebService方法时,需要经过服务的验证才可以调用,一般就是用户名/密码验证,还有一个就是 ...

  8. Android - 支持不同的设备 - 支持不同的平台版本

    在最新版本的Android为app提供很好的新API时,也应该继续支持旧版本的Android直到大部分设备已经更新了.这里将要介绍如何在使用最新API带来的优点的同时继续支持老版本. Dashboar ...

  9. 从xcode 6 上传 App Store

    2014苹果结束了大会,ios8公布.可怜的苹果开发人员又要開始伤脑筋了. 比方提交新产品的那个iTunes connect体验就做得极烂.并且这还是本菜鸟的第一次上线提交.折寿啊 一.制作证书.ap ...

  10. 了解HTML5和“她”的 API (三)

    Web Workers(后台线程) JavaScript是单线程的,较长的javascript运算会阻塞UI线程. web worker 是运行在后台的 JavaScript,不会影响页面的性能. 在 ...