曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 3459|回复: 0
打印 上一主题 下一主题

友元函数

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34387
跳转到指定楼层
楼主
发表于 2011-8-14 01:27:50 | 显示全部楼层 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 beyes 于 2013-9-30 17:59 编辑

一个函数被声明为一个类的友元函数,那么这个函数就可以访问这个类的私有成员,友元函数不是类的私有成员。声明友元函数的方法是:
将友员函数放在类声明的 public 部分,并在函数生面的前面加上 “friend" 关键字。如下样式所示:
[C++] 纯文本查看 复制代码
class c1 {
   //... ...
public:
friend void i_am_your_friend(c1 ob);
//... ...
};

一个函数可以同时是一个或多个类的友元,就如同一个人可以有多个朋友一样。

示例代码:
[C++] 纯文本查看 复制代码
#include <iostream>
using namespace std;

class myclass {
    int a;
    int b;
public:
    myclass(int i, int j) {a = i; b = j;}
    friend int sum(myclass x);    //sum 是myclass类的友员
};


int sum(myclass x)
{
    return x.a + x.b;
}

int main()
{
    myclass n(3, 4);

    cout << sum(n) << "\n";

    return 0;
}

运行输出:
$ ./class_friend
7

由上面程序中对 sum() 函数的定义可见,尽管 sum() 不是类 myclass 的成员函数,但它却可以完全访问类 myclass 的私有成员。
正是由于 sum() 不是类的成员函数,因此它也没必要通过使用对象的名字来调用---比如 myclass:sum() 这样的做法。

友员函数可以在两个或多个类中使用,在某些情况下,这能提高程序的效率。假设下面一种情况:

有两个类 A 和 B,在发生某些事件时,它们会分别在屏幕上弹出消息,而程序需要在屏幕上输出些什么内容时先要去检查屏幕上是否存在弹出的消息,如果检测到存在弹出消息,那么不会输出任何内容到屏幕,反之则允许输出内容到屏幕。这样一来,容易想到在 A 和 B 中各创建一个成员函数,它们分别负责检查各自的弹出消息情况。如果需要频繁的进行检测,那么要分别多次的调用 2 个函数,这种时间上的开销随着调用次数的而越发明显。但是,如果两个类同时拥有同一个友员函数,而这个函数能够同时检测到 A 和 B 对象弹出消息的情况,这样在每一次的检测中只调用了一次函数,这和每次调用 2 次函数理论上至少省了一半的时间。下面代码演示两个类对象共享同一个友员函数的情况:
[C++] 纯文本查看 复制代码
#include <iostream>
using namespace std;

const int IDLE = 0;    //屏幕上没有弹出消息标志
const int INUSE = 1;    //屏幕上有弹出消息标志

class C2;    //前向声明

class C1 {
    int status;
public:
    void set_status(int state);
    friend int idle(C1 a, C2 b);
};

class C2 {
    int status;
public:
    void set_status(int state);
    friend int idle(C1 a, C2 b);
};

void C1::set_status(int state)
{
    status = state;
}

void C2::set_status(int state)
{
    status = state;
}

//idle() 是类 C1 和 C2 的友员函数
int idle(C1 a, C2 b)
{
    if (a.status || b.status)    //如果屏幕上存在C1或C2弹出的消息则返回0
        return 0;
    else
        return 1;
}

int main()
{
    C1 x;
    C2 y;

    //屏幕此时可用
    x.set_status(IDLE);    
    y.set_status(IDLE);

    if (idle(x, y))
        cout << "Screen can be used.\n";
    else
        cout << "Screen can not be used.\n";

    x.set_status(INUSE);    //表示C1对象弹出消息


    if (idle(x, y))
        cout << "Screen can be used.\n";
    else
        cout << "Screen can not be used.\n";

    return 0;
}

运行输出:
$ ./friend
Screen can be used.
Screen can not be used.

程序中用了一个前向声明(也可以叫做前向引用),这个是必须的,因为在类 C1 中声明的函数 idle() 使用到了类 C2,而此时类 C2 还未声明。

另外,一个类的友元函数还可以是另一个类的成员函数。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-11-11 03:49 , Processed in 0.071640 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表