友元(友元函数、友元类和友元成员函数) C++

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

友元(friend)机制允许一个类将对其非公有成员的访问权授予指定的函数或者类,友元的声明以friend开始,它只能出现在类定义的内部,友元声明可以出现在类中的任何地方:友元不是授予友元关系的那个类的成员,所以它们不受其声明出现部分的访问控制影响。通常,将友元声明成组地放在类定义的开始或结尾是个好主意。

1、友元函数

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

#include <iostream>

using namespace std;

class A
{
public:
friend void set_show(int x, A &a); //该函数是友元函数的声明
private:
int data;
}; void set_show(int x, A &a) //友元函数定义,为了访问类A中的成员
{
a.data = x;
cout << a.data << endl;
}
int main(void)
{
class A a; set_show(1, a); return 0;
}

2、友元类

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

关于友元类的注意事项:

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

#include <iostream>

using namespace std;

class A
{
public:
friend class C; //这是友元类的声明
private:
int data;
}; class C //友元类定义,为了访问类A中的成员
{
public:
void set_show(int x, A &a) { a.data = x; cout<<a.data<<endl;}
}; int main(void)
{
class A a;
class C c; c.set_show(1, a); return 0;
}

3、友元成员函数

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

当用到友元成员函数时,需注意友元声明和友元定义之间的相互依赖,在该例子中,类B必须先定义,否则类A就不能将一个B的函数指定为友元。然而,只有在定义了类A之后,才能定义类B的该成员函数。更一般的讲,必须先定义包含成员函数的类,才能将成员函数设为友元。另一方面,不必预先声明类和非成员函数来将它们设为友元。

#include <iostream>

using namespace std;

class A;    //当用到友元成员函数时,需注意友元声明与友元定义之间的互相依赖。这是类A的声明
class B
{
public:
void set_show(int x, A &a); //该函数是类A的友元函数
}; class A
{
public:
friend void B::set_show(int x, A &a); //该函数是友元成员函数的声明
private:
int data;
void show() { cout << data << endl; }
}; void B::set_show(int x, A &a) //只有在定义类A后才能定义该函数,毕竟,它被设为友元是为了访问类A的成员
{
a.data = x;
cout << a.data << endl;
} int main(void)
{
class A a;
class B b; b.set_show(1, a); return 0;
}

友元小结:

在需要允许某些特定的非成员函数访问一个类的私有成员(及受保护成员),而同时仍阻止一般的访问的情况下,友元是可用的。

优点:

可以灵活地实现需要访问若干类的私有或受保护的成员才能完成的任务;

便于与其他不支持类概念的语言(如C语言、汇编等)进行混合编程;

通过使用友元函数重载可以更自然地使用C++语言的IO流库。

缺点:

一个类将对其非公有成员的访问权限授予其他函数或者类,会破坏该类的封装性,降低该类的可靠性和可维护性。

参考资料:

1、《C++ Prime》第4版 第12章类的友元小节

http://blog.csdn.net/u012796139/article/details/46404401

