【友元补充】【动态链接补充】

友元

友元的目的是让一个函数或者类,访问另一个类中的私有成员。

友元的关键字friend是一个修饰符。

友元分为友元类和友元函数

1.全局函数作友元

2.类作友元

3.类的一个成员函数作友元

好处:可以通过友元在类外访问类内的私有和受保护类型的成员

坏处:破坏了类的封装性

class A {
	int num_a;
public:
	friend void fun();
	friend class B;
};
void fun() {
    A a;
	a.num_a = 2;
	cout << a.num_a << endl;
}
class B {
public:
	void fun() {
        A a;
		a.num_a = 2;
        cout << a.num_a << endl;
	}
};
int main() {
	fun();
    B b;
    b.fun();
	return 0;
}

 通过自行运行,我们可以看到结果如预期结果一致。

现在对于第三种情况进行单独讲解补充:

class B{
public:
	void work(){
        A a;
        a.num=3;
    };
};
class A{
	friend void  B::work(); //只让类内的某一个成员函数成为类A的友元函数
	int num;
};

当你把它看进去的时候,恭喜你,错了。此时a.num访问权限有问题。因为在这里A还没有将B的这个成员函数作为友元函数,A没有权限访问A类的私有成员。

class B{
public:
	void work();
};
class A{
	friend void  B::work(); //只让类内的某一个成员函数成为类A的友元函数
	int num;
};
void B::work() {
	A ma;
	ma.num = 3;
}

此时我们可以通过类外实现成员函数解决上述问题。而且类外实现的位置,必须在A将B的成员函数设为友元后。否则依然会报错。


 动态绑定

【⚪】成员函数必须声明为virtual

【⚪】如果基类中声明了为虚函数,则派生类中重写的函数不必再用virtual修饰

         调用方式:通过对象的指针或引用调用成员函数,或通过成员函数调用,反之就无法实现动态链接。

        特点:灵活,问题抽象性和问题的易维护性。

class A {
	int m_data1, m_data2;
public:
	virtual void vfunc1();
	virtual void vfunc2();
	void func1();
	void func2();
};
class B :public A {
	int m_data3;
public:
	virtual void vfunc1();
	void func1();
};
class C :public B {
	int m_data1, m_data4;
public:
	virtual void vfunc2();
	void func2();
};
类A、B、C的对象模型

利用终端查看:

 

图解分析: 

【⚪】由于这三个类都有虚函数,故编译器为每个类都创建了一个虚表,即类 A 的虚表(A vtbl),类B的虚表(B vtbl),类 C的虚表(C vtbl)。类 A,类 B,类 C 的对象都拥有一个虚表指针,*vptr,用来指向自己所属类的虚表。
【⚪】类 A 包括两个虚函数,故 A vtbl 包含两个指针,分别指向 A::vfunc1()和A::vfunc2()。

【⚪】类 B 继承于类 A,故类 B 可以调用类 A 的函数,但由于类 B 重写了B::vfunc1()函数,故 B vtbl 的两个指针分别指向 B::vfunc1()和 A::vfunc2()。

【⚪】类 C 继承于类 B,故类 C 可以调用类 B 的函数,但由于类 C 重写了C::vfunc2()函数,故 C vtbl 的两个指针分别指向 B::vfunc1()(指向继承的最近的一个类的函数)和C::vfunc2()。
【⚪】虽然模型看起来有点复杂,但是只要抓住“对象的虚表指针用来指向自己所属类的虚表,虚表中的指针会指向其继承的最近的一个类的虚函数”这个特点,便可以快速将这几个类的对象模型在自己的脑海中描绘出来。
【⚪】非虚函数的调用不用经过虚表,故不需要虚表中的指针指向这些函数。

假设我们定义一个类 B 的对象。由于 bObject是类 B 的一个对象,故 bObject包含一个虚表指针,指向类 B 的虚表。

int main(){
    B bObject;
    return 0;
}

现在,我们声明一个类 A 的指针p来指向对象 bObject。虽然p是基类的指针只能指向基类的部分,但是虚表指针亦属于基类部分,所以p可以访问到对象 bObject的虚表指针。bObiect的虚表指针指向类 B的虚表,所以p可以访问到 Bvtbl。 

int main(){
    B bObject;
    A* p=&bObject;//父类指针指向子类对象
    
    return 0;
}

 当我们使用p来调用vfunc1()函数时,会发生什么现象?

