详解C++ friend关键字
1. 为什么要使用友元?
通常对于普通函数来说,要访问类的保护成员是不可能的,如果想这么做那么必须把类的成员都生命成为 public( 共用的) ,然而这做带来的问题遍是任何外部函数都可以毫无约束的访问它操作它;另一种方法是利用 C++ 的 friend 修饰符,可以让一些你设定的函数能够对这些私有或保护数据进行操作。
2. 使用友元有哪些缺点?
使用友元的同时也破坏了类的封装特性,这即是友元最大的缺点。当对外声明为友元后,你的所有细节全部都暴露给了对方。
就好像你告诉你朋友你很有钱这个密秘,进而又把你有多少钱,多少古董,多少家产,多少小妾等等所有的家底全给他说了。
3. 友元怎样理解?
定一个友元函数,或是友元类,就是告诉对方:我的所有元素对你是开放的。这种 friend 是建立在灰常灰常灰常信任对方的基础上的。
4.普通函数做为类的一个友元函数
在类里声明一个普通函数,在前面加上 friend 修饰,那么这个函数就成了该类的友元。这时这个普通函数可以访问该类的一切成员。
#include <iostream >
using namespace std; class MyClass
{
public :
MyClass(string name)
{
m_name = name;
} //声明一个友元函数
friend void Display(MyClass &mycalss); protected:
string m_name;
}; //定义这个友元函数
//写成 void MyClass::Display(MyClass &mycalss)
void Display(MyClass &mycalss)
{
cout << "Access Protected data : "<< mycalss.m_name << endl;
} //测试
int main(int argc,char* argv[])
{
MyClass test("Class A"); Display(test); return ;
}
说明:
1. 声明这个友元函数可以在任何地方,可以在 public、protected 当然也可以在 privated 里。
2. 在这个友元函数里,你可以访问这个类里的所有的成员,所有的成员函数,而不管它是不是 public、protected 或 privated 的。
3. 定义友元函数时,不能写成 void MyClass::Display(MyClass &mycalss) 这点要注意。因为友元函数不是成员函数。
5. 一个普通函数可以是多个类的友元函数
在每个类里面都有一个友元函数的声明,声明可以有多个,但定义只能有一个。
#include <string>
#include <iostream >
using namespace std; class MyClass_B; class MyClass_A
{
public:
MyClass_A(string name)
{
m_name = name;
} //声明一个友元函数
friend void Display(MyClass_A &myA, MyClass_B &myB); private:
string m_name;
}; class MyClass_B
{
public:
MyClass_B(string name)
{
m_name = name;
} //注意,又声明一个友元函数
friend void Display(MyClass_A &myA, MyClass_B &myB); private:
string m_name;
}; //定义这个友元函数
void Display(MyClass_A &myA, MyClass_B &myB)
{
cout << "MyClass A : "<< myA.m_name << endl;
cout << "MyClass B : "<< myB.m_name << endl;
} //测试代码
int main(int argc,char* argv[])
{
MyClass_A testA("Class A");
MyClass_B testB("Class A"); Display(testA, testB);
system("pause");
return ;
}
6.一个类的成员函数也可以是另一个类的友元
//A 类
class MyClass_A
{
public:
MyClass_A(string name)
{
m_name = name;
} void Function(MyClass_B &myB); private:
string m_name;
}; //B 类
class MyClass_B
{
public:
MyClass_B(string name)
{
m_name = name;
} //友元函数声明,注意和普通函数的区别
friend void MyClass_A::Function(MyClass_B &myB); private:
string m_name;
}; //函数定义
void MyClass_A::Function(MyClass_B &myB)
{
cout<<myB.m_name<<endl;
} //测试代码
int main(int argc,char* argv[])
{
MyClass_A testA("Class A");
MyClass_B testB("Class B"); testA.Function(testB);
system("pause");
return ;
}
7. 整个类也可以是另一个类的友元
//类 A
class MyClass_B; class MyClass_A
{
public:
MyClass_A(string name)
{
m_name = name;
} //友元类声明
friend class MyClass_B; private:
string m_name;
}; //类 B
class MyClass_B
{
public:
MyClass_B(string name)
{
m_name = name;
} void Display(MyClass_A &myA); private:
string m_name;
}; //成员函数
void MyClass_B::Display(MyClass_A &myA)
{
cout<<myA.m_name<<endl; //访问A的私有成员 MyClass_A test("test"); cout<<test.m_name<<endl; //好像A的所有元素在B里都存在一样
} //测试代码
int main(int argc,char* argv[])
{
MyClass_A testA("Class A");
MyClass_B testB("Class B"); testB.Display(testA); return ;
}
详解C++ friend关键字的更多相关文章
- 转:DesiredCapabilities内容详解--Appium服务关键字
## Appium 服务关键字 <expand_table> |关键字|描述|实例| |----|-----------|-------| |`automationName`|你想使用的自 ...
- java基础回顾(五)线程详解以及synchronized关键字
本文将从线程的使用方式.源码.synchronized关键字的使用方式和陷阱以及一些例子展开java线程和synchronized关键字的内容. 一.线程的概念 线程就是程序中单独顺序的流控制.线程本 ...
- DesiredCapabilities内容详解--Appium服务关键字
上次了解了一些DesiredCapabilities的用法,有些还是不太清楚,去appium官网找了找官方文档,觉得写的很全: ## Appium 服务关键字 <expand_table> ...
- 【转载】C/C++中extern关键字详解
1 基本解释:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义.此外extern也可用来进行链接指定. 也就是说extern ...
- JS中this关键字详解
本文主要解释在JS里面this关键字的指向问题(在浏览器环境下). 阅读此文章,还需要心平气和的阅读完,相信一定会有所收获,我也会不定期的发布,分享一些文章,共同学习 首先,必须搞清楚在JS里面,函数 ...
- python关键字详解
今天依旧在啃:<笨方法学python>,其中习题37是复习各种关键字.我本想百度一下记一下就ok了,但是百度出来第一个就Hongten的博客.我才意识到我也有博客,我应该学习他,把这些积累 ...
- JS 中 this 关键字详解
本文主要解释在JS里面this关键字的指向问题(在浏览器环境下). 首先,必须搞清楚在JS里面,函数的几种调用方式: 普通函数调用 作为方法来调用 作为构造函数来调用 使用apply/call方法来调 ...
- ava下static关键字用法详解
Java下static关键字用法详解 本文章介绍了java下static关键字的用法,大部分内容摘自原作者,在此学习并分享给大家. Static关键字可以修饰什么? 从以下测试可以看出, static ...
- 详解js和jquery里的this关键字
详解js和jquery里的this关键字 js中的this 我们要记住:this永远指向函数运行时所在的对象!而不是函数被创建时所在的对象.this对象是在运行时基于函数的执行环境绑定的,在全局环境中 ...
随机推荐
- Android Http请求失败解决方法
1.MainActivity.java 文件中的onCreate方法改成如下: @SuppressLint("NewApi") @Override protected void o ...
- 关于cocopads 不能正确安装的问题
通过几个网页 我搜到 看着几个网页就够了 绝对可以实现的 http://code4app.com/article/cocoapods-install-usage http://www.cnblogs. ...
- BeanUtils--内省加强
BeanUtils就是一个处理Bean的工具包.内部也是使用内省.但对内省做了加强. Bean的set |get不用再成对出现 核心类: BeanUtils. 1.导包
- Spring静态属性注入
今天遇到一个工具类,需要静态注入一个属性,方法如下: 第一步:属性的set和get方法不要加static package cn.com.chinalife.ebusiness.common.util; ...
- CFont 字体类
CFont 字体类 初始化函数 CreateFontIndirect 初始化一个由LOGFONT结构给出其特征的CFont对象 CreateFont 初始化用指定特性定义的CFont对象 Create ...
- hadoop+spark+mongodb+mysql+c#
一.前言 从20世纪90年代数字化医院概念提出到至今的20多年时间,数字化医院(Digital Hospital)在国内各大医院飞速的普及推广发展,并取得骄人成绩.不但有数字化医院管理信息系统(HIS ...
- 转:Yelp开发团队发布内部网站设计指南
原文来自于:http://www.infoq.com/cn/news/2014/02/yelp-style-guide 近日,Yelp开发团队在博客发布消息:Yelp公开了内部网站设计指南.这份文档此 ...
- Spark Streaming Backpressure分析
1.为什么引入Backpressure 默认情况下,Spark Streaming通过Receiver以生产者生产数据的速率接收数据,计算过程中会出现batch processing time > ...
- C51 的重入问题 WARNING L15: MULTIPLE CALL TO SEGMENT
WARNING L15: MULTIPLE CALL TO SEGMENT 这个问题必须注意,可能引起程序冲突,假设你用于自动化领域,则可能导致信号产生尖峰. 产生这一警告的一个根源是:你在主循环里调 ...
- 单片机汇编语言实现DES加密算法
目前在金融界及非金融界的保密通信中,越来越多地用到了DES算法.DES(Data Encryption Standard)即数据加密算法,是IBM公司于 1977年研究成功并公开发表的.随着我国三金工 ...