程序的动态特性

2023-11-06

程序的动态特性:大多数情况下,程序的功能是在编译的时候确定下来的,称之为静态特性;而如果程序的功能是在运行时才确定的称为动态特性。

动态特性是面向对象语言最强大的功能之一,它在语言层面上支持程序的可扩展性。

动态特性:由C++虚函数、抽象基类、动态绑定和多态构成。

(1)虚函数:可用于使用统一的方式来调用相同功能的函数实现做类似但不同的事情。例如,假定几何形状Shape,其派生类为Circle、Rectangle、Ellicps等,每个派生类都能绘制自己所代表的形状。不管派生类如何,我们希望用统一的方式来调用绘制函数,最好使用Shape定义的接口函数Draw(),并让程序在运行时动态去顶使用哪一个派生类。可以把类Shape中的函数Draw()声明为虚函数,然后派生类中重新定义Draw()使之绘制正确的形状,这种方法叫覆盖。

(2)抽象基类:抽象类的唯一目的就是让派生类继承并实现它的接口方法(Method),因此它通常被称为抽象基类(Abstract Base Class)。如果将基类的虚函数声明为纯虚函数,那么该类就被定义为了抽象基类。纯虚函数是在声明时将其“初始化”为0的函数。将一个函数初始化为0意味着函数的地址将为0,即是告诉编译器:不要为该函数编址,从而阻止该类的实例化行为。

很多良好的面向对象系统中,基类层次结构的顶部通常都是抽象基类,甚至可以有好几层的抽象类。例如集合形状的类结构可分为三层,顶层是抽象基类Shape,第二层也是抽象基类Shape2D和Shape3D,在第三层才是可以被实例化为对象的具体类,如二维形状类Circle、Rectangel和Ellipse,三维形状类Cube、Cylinder和Sphere.

抽象基类的主要用途是“接口与实现分离”:不仅要把数据成员(信息)隐藏起来,而且还要把实现完全隐藏起来,只留一些接口给外部调用。

一般的信息隐藏就是把类的所有数据成员声明为private或者protected的,并提供相应的get和set函数来访问对象的数据。抽象基类则更进一步,它把数据和函数实现都隐藏在实现类中,而在抽象基类中提供丰富的接口函数供调用,这些函数都是public的纯虚函数。这样的抽象基类叫接口类。

由于抽象基类不能够实例化,并且实现类被完全隐藏,所以必须以其他的途径使用户能够获得实现类的对象,比如提供入口函数来动态创建实现类的对象。如果函数可以是全局函数,但最好是静态称冠函数。

(3)动态绑定

动态绑定(或运行时绑定、晚绑定):如果将基类Shape的函数Draw()声明为virtual的,然后用指向派生类对象的基类指针或引用来调用Draw(),那么程序会在运行时选择该派生类的Draw()函数而不是Shape::Draw()(即是,运行时绑定特性)。如下示例:


每一个具有虚函数的类都叫做多态类,这个虚函数或者是从基类继承来的,或者是自己新增加的。C++编译器必须为每一个多态类至少创建一个虚函数(vtable),它其实就是一个函数指针数组,其中存放着这个类所有的虚函数的地址及该类的类型信息,其中包括那些继承但未改写(overrides)的函数。每一个多态对象都有一个隐含的指针成员,它指向所属类型的vtable,这就是vptr.

虚函数的动态绑定采用的是运行时函数寻址技术,该类型信息主要用在RTTI技术上。通过基类指针或引用对虚函数的调用语句都会被编译器改写成下面形式:

(*(p->_vptr[slotNum]))(p, arg-list); //指针当做数组来用,最后改写为指针运算

标准C++实现采用的策略:派生类定义中的名字(对象或函数名)将义无反顾地遮蔽(即隐藏)掉基类中任何同名的对象或函数。但如果派生类定义了一个与基类的虚函数同名的虚函数,但是参数列表有所不同,那么就不会被编译器认为是对基类虚函数的改写,而是隐藏,所以不可能发生运行时绑定。

要想达成运行时绑定的效果,派生类和基类中同名的虚函数必须具有相同的原型。举例如下声明//(1)不是对基类的Draw()函数的改写,而是新增的virtual函数,声明//(2)才是对基类Draw()函数的改写.



上例中,如果RectangleImpl不重新定义Draw()函数,那么下面的代码:RectangleImple 不重新定义Draw()函数,那么下面的代码:

RectangleImpl *pRectImpl = new RectangleImpl;

pRectImpl->Draw(); //(3)

