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

4人阅读 评论(0) 收藏 举报
分类:

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

        友元(frend)机制允许一个类将对其非公有成员的访问权授予指定的函数或者类,友元的声明以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) 友元关系不能被继承。 (2) 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。 (3)...
  • rl529014
  • rl529014
  • 2016-07-17 22:40:42
  • 1018

C++总结 ----- 友元类和友元函数(1)

《windows环境多线程编程原理与应用》中解释:  如果将类的封装比喻成一堵墙的话,那么友元机制就像墙上了开了一个门,那些得  到允许的类或函数允许通过这个门访问一般的类或者函数无法访问的私有属性和...
  • zhy05
  • zhy05
  • 2007-09-16 15:52:00
  • 1948

C++的“友元类”的一个使用场景

我遇到了“必须使用友元类”的一个场景。 我遇到了A中有B,B中有A的场景。 貌似“A的一个函数,作为B的友元函数”这个需求无法被实现。 #include class MyApiCls; cla...
  • u013600225
  • u013600225
  • 2016-03-08 17:32:12
  • 1046

C++中如何声明 “友元类” 和 “友元函数”

调试平台:win7 vs2012 win32控制台终端项目 友元(friend) 字面义:顾名思义既然是朋友了,我的东西同样可以给你使用 书面语:将一个类的非公有成员(包括方法和成员变量)的访问权限赋...
  • comwise
  • comwise
  • 2013-11-05 18:57:32
  • 3165

一个类的成员作为另一个类的友元函数

普通成员函数作为一个类的友元函数,以及一个类作为另一个类的友元类,都好...
  • jw903
  • jw903
  • 2014-08-27 08:59:52
  • 1710

C++友元类使用之前置声明(定义变量)

今天项目使用到了友元类,于是便先试着搞个简单地使用例子 #include class b; class a { private: int value; protected: void funprote...
  • LYS_SONG
  • LYS_SONG
  • 2016-09-29 10:23:33
  • 1019

VS2013跟友元有仇

本文写了友元函数,友元成员和友元类。 所有的访问其他类的友元函数,必须在被访问的类之后定义,这一点是在VS上出现的,貌似g++不是这样的。Mark下,不然自己写的时候很困惑! #inc...
  • u014338577
  • u014338577
  • 2015-09-05 21:02:30
  • 551

C++访问类的私有成员变量的方法(友元函数、友元类)

// win32Test.cpp : Defines the entry point for the console application. // #include "stdafx.h" class...
  • libaineu2004
  • libaineu2004
  • 2014-03-06 11:28:38
  • 9507

c++之派生类访问基类的友元函数

学过c++的都知道派生类是不继承基类的友元函数的,但是有时候我们还是需要访问基类的友元函数的,这样看来好像是没有什么办法了。但是c++中可以使用显式类型转化来访问。下面是写的一个测试程序 程序如下:...
  • guoqianqian5812
  • guoqianqian5812
  • 2016-03-31 13:45:07
  • 1041

“friend声明友元函数,友元函数却依旧无法访问该类的私有属性”的解决方法

背景:这次是一次C++作业题,很诡异,搞了很久弄明白了,虽然成功了,但VS2015依旧有红线提示错误,不过不影响编译、运行。 解决: 友元类方法总结:1、包含声明”friend”的类,必须在((包...
  • qq_32897957
  • qq_32897957
  • 2016-12-01 22:28:40
  • 1350
    个人资料
    等级:
    访问量: 2663
    积分: 142
    排名: 113万+
    文章分类