原创博文,转载请标明出处--周学伟http://www.cnblogs.com/zxouxuewei/

有些情况下,允许特定的非成员函数访问一个类的私有成员,同时仍阻止一般的访问,这是很方便做到的。例如被重载的操作符,如输入或输出操作符,经常需要访问类的私有数据成员。

友元(frend)机制允许一个类将对其非公有成员的访问权授予指定的函数或者类,友元的声明以friend开始,它只能出现在类定义的内部,友元声明可以出现在类中的任何地方:

  友元不是授予友元关系的那个类的成员,所以它们不受其声明出现部分的访问控制影响。通常,将友元声明成组地放在类定义的开始或结尾是个好主意。

1普通函数友元函数

友元函数是指某些虽然不是类成员函数却能够访问类的所有成员的函数。类授予它的友元特别的访问权,这样该友元函数就能访问到类中的所有成员。

  目的:使普通函数能够访问类的友元

  声明: friend + 普通函数声明

  实现位置:可以在类外或类中

  实现代码:与普通函数相同

  调用:类似普通函数,直接调用

#include <iostream>  

using namespace std;  

class Atest
{
public:
Atest()
:value()
{}
~Atest(){}
private:
friend void function(Atest&);//该函数是友元函数的声明
int value;
static int sta_val;
}; void function(Atest& test)//友元函数定义,为了访问类Atest中的成员
{
cout <<"value is "<<test.value<<endl;
cout <<"static is "<<Atest::sta_val<<endl;
} int Atest::sta_val = ; int main(int argc, char const *argv[])
{
Atest struct_val; function(struct_val);
return ;
}

執行結果:

2Y的所有成员函数都为类X友元函数友元类

 友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。当希望一个类可以存取另一个类的私有成员时,可以将该类声明为另一类的友元类。

关于友元类的注意事项:

(1) 友元关系不能被继承。
(2) 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。
(3) 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明。 

目的:使用单个声明使Y类的所有函数成为类X的友元,它提供一种类之间合作的一种方式,使类Y的对象可以具有类X和类Y的功能。

  声明位置:公有私有均可,常写为私有(把类看成一个变量)

  声明: friend + class +类名;(不是对象哦)

#include <iostream>  

using namespace std;  

class Bstruct
{
public:
Bstruct()
:Bvalue(),name((char*)"ZHOU"){}
friend class Astruct;//这是友元类的声明
private:
int Bvalue;
char* name;
}; class Astruct//友元类定义,为了访问类Bstruct中的成员
{
public:
void function(Bstruct&);
}; void Astruct::function(Bstruct& str)
{
cout <<"Bvalue is "<<str.Bvalue<<", name is "<<str.name<<endl;
} int main(int argc, char const *argv[])
{
Astruct A;
Bstruct B; A.function(B); return ;
}

執行結果:

3。Y的一个成员函数为类X的友元函数

使类B中的成员函数成为类A的友元函数,这样类B的该成员函数就可以访问类A的所有成员了。

当用到友元成员函数时,需注意友元声明和友元定义之间的相互依赖,在该例子中,类B必须先定义,否则类A就不能将一个B的函数指定为友元。然而,只有在定义了类A之后,才能定义类B的该成员函数。

  更一般的讲,必须先定义包含成员函数的类,才能将成员函数设为友元。另一方面,不必预先声明类和非成员函数来将它们设为友元。

  目的:使类Y的一个成员函数成为类X的友元,具体而言:在类Y的这个成员函数中,借助参数X,可以直接以X的私有变量

  声明位置:声明在公有中 (本身为函数)

  声明:friend + 成员函数的声明

  调用:先定义Y的对象y---使用y调用自己的成员函数---自己的成员函数中使用了友元机制

#include <iostream>  

using namespace std;  

class Bstruct;//当用到友元成员函数时,需注意友元声明与友元定义之间的互相依赖。这是类Bstruct的声明 

class Astruct
{
public:
void function(Bstruct&);//该函数是类Bstruct的友元函数
}; class Bstruct
{
public:
Bstruct()
:Bvalue(),name((char*)"ZHOU"){}
friend void Astruct::function(Bstruct&);//该函数是友元成员函数的声明
int Bvalue;
char* name;
}; void Astruct::function(Bstruct& str)//只有在定义类Bstruct后才能定义该函数,毕竟,它被设为友元是为了访问类Bstruct的成员
{
cout <<"Bvalue is "<<str.Bvalue<<", name is "<<str.name<<endl;
} int main(int argc, char const *argv[])
{ Bstruct B;
Astruct A;
A.function(B); return ;
}

執行結果:

友元函数和类的成员函数的区别

1 成员函数有this指针,而友元函数没有this指针。

2 友元函数是不能被继承的,就像父亲的朋友未必是儿子的朋友。

  