C++友元(友元函数、友元类和友元成员函数)的更多相关文章

  1. C++类的成员函数(在类外定义成员函数、inline成员函数)

    类的成员函数(简称类函数)是函数的一种,它的用法和作用和前面介绍过的函数基本上是一样的,它也有返回值和函数类型,它与一般函数的区别只是:它是属于一个类的成员,出现在类体中.它可以被指定为private ...

  2. 类1(this指针/const成员函数/类作用域/外部成员函数/返回this对象的函数)

    假设我们要设计一个包含以下操作的 Sales_data 类: 1.一个 isbn 成员函数,用于返回对象的 book_no 成员变量 2.一个 combine 成员函数,用于将一个 Sales_dat ...

  3. CDocument类的UpdateAllViews()成员函数

    (一)UpdateAllViews() 与 Invalidate()的区别 UpdateAllViews()是在DOC/VIEW结构中,当一个视图的数据改变后,通知所有视图作相应的改变,和重画毫无关系 ...

  4. C++类的const成员函数、默认的构造函数、复制形参调用函数(转)

    C++类的const成员函数 double Sales_item::avg_price() const { } const关键字表明这是一个const成员函数,它不可以修改Sales_item类的成员 ...

  5. C++模板编程中只特化模板类的一个成员函数

    模板编程中如果要特化或偏特化(局部特化)一个类模板,需要特化该类模板的所有成员函数.类模板中大多数成员函数的功能可能是一模一样的,特化时我们可能只需要重新实现1.2个成员函数即可.在这种情况下,如果全 ...

  6. c++友元函数、友元类、友成员函数

    友元函数:不是类成员函数,是一个类外的函数,但是可以访问类所有成员. class Point{ public: friend void fun(Point t);//友元函数 private: int ...

  7. C++(十六) — 类中引用成员函数、命名空间的使用

    1.为什么类中引用成员函数? 类将属性和方法做了封装.类是一种数据类型,也就是:固定大小内存块的别名. 类的定义是一个抽象的概念,定义时不分配内存,当用类定义对象时,才分配一个固定大小的内存块. 此时 ...

  8. 为什么通过空指针(NULL)能够正确调用类的部分成员函数

    #include <iostream> using namespace std; class B { public: void foo() { cout << "B ...

  9. C++模板编程中只特化模板类的一个成员函数(花样特化一个成员函数)

    转自:https://www.cnblogs.com/zhoug2020/p/6581477.html 模板编程中如果要特化或偏特化(局部特化)一个类模板,需要特化该类模板的所有成员函数.类模板中大多 ...

  10. MFC 添加C++类,别的类不通过C++类的定义的对象就可以直接调用C++类里面的成员函数;

    MFC 添加C++类,不用定义C++类的对象,别的类不通过C++类的定义的对象就可以直接调用C++类里面的成员函数: 1先在mfc程序中添加普通类CProdata,然后删除头文件Prodata.h里面 ...

随机推荐

  1. Mysql 日志文件类型

    简介: Mysql 中提供了多种类型的日志文件,分别反映 Mysql 的不同信息,了解它们很有必要. 1.Error log ( 错误日志 ) 错误日志记录了 Mysql Server 运行过程中所有 ...

  2. <转>Linux 环境进程间通信(六)

    http://www.ibm.com/developerworks/cn/linux/l-ipc/part6/ 一个套接口可以看作是进程间通信的端点(endpoint),每个套接口的名字都是唯一的(唯 ...

  3. PHP中使用CURL模拟文件上传实例

    调用实例: 该方法将本地的E盘文件test.doc上传到接口服务器上的 uploadFile方法中,uploadFile会对上传的文件做进一步处理. 若你想自己对上传的文件做操作,将接口uploadF ...

  4. Kafka核心概念(转)

    转自:https://blog.csdn.net/liyiming2017/article/details/82805479 1.Kafka集群结构 实际上kafka的结构图是有些区别的,现在我们看下 ...

  5. fedora 16 yum yuan

    暑假买了几本Linux的书一直放在书架上没看,周末闲着没事就拿起本<LinuxC从入门到精通>看了起来,初学Linux首先要做的便是在电脑上安装Linux系统.于是按书上的要求下载了Fed ...

  6. 【HDU4734】F(x) 【数位dp】

    题意 先定义了一个函数F(X)=An*2^n-1+An-1*2^n-2+.....+A1*1.其中Ai为X的第i位的值.对于每组数据给出了两个整数A,B.问不超过B的数中有多少的F值是不超过F(A)的 ...

  7. Item2的使用

    网址:http://wulfric.me/2015/08/iterm2/ 巧用 Command 键 按住⌘键: 可以拖拽选中的字符串: 点击 url:调用默认浏览器访问该网址: 点击文件:调用默认程序 ...

  8. 825. Friends Of Appropriate Ages有效的好友请求的数量

    [抄题]: Some people will make friend requests. The list of their ages is given and ages[i] is the age ...

  9. kubernetes基础环境配置

    一.基础环境配置 环境详情 主机名(FQDN) IP地址(NAT) 描述 linux-node1.example.com eth0:192.168.56.11 1VCPU.2G内存.一块硬盘s da5 ...

  10. Openssl enc命令

    一.简介 enc - 对称加密例程,使用对称密钥对数据进行加解密,特点是速度快,能对大量数据进行处理.算法有流算法和分组加密算法,流算法是逐字节加,由于其容易被破译,现在已很少使用:分组加密算法是将数 ...