C++——奔放的友元

奔放的友元

C++中采用类的机制后实现了数据的隐藏与封装, 类的数据成员一般定义为私有成员, 成员函数一般定义为公有的。依此提供类与外界间的通信接口。但是, 有时需要定义一些函数, 这些函数不是类的一部分, 但又需要频繁地访问类的数据成员, 这时可以将这些函数定义为该类的友元函数。

除了友元函数外, 还有友元类, 两者统称为友元。

友元的作用是提高了程序的运行效率(即减少了类型和安全性检查及调用的时间开销), 但它破坏了类的封装性和隐藏性, 使得非成员函数可以访问类的私有成员。
 

0、两点特性

(1)同类之间无私处

         一个类可以访问本类所有对象的私有成员。(同族类的对象之间没有隐私,所有数据皆可访问)

(2)异类之间有友元

         友元打破了外部访问类中的 private 私有数据成员的权限。友元内没有this指针,所有数据得通过对象来访问。

1、友元函数

全局函数作友元函数。

友元函数(全局函数):求两点之间的距离

class Point
{
public:
    Point(double a, double b)
        :x(a),y(b){} //构造 输入一个点的横纵坐标

    friend double dis (Point t1,Point t2);  //全局友元函数声明
private:
    double x,y;
};

double dis (Point & t1,Point & t2)  //函数体 
//定义为友元函数之后 dis函数可以通过Point的对象访问Point的私有数据。
{ 
    double dx = t1.x - t2.x;
    double dy = t1.y - t2.y;
    return sqrt(dx*dx+dy*dy);
}

int main()
{
    Point t1(0,0);
    Point t2(3,4);
    double r = dis(t1,t2);
    cout<<r<<endl;
    return 0;
}

成员函数作友元函数

两个类的成员函数或用到的数据会交叉,所以声明也是个问题。

前向声明, 是一种不完全型声明, 即只需提供类名(无需提供类实现)即可。 

友元:前向声明 只能限用于 指针或引用。

#include <iostream>
#include <math.h>

using namespace std;
//友元函数:求两点之间的距离

class Point; //前向声明 解决 class pointManagement 里边应用的Point 引用。

class pointManagement
{
public:
    double dis (Point &t1,Point &t2);
    //其函数体 因为用到了Ponit的数据 so放在 class Ponit 后边
};

class Point
{
public:
    Point(double a, double b)
        :x(a),y(b){} //构造 输入一个点的横纵坐标
    friend double pointManagement::dis(Point & t1,Point & t2);//用谁的数据在谁里边声明友元函数
private:
    double x,y;
};

double pointManagement:: dis (Point &t1,Point &t2) //求两点距离
{
    double dx = t1.x - t2.x;
    double dy = t1.y - t2.y;
    return sqrt(dx*dx+dy*dy);
}

int main()
{
    Point t1(0,0);
    Point t2(3,4);
    pointManagement pm;
    
    double r = pm.dis(t1,t2); //通过对象去访问
    cout<<r<<endl;
    return 0;
}

2、友元类

当希望一个类中所有成员函数, 均可存取另一个类的私有成员时, 方便起见,可以将该类声明为另一类的友元类。

友元类, 使异类之间的成员函数访问数据更加简单,也就是将所有的友元类的成员函数及私有成员公开化了。方便操作(不用多次声明&调用了)。但是会导致封装破坏的面积扩大化。

把a声明为b的友元,就可以通过b的变量访问b的 private 数据成员。

如下: 把pm声明为p的友元,就可以在pm的类里 通过p的变量访问p的私有数据成员。(通过谁的对象去访问)

#include <iostream>
#include <math.h>

using namespace std;
class Point
{
    friend class PointManagement;// 声明友元类
public:
    Point(double a, double b)
        :x(a),y(b){} //构造 输入一个点的横纵坐标
private:
    double x,y;
};


class PointManagement
{

public:
    double getDistance (Point &t1,Point &t2)
    {
        double dx = t1.x - t2.x;
        double dy = t1.y - t2.y;
        return sqrt(dx*dx+dy*dy);
    }
};


int main ()
{
    Point t1(0,0),t2(3,4);

    PointManagement pm;
    double r = pm.getDistance(t1,t2);
    cout<<r<<endl;
}

友元利弊:

友元不是类成员,但是它可以通过对象访问类中的私有成员。 友元的作用在于提高程序的运行效率, 但是它破坏了类的封装性和隐藏性, 使得非成员函数可以访问类的私有成员。-->友元是使对类的更加自由奔放的做法。

 

注意:

友元关系不能被继承。

单向性、不可交换性、 不可传递性。

//友元关系是单向的,不具有交换性。若类 B 是类 A 的友元,类 A 不一定是类 B的友元,要看在类中是否有相应的声明。

//友元关系不具有传递性。若类 B 是类 A 的友元,类 C 是 B 的友元,类 C 不一定是类 A 的友元,同样要看类中是否有相应的声明。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值