详解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 Studio中新建项目时Your android sdk is out of date or is missing templates的解决办法
在Android Studio中新建项目时出现了以下问题:Your android sdk is out of date or is missing templates. Please ensure ...
- Lua 基础知识-面向对象
通过函数闭包的方式来实现面向对象 -- 通过函数闭包的方式来实现面向对象 function People(name) local self = {} local function init() sel ...
- PHP 函数的引用传递
$a = "nowamagic";$b =& $a;echo $b.$a; 这意味着 $a 和 $b 指向了同一个变量.同一个变量内容有不同的变量名,引用就是这么个回事. ...
- Secure CRT 如何连接虚拟机里面的CentOS系统——当主机使用无线网的时候 作者原创 欢迎转载
第一步:设置自己的无线网,并且分享给VM8这个虚拟网卡 第二步:查看VM8网卡的IP地址,如图是192.168.137.1 第三步:设置虚拟机的配置:选择VM8网卡并且是NAT的 第四步:设置虚拟机里 ...
- Javascript 中神奇的 this
Javascript 当中的 this 与其他语言是完全不同的机制,很有可能会让一些编写其他语言的工程师迷惑. 1. 误以为 this 指向函数自身 根据 this 的英语语法,很容易将函数中出现的 ...
- ASP.NET常用技术之Cookie
cookie是一小段的文本信息(多数浏览器限制cookie最大字节数为4096字节),在浏览器和服务器之间随用户请求而传递(用户访问网站,没有设置cookie限制范围情况下,无论请求那个页面,浏览器和 ...
- RBAC角色权限设计思路
1 设计思路 为了设计一套具有较强可扩展性的用户认证管理,需要建立用户.角色和权限等数据库表,并且建立之间的关系,具体实现如下. 1.1 用户 用户仅仅是纯粹的用户,用来记录用户相关信息,如用户名.密 ...
- PHPCMSv9 更改后台地址(测试)
最新发布的PHPCMS V9由于采用了MVC的设计模式,所以它的后台访问地址是固定的,虽然可以通过修改路由配置文件来实现修改,但每次都修改路由配置文件对于我来说有点麻烦了,而且一不小心就会出错.这里使 ...
- JQuery连接地址
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script> http://co ...
- Python自动化运维之9、模块之sys、os、hashlib、random、time&datetime、logging、subprocess
python模块 用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来,可能需 ...