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

news2024/11/17 8:52:01

友元

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

有缘的关键字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;
}

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在树莓派上基于 LNMP 搭建 Nextcloud

原文链接&#xff1a;https://blog.iyatt.com/?p17296 环境 树莓派CM4raspios 20240704 Debian 12 arm64 搭建 LNMP 环境 安装 Nginx sudo apt update sudo apt install -y nginx安装 php 及功能组件支持 参考&#xff1a;https://docs.nextcloud.com/server/latest/adm…

【高分系列卫星简介——高分辨率多模综合成像卫星】

高分辨率多模综合成像卫星 高分辨率多模综合成像卫星&#xff08;以下简称“高分多模卫星”&#xff09;是中国航天科技集团所属中国空间技术研究院抓总负责研制的具备亚米级分辨率的民用光学遥感卫星。以下是对高分多模卫星的详细介绍&#xff1a; 一、基本信息 发射时间&…

打造备份一体机,群晖科技平台化战略再进阶

数字经济时代&#xff0c;海量数据不断涌现&#xff0c;并成为核心生产要素&#xff0c;驱动着企业生产方式和商业模式发生深刻变革。 与其他生产要素不同&#xff0c;数据要素具有非稀缺性、非竞争性等特征&#xff0c;且只有在具体业务场景中才能充分释放其价值。尤其是近年…

AIGC: 10 AI转文服务器的搭建过程记录

上图是台风席卷城市&#xff0c;现在企业的服务基本都是混合部署&#xff0c;云计算厂商的机房往往可以提供比较好的保护&#xff0c;一般在地下&#xff0c;扛多少级地震&#xff0c;扛多少级台风&#xff0c;而自建机房&#xff0c;往往写字楼经常停电&#xff0c;网络运营上…

MapBox Android版开发 6 关于Logo

MapBox Android版开发 6 关于Logo Logo的显示查看源码及思路&#xff08;Logo&#xff09;第一步第二步 隐藏Logo示例查看源码及思路&#xff08;Info&#xff09;第一步第二步 隐藏Logo和Info示例 看到有网友留言问如何移除Logo&#xff0c;今天看了下V9源码&#xff0c;发现M…

ThreeJs绘制圆柱体

上一章节实现了圆锥体的绘制&#xff0c;这节来绘制圆柱体&#xff0c;圆柱体就是矩形旋转获得&#xff0c;如上文一样&#xff0c;先要创建出基础的组件&#xff0c;包括场景&#xff0c;相机&#xff0c;灯光&#xff0c;渲染器。代码如下&#xff1a; initScene() {this.sce…

【LeetCode】每日一题 2024_9_27 每种字符至少取 K 个(双指针)

前言 每天和你一起刷 LeetCode 每日一题~ LeetCode 启动&#xff01; 题目&#xff1a;每种字符至少取 K 个 代码与解题思路 func takeCharacters(s string, k int) int {// 核心思路&#xff1a;// 题目要求字符串 s 中&#xff0c;每种字符都取至少 k 个// 而且可以从头取…

使用 LlamaIndex 进行 CRAG 开发用来强化检索增强生成

提升AI模型的准确性与可靠性 ©作者|Ninja Geek 来源|神州问学 介绍 检索增强生成&#xff08;RAG&#xff09;彻底改变了使用大语言模型和利用外部知识库的方式。它允许模型从文档存储的相关索引数据中获取信息用以增强其生成的内容&#xff0c;使其更加准确和信息丰富…

en造数据结构与算法C# 之 二叉排序树的删除

en造数据结构与算法C# 之 二叉排序树的增/查-CSDN博客 删除方法比起添加和查找就稍显复杂了 &#xff0c;所以单独拿出来写一篇 分析 输入 1.根节点&#xff0c;用于从根上查找你要删除的节点 2.需要删除的值 public Node<T> Delete(Node<T> root, T data) {if (…

数据结构及基本算法