c++友元函數---16的更多相关文章

  1. Oracle排序函數Rank

    出口給報關行出貨的時候,同一票shipment中合併多個invoice跟packing,轉出到廠商的報關系統時候,出口報關的序號會將invoice的序號做自動增加. 因為wafer會有出口給其他外包做 ...

  2. oracle decode(nvl(estimate_qty,0),0,1,estimate_qty) 函數

    oracle   decode(nvl(estimate_qty,0),0,1,estimate_qty) 函數

  3. js匿名函數

    (function($){})(jquery) == (function($){})(jQuery) 实际上是匿名函数 用于存放开发插件的代码 作用(非常有用): 这种写法的最大好处是形成闭包.在(f ...

  4. Math.Round函數

    Math.Round這個函數的解釋是將值按指定的小數位數舍入,但並不就是四捨五入.這種舍入有時稱為就近舍入或四舍六入五成雙 其實在 VB, VBScript, C#, J#, T-SQL 中 Roun ...

  5. C#判断奇偶数的函數

    // 现代流行的"程序员" public static bool IsOdd(int n) { while (true) { switch (n) { : return true; ...

  6. PHP 計算字符串長度函數

    PHP內置的字符串長度函數strlen無法正確處理中文字符串,它得到的只是字符串所占的字節數.對於GB2312的中文編碼,strlen得到的值是漢字個數的2倍,而對於UTF-8編碼的中文,就是3倍的差 ...

  7. SQL窗体函數一例

    需求: MSSQL,列出服務實例中全部數據庫的例如以下信息: 數據庫ID.數據庫名.創建日期.數據文件類型.數據文件大小.數據庫總大小.文件所在路徑. 寫法(後面的百分比為所花時間占比): -- 连接 ...

  8. js函數

    函數是什麼?函數就是被事件驅動或者調用執行的可重複的代碼塊. 函數聲明: 使用關鍵詞function,關鍵詞function大小敏感. function a{代碼塊} 局部變量: 在函數內部聲明的變量 ...

  9. concat函數 函數concat 可以用來合拼兩個或以上的字串。

    12. “Mexico 墨西哥”的首都是”Mexico City”. 顯示所有國家名字,其首都是國家名字加上”City”. concat函數 函數concat 可以用來合拼兩個或以上的字串. : SE ...

随机推荐

  1. Linux共享库 Linux内核链表

    #ifndef __LINKEDLIST_H_ #define __LINKEDLIST_H_ #include <stdlib.h> #define offsetof(type, mem ...

  2. C和C++的内存操作小贴士(一):const char*的内存释放问题

    C和C++的内存操作一直是困扰开发人员的老问题,基本概念相信老司机们都很清楚了,在这里就不做过多的描述了,只是把在实际开发中可能遇到的一些小问题的案例列举下,供大家参考.“C和C++的内存操作小贴士” ...

  3. c数据结构第一个公式写程序计算给定多项式在给定点x处的值

    假设x=2,那么a的数组有几个, 那n就是根据索引来的 假设数组[, , , , ] n就是0, 1, 2,,3, 4 f = + ( + ( + ( + ()))) f = + ( + ( + ( ...

  4. 00-01.PHP 网站假设win7配置自己的IIS服务器亲自做的图文很详细 [转 - 赞 ]

    win7配置自己的IIS服务器亲自做的图文很详细 分步阅读 跟人网站爱好初学者必看的win7系统配置自己的IIS,可以在你自己的电脑上配置网站服务器发不到网上,下面就跟着我的步骤一起做吧100%成功. ...

  5. 第三百四十二节,Python分布式爬虫打造搜索引擎Scrapy精讲—爬虫数据保存

    第三百四十二节,Python分布式爬虫打造搜索引擎Scrapy精讲—爬虫数据保存 注意:数据保存的操作都是在pipelines.py文件里操作的 将数据保存为json文件 spider是一个信号检测 ...

  6. visual studio运行时库MT、MTd、MD、MDd 的区别

    msdn上面的解释: MT:mutithread,多线程库,编译器会从运行时库里面选择多线程静态连接库来解释程序中的代码,即连接LIBCMT.lib库 MTd:mutithread+debug,多线程 ...

  7. Git -- 工作区 和 暂存区

    Git和其他版本控制系统如SVN的一个不同之处就是有暂存区的概念. 先来看名词解释. 工作区(Working Directory) 就是你在电脑里能看到的目录,比如我的learngit文件夹就是一个工 ...

  8. (弃) Keystone CLI_选项与子命令概况

    本文档介绍icehouse发行版keystone命令 keystone Command-Line Interface (CLI)提供用于和keystone服务器交互的方便工具,但是该命令行工具逐渐受到 ...

  9. java EE 环境配置(JDK + Tomcat + Eclipse for java EE)

    这学期的课程多数都是java语言的,像Java Web程序设计,java课程设计案例,所以趁周末先把软件,环境配置好. 下载JDK 先给上下载链接:http://www.oracle.com/tech ...

  10. List转DataTable(反射) ; 将泛型集合类转换成DataTable ; 将集合类转换成DataTable

    public class ConvertX { #region 将集合类转换成DataTable /// <summary> /// 将集合类转换成DataTable /// </s ...