int main(){
    B bObject;
    A* p=&bObject;
    p->vfunc1();

    return 0;
}

 程序在执行 p->vfunc1()时,会发现p是个指针,且调用的函数是虚函数,接下来便会进行以下的步骤。
        首先,根据虚表指针 p->vptr来访问对象 bObject 对应的虚表。虽然指针p是基类 A 类型,但是 vptr 也是基类的一部分,所以可以通过 p->vptr 可以访问到对象对应的虚表
        然后,在虚表中查找所调用的函数对应的条目。由于虚表在编译阶段就可以构造出来了,所以可以根据所调用的函数定位到虚表中的对应条目。对于p->vfunc1()的调用,B vtbl 的第一项即是 vfunc1 对应的条目。
        最后,根据虚表中找到的函数指针,调用函数。从图3可以看到,Bvtbl的第一项指向 B::vfunc1(),所以 p->vfunc1()实质会调用 B::vfunc1()函数。

class A{
public:
    virtual void vfun1(){
        cout<<"father eat"<<endl;
    }
};
class B:public A{    
public:
    virtual void vfun1()//在继承关系下,vfun1前面不写virtual,它也是虚函数
    {
        cout<<"child eat"<<endl;
    }
};
int main(){
    A *a=new B;
    a->vfun1();

    return 0;
}

感谢大家支持,今日份知识点已经补充完毕。

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

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

相关文章

Python画笔案例-068 绘制漂亮米