目录 第一章 概论 第一节 引言 第二节 基本概念和常用术语 第三节 算法的描述与分析 第二章 线性表 第一节 线性表定义和基本运算个 一、线性表的逻辑定义 二、线性表的基本运算 第二节 线性表的顺序存储和基本运算的实现 一、线性表的顺序存储 二、顺序表上基本运算…

自动驾驶电车难题的康德式道德决策

摘 要 自动驾驶电车难题是检验人工智能伦理可行性的一块试金石 , 面对不同情境 , 其计算程序既要作出可决定的、 内在一致的判断决策 , 又要与人类的普遍道德常识相兼容 。 康德义务论给出了具有普遍性与一致性的理论框架。 自动驾驶电车的道德决策可视为由计算程序执行的第…

Linux学习之路 -- 线程 -- 条件变量与生产消费模型

前面我们已经提过线程互斥的相关概念&#xff0c;但是我们在前文的抢票逻辑中&#xff0c;我们其实很容易发现一个问题。那就是票可能被一直被一个人抢&#xff0c;这里我们就需要引入条件变量的概念。 目录 1、条件变量 <1>线程同步 <2>相关概念 <3>相…

pycharm2024版 搭配Anaconda创建pytorch项目

pycharm2024版 搭配Anaconda创建pytorch项目 ​ 刚接触anaconda和pytorch&#xff0c;b站看的教学视频中博主使用的是2019版的pycharm&#xff0c;所以在创建pytorch项目时有些懵&#xff0c;在多次摸索后大概明白了一些 上图中是2024版pycharm的新项目创建界面 Project venv…

计算机毕业设计 基于Python的广东旅游数据分析系统的设计与实现 Python+Django+Vue Python爬虫 附源码 讲解 文档

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

部分监督多器官医学图像分割中的标记与未标记分布对齐|文献速递--基于多模态-半监督深度学习的病理学诊断与病灶分割

Title 题目 Labeled-to-unlabeled distribution alignment for partially-supervised multi-organ medical image segmentation 部分监督多器官医学图像分割中的标记与未标记分布对齐 01 文献速递介绍 多器官医学图像分割&#xff08;Mo-MedISeg&#xff09;是医学图像分析…

vscode开发uniapp安装插件指南

安装vuets的相关插件 首先是vue的相关插件&#xff0c;目前2024年9月应该是vue-offical 安装uniapp开发插件 uni-create-view &#xff1a;快速创建 uni-app 页面 安装uni-create-view之后修改插件拓展设置 勾选第一个选择创建视图时创建同名文件夹 选择第二个创建文件夹中生…

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…

zabbix 软件监控

一、zabbix基本概念与组件和原理 1.1 zabbix概述 Zabbix 是一款可监控网络的众多参数以及服务器、虚拟机、应用程序、服务、数据库、网站、云等的健康状况和完整性。Zabbix 使用灵活的通知机制&#xff0c;允许用户为几乎任何事件配置基于电子邮件的警报。这允许对服务器问题做…

酒店智能门锁SDK接口通用转换函数对接酒店收银-SAAS本地化-未来之窗行业应用跨平台架构

一、通用转换代码 public class CyberWin_LocakAPP{// public static byte[] bufCard new byte[128 1];public static string 未来之窗_美萍_getsign(byte[] bufCard){int i;string 酒店标识, s, s2;// 先读卡string 未来之窗 Encoding.ASCII.GetString(bufCard);// edt_Ca…

回归预测|基于蜣螂优化长短期记忆网络的数据回归预测Matlab程序DBO-LSTM 多特征输入单输出 含基础LSTM

基于蜣螂优化长短期记忆网络的数据回归预测Matlab程序DBO-LSTM 多特征输入单输出 含基础LSTM 文章目录 一、基本原理DBO-LSTM 多特征输入单输出回归预测的原理和流程2.1 蜣螂优化&#xff08;DBO&#xff09;2.2 长短期记忆网络&#xff08;LSTM&#xff09;3.1 数据准备3.2 模…