C++超详细讲解友元的使用

 更新时间:2022年04月23日 09:18:12   作者:清风自在 流水潺潺  
采用类的机制后实现了数据的隐藏与封装,类的数据成员一般定义为私有成员,成员函数一般定义为公有的,依此提供类与外界间的通信接口。但是,有时需要定义一些函数,这些函数不是类的一部分,但又需要频繁地访问类的数据成员,这时可以将这些函数定义为该类的友元函数

一、友元的概念

  • 什么是友元?
  • 友元是 C++ 中的一种关系
  • 友元关系发生在函数与类之间或者类与类之间
  • 友元关系是单项的,不能传递

二、友元的用法

  • 在类中以 friend 关键字声明友元
  • 类的友元可以是其它类或者具体函数
  • 友元不是类的一部分
  • 友元不受类中访问级别的限制
  • 友元可以直接访问具体类的所有成员

三、友元的语法

在类中用 friend 关键字对函数或类进行声明

先看一个不使用友元的代码:

#include <stdio.h>
#include <math.h>
class Point
{
    double x;
    double y;
public:
    Point(double x, double y)
    {
        this->x = x;
        this->y = y;
    }
    double getX()
    {
        return x;
    }
    double getY()
    {
        return y;
    }
    //friend double func(Point& p1, Point& p2);
};
double func(Point& p1, Point& p2)
{
    double ret = 0;
    ret = (p2.getY() - p1.getY()) * (p2.getY() - p1.getY()) +
          (p2.getX() - p1.getX()) * (p2.getX() - p1.getX());
    ret = sqrt(ret);
    return ret;
}
int main()
{
    Point p1(1, 2);
    Point p2(10, 20);
    printf("p1(%f, %f)\n", p1.getX(), p1.getY());
    printf("p2(%f, %f)\n", p2.getX(), p2.getY());
    printf("|(p1, p2)| = %f\n", func(p1, p2));
    return 0;
}

输出结果如下:

这个程序在x 和 y中计算两点之间的距离时需要频繁访问私有成员 x 和 y,所以不得不调用getX() 和getY() 来访问x 和 y,x 和 y 函数中调用了 8 次getX() 和getY(),很麻烦。

这个时候,就该我们的友元上场了:

#include <stdio.h>
#include <math.h>
class Point
{
    double x;
    double y;
public:
    Point(double x, double y)
    {
        this->x = x;
        this->y = y;
    }
    double getX()
    {
        return x;
    }
    double getY()
    {
        return y;
    }
    friend double func(Point& p1, Point& p2);
};
double func(Point& p1, Point& p2)
{
    double ret = 0;
    ret = (p2.y - p1.y) * (p2.y - p1.y) +
          (p2.x - p1.x) * (p2.x - p1.x);
    ret = sqrt(ret);
    return ret;
}
int main()
{
    Point p1(1, 2);
    Point p2(10, 20);
    printf("p1(%f, %f)\n", p1.getX(), p1.getY());
    printf("p2(%f, %f)\n", p2.getX(), p2.getY());
    printf("|(p1, p2)| = %f\n", func(p1, p2));
    return 0;
}

输出结果如下:

四、友元的尴尬

  • 友元是为了兼顾 C 语言的高效而诞生的
  • 友元直接破坏了面向对象的封装性
  • 友元在实际产品中的高效是得不偿失的
  • 友元在现代软件工程中已经逐渐被遗弃

五、注意事项

  • 友元关系不具备传递性
  • 类的友元可以是其它类的成员函数
  • 类的友元可以是某个完整的类
  • 所有的成员函数都是友元

下面来深入分析一下友元:

