友元

  • 友元是一种允许非类成员函数访问类的非公有成员的一种机制。
  • 可以把一个函数指定为类的友元,也可以把整个类指定为另一个类的友元。
  1. 友元函数
  2. 友元类

  •  友元函数在类作用域外定义,但它需要在类体中进行说明
  • 为了与该类的成员函数加以区别,定义的方式是在类中用关键字friend说明该函数,格式如下:
    friend  类型 友元函数名(参数表);
  • 友元的作用在于提高程序的运行效率。

下面用程序来使用下友元:

#include <iostream>
using namespace std;

class Point {
    friend double distance(const Point& p1, const Point& p2);//声明友员函数
public:
    Point(int x, int y);
private:
    int x_;
    int y_;
};

Point::Point(int x, int y):x_(x), y_(y) {

}

int main(void) {
    return 0;
}

其中友员函数并不是类的成员函数,为了证明这点,我们先假设友员是成员函数,所以可以这样写:

编译一下:

友员的定义是在类体之外的,所以正确的实现友员函数的写法是去掉域访问修饰,如下:

既始在定义友元函数时在类体中实现实际上它也是在类体外:

下面来具体实现它,求两点之间的距离:

编译:

可见友元确实是可以访问类的私有变量,下面编写一下测试代码:

编译:

呃,这是啥子错,纠结了关天,最终发现是函数名的问题,可能是distance与系统函数重名了,所以需要修改一下,将首字母改为大写就OK了:

运行:

这就是友元使用的效果,在上面中说到“友元的作用在于提高程序的运行效率。”,何以见得呢?如果这个程序不用友元的话,则需要提供两个访问私有成员的函数,多了函数调用的开销。

  • 友元函数不是类的成员函数,在函数体中访问对象的成员,必须用对象名加运算符“.”加对象成员名。但友元函数可以访问类中的所有成员(公有的、私有的、保护的),一般函数只能访问类中的公有成员。
  • 友元函数不受类中的访问权限关键字限制,可以把它放在类的公有、私有、保护部分,但结果一样。
  • 某类的友元函数的作用域并非该类作用域。如果该友元函数是另一类的成员函数,则其作用域为另一类的作用域,否则与一般函数相同。
  • 友元函数破坏了面向对象程序设计类的封装性,所以友元函数如不是必须使用,则尽可能少用。或者用其他手段保证封装性。

  • 如果某类B的成员函数会频繁的存取另一个类A的数据成员, 而A的数据成员的Private/Protectd限制造成B存取的麻烦, B只能通过A的Public的成员函数进行间接存取。
  • 把B做成A类的友元类,即A类向B类开发其Private/Protectd内容, 让B直接存取。
  • 友元类:一个类可以作另一个类的友元。
  • 友元类的所有成员函数都是另一个类的友元函数。
  • 友元类的声名:
    friend class 类名;

 下面来编写一个摇控器控制电视机的例子来说明友元类的使用:

#include <iostream>
using namespace std;

//电视机
class Television {
public:
    Television(int volume, int chanel):volume_(volume),chanel_(chanel) {

    }
private:
    int volume_;//音量
    int chanel_;//频道
};

//摇控器
class TeleController {
public:
    void volumeUp(Television& tv) {
        tv.volume_ += 1;
    }

    void volumeDown(Television& tv) {
        tv.volume_ -= 1;
    }

    void chanelUp(Television& tv) {
        tv.chanel_ += 1;
    }

    void chanelDown(Television& tv) {
        tv.chanel_ -= 1;
    }
};

int main(void) {
    return 0;
}

编译:

那友元类派上用场了:

#include <iostream>
using namespace std;

//电视机
class Television {
    friend class TeleController;//将摇控器类声明为电视机的友员类,这样它的私有成员对于摇控器而言就全公开了
public:
    Television(int volume, int chanel):volume_(volume),chanel_(chanel) {

    }
private:
    int volume_;//音量
    int chanel_;//频道
};

//摇控器
class TeleController {
public:
    void volumeUp(Television& tv) {
        tv.volume_ += 1;
    }

    void volumeDown(Television& tv) {
        tv.volume_ -= 1;
    }

    void chanelUp(Television& tv) {
        tv.chanel_ += 1;
    }

    void chanelDown(Television& tv) {
        tv.chanel_ -= 1;
    }
};

int main(void) {
    return 0;
}

再次编译:

这时编写测试代码:

这里就不打印了,重在说明友元类的使用,电视机与遥控器类是写在一个cpp文件中,如果单独写在不同的cpp文件中会怎么呢?下面来看下:

 

Television.h:

#ifndef _TELEVISION_H_
#define _TELEVISION_H_

class Television
{
    friend class TeleController;
public:
    Television(int volume, int chanel);
private:
    int volume_;
    int chanel_;
};

#endif // _TELEVISION_H_

Television.cpp:

#include "Television.h"

Television::Television(int volume, int chanel) : volume_(volume), chanel_(chanel)
{

}

TeleController.h:

#ifndef  _TELE_CONTROLLER_H_
#define _TELE_CONTROLLER_H_

class TeleController
{
public:
    void VolumeUp(Television& tv);

    void VolumeDown(Television& tv);

    void ChanelUp(Television& tv);

    void ChanelDown(Television& tv);
};

#endif // _TELE_CONTROLLER_H_

TeleController.cpp:

#include "TeleController.h"

void TeleController::VolumeUp(Television& tv)
{
    tv.volume_ += 1;
}

void TeleController::VolumeDown(Television& tv)
{
    tv.volume_ -= 1;
}

void TeleController::ChanelUp(Television& tv)
{
    tv.chanel_ += 1;
}

void TeleController::ChanelDown(Television& tv)
{
    tv.volume_ -= 1;
}

02.cpp:

#include <iostream>
using namespace std;

int main(void) {
    return 0;
}

这时编译:

报错了,说明Television对于TeleController类在这种情况下是不可见的:

再次编译:

实际上遥控器头文件中的电视机引用也可以用前向声明来搞,修改代码如下:

再在具体实现中包含头文件既可:

修改之后再编译,依然好使,那这种前向声明它是有好外的:TeleController.h头文件会相对而言小一些,如果直接包含Television.h头文件,如果在多个文件中包含TeleController.h文件则文件会增大。

  • 友元关系是单向的
    A是B的友元类(在B类中有friend class A),并不代表B也是A的友元类。
  • 友元关系不能被传递
    A是B的友元类,B又是C的友元类,并不代表A是C的友元类。
  • 友元关系不能被继承
    A是B的友元类,C继承A,并不代表C是B的友元类。

转载于:https://www.cnblogs.com/webor2006/p/5247394.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值