C++面向对象(OOP)编程-友元(友元函数和友元类)

本文主要介绍面向对象编程的友元的使用,以及友元的特性和分类,提供C++代码。

1 为什么引进友元

        面向对象编程(OOP)的三大特性中的封装,是通过类实现对数据的隐藏和封装。一般定义类的成员变量为私有成员,成员函数为公有函数,通过公有函数作为类的接口实现与外部交互。一些情况下,类外的某些函数需要频繁访问类的成员变量,因此引入了友元的概念,将类外的函数定义为该类的友元函数,从而实现对该类私有成员的访问。由此,还引入友元类,就是一个类是另一个类的友元类,友元类可以访问另一个类的所有成员。友元函数和友元类称为友元。

        友元的作用是提高了程序的运行效率(减少了类型检查和安全检查的耗时),但是友元破坏了类的封装和隐藏性,让非类成员函数可以类的私有成员。 

        友元是C++语言中的一种关系,友元关系发生在函数与类之间或者类与类之间。友元关系是单向的,不能传递。

        与类有友元关系的函数称为友元函数,与类有友元关系的类称为友元类。

2 友元的性质

        (1)在被访问类中以friend关键字修饰友元类或者友元函数

        (2)友元不属于该类,且不受该类的访问限制,可以直接访问具体类的所有成员

        (3)友元关系不能被继承

        (4)友元关系是单向的,不具有交换性,只能是一个函数访问一个类的所有成员,或者一个类允许访问另一个类的所有成员,反之不行

        (5)友元关系不具有传递性

3 友元的本质

        友元的本质是提供不属于该类成员,包括全局函数、其他类的成员函数、其他类,访问本类所有成员和成员属性的属性。

4 友元分类

4.1 全局函数为友元函数

        全局函数拥有访问一个类所有成员的能力,需要在被访问类中用关键字friend声明f被访问类的友元函数。一个类可以拥有多个友元函数。一个函数也可以是多个类的友元函数。

代码如下:

#include <iostream>
#include <string>
using namespace std;

class A
{
    private:
        string name_;
        int age_;
    public:
        A(const string name,const int age) : name_(name), age_(age) {cout << "A构造函数 初始化参数" << endl;};
        virtual ~A()
        {
            cout << "A析构函数 " << endl;
        }
        void func()
        {
            std::cout << "A's func()" << std::endl;
        }

        
        friend void get_members_global(A & a);  // 友元全局函数,可以访问A的私有成员变量和所有的公有成员
        
};

// 全局函数作为友元函数
void get_members_global(A & a)
{
    cout << a.name_ << " is " << a.age_ << " years old " << endl;
    a.func();
}


int main()
{
    A a("Hubery",45);

    cout << "***************************全局函数作为友元函数***************************" << endl;

    get_members_global(a);

    return 0;
}

运行结果:

4.2 类的成员函数为友元函数

        类成员函数作为类的友元声明时只需在友元的名称前加上关键字friend,其格式如下:

friend 类型 类名::函数名(形式参数);

一个函数可以是多个类的友元函数,只需要在各个类中分别声明。

代码如下:

#include <iostream>
#include <string>
using namespace std;

class A;

class C
{
    public:
        //类的成员函数作为友元函数
        void get_members_member(A &a);
        C()
        {
            cout << "C构造函数" << endl;
        }
        ~C()
        {
            cout << "C析构函数" << endl;
        }
};

class A
{
    private:
        string name_;
        int age_;
    public:
        A(const string name,const int age) : name_(name), age_(age) {cout << "A构造函数 初始化参数" << endl;};
        virtual ~A()
        {
            cout << "A析构函数 " << endl;
        }
        void func()
        {
            std::cout << "A's func()" << std::endl;
        }

        friend void C::get_members_member(A &a); // C的成员函数做友元函数,可以访问所有成员
        
};

// 类的成员函数作为友元函数
void C::get_members_member(A &a)
{
    cout << a.name_ << " is " << a.age_ << " years old " << endl;
    a.func();
}

int main()
{
    A a("Hubery",45);
    C c;

    cout << "***************************类的成员函数作为友元函数***************************" << endl;

    c.get_members_member(a);

    return 0;
}

运行结果:

这里用到类的前向声明。前向声明,是一种不完全型(forward declaration)声明,即只需提供类名(无需提供类实现)即可。前向声明功能有限:
        (1)不能定义类的对象。
      (2)可以用于定义指向这个类型的指针或引用。
      (3)用于声明(不是定义)使用该类型作为形参或者返回类型的函数。