1、绘制漂亮米 通过 python 的turtle 库绘制 漂亮米,如下图: 2、实现代码 绘制 漂亮米,以下为实现代码: """漂亮米.py注意亮度为0.5的时候最鲜艳本程序需要coloradd模块支持,安装方法:pip install coloradd程序运行需要很长时间,请耐心等待。可以把窗口最小…

智能Ai语音机器人的应用价值有哪些?

随着时间的推移&#xff0c;人工智能的发展越来越成熟&#xff0c;智能时代也离人们越来越近&#xff0c;近几年人工智能越来越火爆&#xff0c;人工智能的应用已经开始渗透到各行各业&#xff0c;与生活交融&#xff0c;成为人们无法拒绝&#xff0c;无法失去的一个重要存在。…

医疗大数据安全与隐私保护:数据分类分级的基石作用

医疗行业在数字化转型中迅猛发展&#xff0c;医疗大数据作为核心驱动力&#xff0c;深刻改变医疗服务的模式与效率。它不仅促进医疗信息的流通与共享&#xff0c;推动个性化、精准化的医疗服务新生态。同时&#xff0c;也在提升医疗服务质量、优化医疗资源配置等方面展现巨大潜…

Spring Ioc底层原理代码详细解释

文章目录 概要根据需求编写XML文件&#xff0c;配置需要创建的bean编写程序读取XML文件&#xff0c;获取bean相关信息&#xff0c;类&#xff0c;属性&#xff0c;id前提知识点Dom4j根据第二步获取到的信息&#xff0c;结合反射机制动态创建对象&#xff0c;同时完成属性赋值将…

蓝桥杯【物联网】零基础到国奖之路:十二. TIM

蓝桥杯【物联网】零基础到国奖之路:十二. TIM 第一节 理论知识第二节 cubemx配置 第一节 理论知识 STM32L071xx器件包括4个通用定时器、1个低功耗定时器&#xff08;LPTIM&#xff09;、2个基本定时器、2个看门狗定时器和SysTick定时器。 通用定时器&#xff08;TIM2、TIM3、…

Spring Cloud Alibaba-(6)Spring Cloud Gateway【网关】

Spring Cloud Alibaba-&#xff08;1&#xff09;搭建项目环境 Spring Cloud Alibaba-&#xff08;2&#xff09;Nacos【服务注册与发现、配置管理】 Spring Cloud Alibaba-&#xff08;3&#xff09;OpenFeign【服务调用】 Spring Cloud Alibaba-&#xff08;4&#xff09;Sen…

数据分析工具julius ai如何使用

什么是julius ai Julius AI 是一款强大的ai数据分析工具。用户可以使用excel、数据库、文本文件等多种格式的数据&#xff0c;Julius AI 会自动分析这些数据并提供详细的解释和可视化图表。官网显示它目前已经有三十万用户。它也支持手机版。 虽然openai也支持生成图表&#xf…

asp.net core grpc快速入门

环境 .net 8 vs2022 创建 gRPC 服务器 一定要勾选Https 安装Nuget包 <PackageReference Include"Google.Protobuf" Version"3.28.2" /> <PackageReference Include"Grpc.AspNetCore" Version"2.66.0" /> <PackageR…

项目实战:k8s部署考试系统

一、新建nfs服务器&#xff08;192.168.1.44&#xff09; 1.基础配置&#xff08;IP地址防火墙等&#xff09; 2.配置时间同步 [rootlocalhost ~]# yum -y install ntpdate.x86_64 [rootlocalhost ~]# ntpdate time2.aliyun.com 27 Sep 10:28:08 ntpdate[1634]: adjust tim…

MySql在更新操作时引入“两阶段提交”的必要性

日志模块有两个redo log和binlog&#xff0c;redo log 是引擎层的日志&#xff08;负责存储相关的事&#xff09;&#xff0c;binlog是在Server层&#xff0c;主要做MySQL共嗯那个层面的事情。redo log就像一个缓冲区&#xff0c;可以让当更新操作的时候先放redo log中&#xf…

node.js npm 安装和安装create-next-app -windowsserver12

1、官网下载windows版本NODE.JS https://nodejs.org/dist/v20.17.0/node-v20.17.0-x64.msi 2、安装后增加两个文件夹目录node_global、node_cache npm config set prefix "C:\Program Files\nodejs\node_global" npm config set prefix "C:\Program Files\nod…

基于SpringBoot的新冠检测信息管理系统的设计与实现

文未可获取一份本项目的java源码和数据库参考。 国内外在该方向的研究现状及分析 新型冠状病毒肺炎疫情发生以来&#xff0c;中国政府采取积极的防控策略和措施&#xff0c;经过两个多月的不懈努力&#xff0c;有效控制了新发病例的増长&#xff0c;本地传播已经趋于完全控制…

Mysql高级篇(中)——锁机制

锁机制 一、概述二、分类1、读锁2、写锁★、FOR SHARE / FOR UPDATE&#xff08;1&#xff09;NOWAIT&#xff08;2&#xff09;SKIP LOCKED&#xff08;3&#xff09;NOWAIT 和 SKIP LOCKED 的比较 ★、 脏写3、表级锁之 S锁 / X锁&#xff08;1&#xff09;总结&#xff08;2…

自动化学习3:日志记录及测试报告的生成--自动化框架搭建

一.日志记录 1.配置文件pytest.ini&#xff1a;将日志写入文件方便日后查询或查看执行信息。 需要将文件处理器&#xff08;文件存放位置/时间/格式等等&#xff09;添加到配置文件中的【日志记录器】 # pytest.ini [pytest] # ---------------日志文件&#xff0c;需要配合…

PMP--二模--解题--141-150

文章目录 14.敏捷--创建敏捷环境--团队构成--混合项目环境&#xff0c;通常是自组织团队&#xff0c;即团队成员自己决定谁做什么&#xff0c;而不是项目经理决定。易混--常见场景--一个新人加入141、 [单选] 在一个混合项目的执行过程中&#xff0c;不得不更换一个开发人员。新…

微软Win11 22H2/23H2 九月可选更新KB5043145发布!

系统之家于9月27日发出最新报道&#xff0c;微软针对Windows11系统&#xff0c;发布了九月最新可选更新补丁KB5043145&#xff0c;22H2用户安装后&#xff0c;系统版本号升至22621.4249&#xff0c;23H2用户安装后升至22631.4249。本次更新修复了Edge使用IE模式有时会停止响应等…

腾讯云SDK产品功能

本文主要介绍音视频终端 SDK&#xff08;腾讯云视立方&#xff09;的核心功能。 直播推流 音视频终端 SDK&#xff08;腾讯云视立方&#xff09;为终端直播场景提供强大的 RTMP、RTC 推流能力&#xff0c;配合云直播&#xff08;CSS&#xff09;全球布局的2000节点&#xff0…

GreenPlum数开手册【语法篇】

GreenPlum数开手册 一、数据类型 1、基本数据类型 类型长度描述范围bigint8字节大范围整数-9223372036854775808 到 9223372036854775807smallint2字节小范围整数-32768到32767integer(int)4字节常用整数-2147483648 到 2147483647decimal可变长用户指定的精度&#xff0c;精…

ARM_5_UART总线接口实验

一、总线相关的概念 1.1、总线的含义 定义&#xff1a;总线是不同设备间通信的桥梁 比如&#xff1a; PC ---------------- UART总线------------------ SOC SOC&#xff08;stm32mp157a&#xff09; --------------- IIC总线 ---------------- 空气温湿度芯片&#xff0…

【C++报错已解决】std::ios_base::failure

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…