pRectImpl->Draw(200); //ok!

将无法编译,因为//(3)处调用的Draw()是基类的函数,它被RectangleImpl中的同名函数Draw(int)隐藏了。

(4)运行时多态

运行时多态:由于许多派生类因为继承了共同的基类而建立is-a关系时,每一个派生类的对象都可以被当成基类的对象来使用,这些派生类对象能贵统一函数调用做出不同的反应,这就是运行时多态。

C++支持运行时多态特性有两种手段,一种是虚函数机制,另一种是RTTI。c++支持多态方法如下:

@  经过隐含的转型操作,令一个public多态基类的指针或者引用指向它的一个派生类的对象

@  通过这个指针或者引用调用基类的虚函数,包括通过指针的反引用调用虚函数,因为反引用一个指针将返回所指对象的引用;

@  使用dynameic_cast<>和typeid运算符。

综合C++的“虚函数”和“多态”,有如下特点:

@  应用程序不必为每一个派生类编写功能调用,只需要对基类的虚函数进行改写和扩展即可。

@派生类的功能可以被基类指针引用,这叫向后兼容。以前写的程序可以被将来写的程序调用;将来写的程序也可以被以前写得程序调用。

现在许多分布式中间件比如CORBA、COM等充分利用了虚函数动态绑定这一优点,把底层的网络通信功能全部封装起来,而在上层预留一些回调接口由用户实现,这些接口往往表现为虚函数。

(5)多态数组

多态和指针算术运算不能混合运用,而数组操作几乎总是会涉及到指针运算,因此多态和数组不应该混合运用(Scott Meyers).

解决办法:不要在数组中直接存放多态对象,而是换之以基类指针或者基类的智能指针。(直接使用基类的指针可能需要自己负责删除它们指向的对象,但是使用智能指针则不需要操这份心)。

普通指针使用:

智能指针多态数组















本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

程序的动态特性 的相关文章

  • react hook之React.lazy()

    也不怕大家笑话 看到react lazy 我第一个想到的居然是vue 中的一个vue lazy 用户懒加载的插件 但是这两个差别还是有点大的 好了我们言归正传 开始来看看我们的react lazy 其实看见lazy 大家见名知意 就知道是来
  • 网络概述介绍

    网络概括 计算机网络 通过传输介质 通信设施和网络通信协议 把分散在不同地点的计算机设备互联起来 实现资源共享和数据传输 网络编程 编写程序代码将两个或者两个以上的设备进行数据传输 OSI参考模型 将复杂的网络问题根据功能划分到不同层次上
  • tensflower 安装

    V型从v
  • Mysql的执行日志

    Mysql的执行日志可以帮助我们确定在项目中是否完了了连接数据库 尤其是在生产环境中 直接使用命令方式进行定位能够解决很多问题 下面介绍几个常用命令 准备 确定日志开启状态 首先确认你日志是否启用了mysql gt show variabl
  • 一文入门车载以太网,吐血整理!不看后悔!

    前言 近些年来 随着为了让汽车更加安全 智能 环保等 一系列的高级辅助驾驶功能喷涌而出 未来满足这些需求 就对传统的电子电器架构带来了严峻的考验 需要越来越多的电子部件参与信息交互 导致对网络传输速率 稳定性 负载率等方面都提出了更为严格的
  • [数据库] Navicat for MySQL事件Event实现数据每日定期操作

    在我们操作数据库过程中 通常会遇到一些某个时间点操作数据库的问题 例如 1 每天凌晨12点对数据库进行定时备份 结算和汇总 2 每天凌晨2点删除数据库前三天的数据 3 插入某个数据超过一定时间改变某个值的状态 比如预警系统 这里就需要通过E