4.3 类作为友元

        友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。当希望一个类可以访问另一个类的私有成员、保护成员时,可以将该类声明为另一类的友元类。

定义友元类的语句格式如下:

friend class 类名;
friend和class是关键字,类名必须是程序中的一个已定义的类。

代码如下:

#include <iostream>
#include <string>
using namespace std;

class B; // 前向声明

class A
{
    private:
        string name_;
        int age_;
    public:
        A(const string name,const int age) : name_(name), age_(age) {cout << "A构造函数 初始化参数" << endl;};
        virtual ~A()
        {
            cout << "A析构函数 " << endl;
        }
        void func()
        {
            std::cout << "A's func()" << std::endl;
        }
        friend class B; // 声明B为A的友元类,B中成员函数可以访问A中所有的成员
        
};

class B
{
    private:
        string name_;
        int age_;
    public:
        B(const string name,const int age) : name_(name), age_(age) {cout << "B构造函数 初始化参数" << endl;};
        virtual ~B()
        {
            cout << "B析构函数 " << endl;
        }
        void func()
        {
            std::cout << "B's func()" << std::endl;
        };
        // 友元类
        void get_members_class(A & a)
        {
            cout << a.name_ << " is " << a.age_ << " years old " << endl;
            a.func();
        };

};


int main()
{
    A a("Hubery",45);
    B b("Tom",24);

    cout << "***************************友元类***************************" << endl;
    b.get_members_class(a);

    return 0;
}

运行结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/243510.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

虚拟机/etc/fstab 变更只读模式ready-only处理

虚拟机误操作将/etc/fstab中的根目录注释掉了&#xff0c;重启虚机后虚机可以正常启动&#xff0c;但无法进行修改 # vi /etc/fstab 提示文件只读 无法进行操作 解决办法&#xff1a; 1、重启虚机&#xff0c;按e进入单用户模式 2、修改内核所在那行参数&#xff0c;将ro 修…

什么是FPGA原型验证?

EDA工具的使用主要分为设计、验证和制造三大类。验证工作贯穿整个芯片设计流程&#xff0c;可以说芯片的验证阶段占据了整个芯片开发的大部分时间。从芯片需求定义、功能设计开发到物理实现制造&#xff0c;每个环节都需要进行大量的验证。 现如今验证方法也越来越多&#xff…

力扣题:数字与字符串间转换-12.14

力扣题-12.14 [力扣刷题攻略] Re&#xff1a;从零开始的力扣刷题生活 力扣题1&#xff1a;442. 数组中重复的数据 解题思想&#xff1a;从字符串中能够正确提取数字即可 class Solution(object):def complexNumberMultiply(self, num1, num2):""":type num1:…

科技提升安全,基于YOLOv8全系列模型【n/s/m/l/x】开发构建商超扶梯场景下行人安全行为姿态检测识别系统

在商超等人流量较为密集的场景下经常会报道出现一些行人在扶梯上摔倒、受伤等问题&#xff0c;随着AI技术的快速发展与不断普及&#xff0c;越来越多的商超、地铁等场景开始加装专用的安全检测预警系统&#xff0c;核心工作原理即使AI模型与摄像头图像视频流的实时计算&#xf…

Flutter常用命令

一、环境安装 flutter --version 查看当前安装的flutter 版本 flutter upgrade 升级当前的flutter 版本 flutter doctor 检查环境安装是否完成 二、项目编译运行 flutter clean 清空build目录 flutter pub get 获取pub插件包 flutter run --设备名称 运行项目到指定设…

linux 内核同步互斥技术之原子变量

原子变量用来实现对整数的互斥访问&#xff0c;通常用来实现计数器。 例如&#xff0c;我们写一行代码把变量 a 加 1&#xff0c;编译器把代码编译成 3 条汇编指令。 &#xff08;1&#xff09;把变量 a 从内存加载到寄存器。 &#xff08;2&#xff09;把寄存器的值加 1。 &am…

CSDN新增的代码分析 一键注释新技能

一键注释 贴段Django代码 from django.urls import reversedef my_view(request):url reverse(index)return redirect(url) 贴段Vue代码 <template><div id"app"><input v-model.lazy"msg" type"text" name"" &g…

05.CSS前言

CSS前言 1.CSS产生背景 从 HTML 被发明开始&#xff0c;样式就以各种形式存在&#xff0c;最初的 HTML 只包含很少的显示属性随着 HTML 的成长&#xff0c;为了满足页面设计者的要求&#xff0c;HTML 添加了很多显示功能&#xff0c;例如文本格式化标签但是随着这些功能的增加…