#include <stdio.h>
class ClassC
{
    const char* n;
public:
    ClassC(const char* n)
    {
        this->n = n;
    }
    friend class ClassB;
};
class ClassB
{
    const char* n;
public:
    ClassB(const char* n)
    {
        this->n = n;
    }
    void getClassCName(ClassC& c)
    {
        printf("c.n = %s\n", c.n);
    }
    friend class ClassA;
};
class ClassA
{
    const char* n;
public:
    ClassA(const char* n)
    {
        this->n = n;
    }
    void getClassBName(ClassB& b)
    {
        printf("b.n = %s\n", b.n);
    }
    /*
    void getClassCName(ClassC& c)
    {
        printf("c.n = %s\n", c.n);
    }
    */
};
int main()
{
    ClassA A("A");
    ClassB B("B");
    ClassC C("C");
    A.getClassBName(B);
    B.getClassCName(C);
    return 0;
}

B 是 C 的友元,A 是 B 的友元,输出结果如下:

既然 A 可以访问 B,B 可以访问 C,那么 A 可以访问 C 么?把上面代码取消注释:

  void getClassCName(ClassC& c)
  {
        printf("c.n = %s\n", c.n);
  }

输出报错,这说明友元关系不具备传递性

六、小结

  • 友元是为了兼顾 C 语言的高效而诞生的
  • 友元直接破坏了面向对象的封装性
  • 友元关系不具备传递性
  • 类的友元可以是其它类的成员函数
  • 类的友元可以是某个完整的类

到此这篇关于C++超详细讲解友元的使用的文章就介绍到这了,更多相关C++友元内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言接口与实现方法实例详解

    C语言接口与实现方法实例详解

    这篇文章主要介绍了C语言接口与实现方法,包括接口的概念、实现方法及抽象数据类型等,并配合实例予以说明,需要的朋友可以参考下
    2014-09-09
  • C语言之选择分支语句详解

    C语言之选择分支语句详解

    大家好,本篇文章主要讲的是C语言之选择分支语句详解,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2021-12-12
  • C语言实现图的遍历之深度优先搜索实例

    C语言实现图的遍历之深度优先搜索实例

    这篇文章主要介绍了C语言实现图的遍历之深度优先搜索实例,采用不同的方法实现了深度优先搜索算法,有不错的借鉴价值,需要的朋友可以参考下
    2014-09-09
  • 基于Qt OpenCV的图像灰度化像素操作详解

    基于Qt OpenCV的图像灰度化像素操作详解

    这篇文章主要为大家详细介绍了基于Qt+OpenCV的图像灰度化像素操作:最大值法、平均法、加权平均值法,感兴趣的小伙伴可以了解一下
    2022-07-07
  • matlab鸟群算法求解车间调度问题详解及实现源码

    matlab鸟群算法求解车间调度问题详解及实现源码

    这篇文章主要为大家介绍了matlab鸟群算法求解车间调度的问题分析及实现源码,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2022-02-02
  • C++中的opeartor new和placement new使用步骤

    C++中的opeartor new和placement new使用步骤

    这篇文章主要介绍了C++中的opeartor new和placement new详解,在很多情况下,placement new的使用方法和其他普通的new有所不同。这里提供了它的使用步骤,需要的朋友可以参考下
    2022-10-10
  • 基于C语言实现迷宫游戏的示例代码

    基于C语言实现迷宫游戏的示例代码

    这篇文章主要介绍了基于C语言如何实现简单的迷宫游戏,对于学习游戏开发的朋友相信有一定的借鉴价值,需要的朋友可以参考下
    2022-05-05
  • Qt项目实战之实现多文本编辑器

    Qt项目实战之实现多文本编辑器

    这篇文章主要为大家详细介绍了如何利用Qt实现简易的多文本编辑器,文中的示例代码讲解详细,具有一定的参考价值,感兴趣的小伙伴可以了解一下
    2023-03-03
  • C语言实现学生选课系统

    C语言实现学生选课系统

    这篇文章主要为大家详细介绍了C语言实现学生选课系统,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-02-02
  • C++利用inotify+epoll实现异步文件监控的方法

    C++利用inotify+epoll实现异步文件监控的方法

    这篇文章讲给大家详细介绍一下C++利用inotify+epoll实现异步文件监控的方法,inotify是一种异步文件监控机制,文章通过代码示例介绍的非常详细,具有一定的参考价值,需要的朋友可以参考下
    2023-08-08

最新评论