随机推荐

  • 耦合和解耦的理解 vue高耦合和低耦合的理解

    耦合 耦合是指两个或两个以上的体系或两种运动形式间通过相互作用而彼此影响以至联合起来的现象 在软件工程中 对象之间的耦合度就是对象之间的依赖性 对象之间的耦合越高 维护成本越高 因 此对象的设计应使类和构件之间的耦合最小 解耦 解耦 字面意
  • OpenAI Translator

    简介 OpenAI Translator 一款基于 ChatGPT API 的划词翻译浏览器插件和跨平台桌面端应用 使用 ChatGPT API 进行划词翻译和文本润色 借助了 ChatGPT 强大的翻译能力 帮助用户更流畅地阅读外语和编辑
  • Mac下静态库和动态库的创建和使用

    1 演示代码 add cpp int add int a int b return a b main cpp include
  • js三元表达式

  • Ubuntu13下调试USB AUDIO的一些记录

    最近想玩玩LINUX 于是双系统装了一个Ubuntu13 04 在新系统下用着都还好 不过我自己DIY的USB DAC出了问题 在WIN7下能正常工作 但是在Ubuntu下就爆音不断 很明显是音频数据流断流引起的 这说明stm32上的固件与
  • K8S集群管理

    集群管理 1 集群管理 1 1 节点管理 1 1 1 令牌管理 1 1 2 集群扩缩容 1 1 3 集群升级 1 1 4 证书管理 1 2 数据管理 1 2 1 ETCD基础 1 2 2 ETCD实践 1 2 3 备份还原 1 2 4 ET
  • 4、一维数组、遍历数组、冒泡排序、插入排序、选择排序

    一维数组 定义形式1 数据类型 数组变量名 new 数据类型 数组长度 例1 int array new int 10 例2 char array new char 8 定义形式2 数据类型 数组变量名 值1 值2 值3 值n 例1 int
  • 安装企业版宝塔加美化模版

    宝塔企业7 9 9指令 yum install y wget wget O install sh http jsjs xn n6q058g tk down php 65f0164d0846e99b28c9416a65b66bdd sh sh
  • Storm简介

    场景 伴随着信息科技日新月异的发展 信息呈现出爆发式的膨胀 人们获取信息的途径也更加多样 更加便捷 同时对于信息的时效性要求也越来越高 举个搜索场景中的例子 当一个卖家发布了一条宝贝信息时 他希望的当然是这个宝贝马上就可以被卖家搜索出来 点
  • Redis学习记录(二)

    redis命令 基本命令 心跳命令 ping 读写键值命令 set get DB切换 select 数据库切换 查看数据库中的key数量 dbsize 删除当前库中的数据 flushdb 删除所有库中的数据 flushall 退出客户端命令
  • 【语义分割】DFANet -- Deep Feature Aggregation for Real-Time Semantic Segmentation

    efficient inferrence speed and high accuracy with high resolution Architecture DFANet从整体上可看做是encoder decoder结构 包括四个部分 th
  • sklearn中的XGBClassifier参数详解

    前言 1 Xgboost简介 Xgboost是Boosting算法的其中一种 Boosting算法的思想是将许多弱分类器集成在一起 形成一个强分类器 因为Xgboost是一种提升树模型 所以它是将许多树模型集成在一起 形成一个很强的分类器
  • Linux内核模块管理(查看、添加和删除)

    Linux 的内核会在启动过程中自动检验和加载硬件与文件系统的驱动 一般这些驱动都是用模块的形式加载的 使用模块的形式保存驱动 可以不直接把驱动放入内核 有利于控制内核大小 模块的全称是动态可加载内核模块 它是具有独立功能的程序 可以被单独
  • Java多线程问题--wait()和notify()

    本文内容部分引自 Java多线程编程核心技术 感谢作者 代码地址 https github com xianzhixianzhixian thread git 介绍wait 和notify 的使用以及注意事项 1 wait 方法是Objec
  • 图像相似度的评价指标 : FID(Fréchet Inception Distance)

    FID Fr chet Inception Distance 是用来计算真实图像与生成图像的特征向量间距离的一种度量 如果FID值越小 则相似程度越高 最好情况即是FID 0 两个图像相同 实际计算 参考链接 https machinele
  • 一个石头剪刀布游戏的python解法

    一个石头剪刀布的python解法 import random game 石头 剪刀 布 随机生成一个1 3之间的数 random digit random randint 1 3 输入你猜测的数 num int input 请输入1 2 3
  • RHEL5.6 下安装并测试openCV1.0.0(----成功----)

    一 首先去openCV官网下载openCV1 0 0版本 貌似需要翻墙后才能下载 二 解压源码包并安装 configure without python enable shared prefix opt opencv make make i
  • C++ 多线程 报错invalid use of non-static member function

    创建一个类test class test public void func std cout lt lt test main函数多线程调用test test t new test std thread th t gt func 编译报错 G
  • visual studio用环境变量设置目录

    visual studio里可以用环境变量来指定包含目录等目录
  • 程序的动态特性

    程序的动态特性 大多数情况下 程序的功能是在编译的时候确定下来的 称之为静态特性 而如果程序的功能是在运行时才确定的称为动态特性 动态特性是面向对象语言最强大的功能之一 它在语言层面上支持程序的可扩展性 动态特性 由C 虚函数 抽象基类 动