Linux系统调用接口---使用write函数写文件

Linux系统调用接口—使用write函数写文件 1 wirte函数介绍 我们打开了一个文件&#xff0c;可以使用write函数往该文件中写入数据。当我们往该文件中写入N个字节数据&#xff0c;位置pos会从0变为N&#xff0c;当我们再次往该文件中写入M个字节数据&#xff0c;位置会变为NM。…

【沐风老师】科研绘图3DMAX病毒建模教程

3dMax在科研绘图方面也有广泛的应用&#xff0c;本教程就给大家讲解病毒的建模方法&#xff0c;下面直接进入教程&#xff1a; 3dMax病毒建模方法&#xff1a; 1.启动3dMax&#xff0c;在视口中创建一个“几何球体”。方法&#xff1a;右边命令面板->创建->几何体->…

IDEA对@Author、@Date 标签等的黄色警告问题

配置路径 seting --> Editor -->Inspections --> Java --> Javadoc -->Declaration has Javadoc problems设置--> 编辑器-->检查--> Java --> Javadoc -->javadoc声明问题-->附加javadoc标记参数 ,Author,Date

前端已死?探讨人工智能与低代码对前端的影响

文章目录 每日一句正能量前言前端行业究竟是好是坏&#xff1f;数字化转型的当下前端工程师该何去何从&#xff1f; 想要入行前端先认清这三个事实 后记 每日一句正能量 人的结构就是相互支撑&#xff0c;众人的事业需要每个人的参与。 前言 随着人工智能和低代码的崛起&#…

【Canvas】绘制风速热力图

前言 &#x1f4eb; 大家好&#xff0c;我是南木元元&#xff0c;热衷分享有趣实用的文章&#xff0c;希望大家多多支持&#xff0c;一起进步&#xff01; &#x1f345; 个人主页&#xff1a;南木元元 目录 风速热力图 前期工作 数据准备 数据稀疏问题 双线性插值 绘制色…

关于pytorch中的dim的理解

今天碰到一个代码看起来很简单&#xff0c;但是细究原理又感觉好像不太通不太对劲&#xff0c;就是多维tensor数据的操作&#xff0c;比如&#xff1a;y.sum(dim2)&#xff0c;乍一看很简单数据相加操作&#xff0c;但是仔细一想&#xff0c;这里在第3维度的数据到底是横向相加…

什么是前端开发中的跨站请求伪造(CSRF)攻击?如何防止它?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

dell 恢复系统

戴尔笔记本电脑_台式电脑_服务器_电脑配件_戴尔官方网站 | Dell dell 官方渠道与下载&#xff0c;输入自己dell主机上的服务编码,下载dell的恢复工具回来安装好&#xff0c; 如何下载和使用戴尔操作系统恢复映像 | Dell 中国

MySQL之DQL语句

文章目录 DQL语句指定查询查询全部查询部分数据别名查询使用order by子句拼接查询去重查询WHERE – 条件过滤模糊查询JOIN – 多表关联求和查询排序查询统计查询分页查询 DQL语句 DQL&#xff08;Data Query Language&#xff09;查询数据 操作查询&#xff1a;select简单的查…

Spark集群部署

1.5 Spark集群部署 1.5.1 Spark部署模式 Local 多用于本地测试&#xff0c;如在eclipse&#xff0c;idea中写程序测试等。 Standalone 是Spark自带的一个资源调度框架&#xff0c;它支持完全分布式。 Yarn 生态圈里面的一个资源调度框架&#xff0c;Spark也是可以基于Yarn来…

Python:将numpy数据表示成base64

安装Pybase64库 pip install pybase64conda install pybase64 示例 在Python中&#xff0c;你可以使用numpy库和base64库将numpy数组编码为Base64字符串。以下是一个示例&#xff1a; import numpy as np import base64 # 创建一个numpy数组 data np.array([1, 2…

使用Netropy广域网模拟器测试简化SD-WAN测试

来源&#xff1a;艾特保IT 虹科干货丨使用Netropy广域网模拟器测试简化SD-WAN测试 原文链接&#xff1a;https://mp.weixin.qq.com/s/k5-5Ske9zOMzyx4e3JmtSw 欢迎关注虹科&#xff0c;为您提供最新资讯&#xff01; 文章速览&#xff1a; -为什么需要WAN模拟器&#xff1f;…