c++ - 抽象类 和 使用多态当中一些注意事项

news2024/11/19 23:22:20

 抽象类

纯虚函数 

 在虚函数的后面写上 =0 ,则这个函数为纯虚函数。

class A
{
public:
	virtual void func() = 0;
};

纯虚函数不需要写函数的定义,他有类似声明一样的结构。

 抽象类概念

 我们把具有纯虚函数的类,叫做抽象类。

所谓抽象就是,不符合常理的,偶然的,和平常的类不太一样的类。抽象一般是我们人自己想出来的形象,在现实世界当中没有对应的实体,同样的抽象类在现实世界当中没有对应的实体。

 所以,以上描述就引出了抽象类最大的特点:抽象类不能实例化对象

 而且,如果某一个子类的父亲是一个抽象类,那么这个子类也是不能实例化对象的,因为子类继承了父类当中的纯虚函数。那么子类就包含了纯虚函数,主要是包含纯虚函数的类就是抽象类。

 那么,怎样才能让上述的 B 子类能够 实例化对象呢?我们只需要在 B 当中重写一些 A 当中的纯虚函数就可以 让 子类(B类)实例化对象了

// 这是一个抽象类
class A
{
public:
	virtual void func() = 0;
};

// 重写之后就可以 实例化B 对象了
class B : public A
{
public:
	virtual void func()
	{
		cout << "B::func()" << endl;
	}
};

int main()
{
	B b;

	return 0;
}

使用抽象类作为父类,实现出来的子类的多态使用方式,是和普通的一样的。只不过在 父类 当中不在有虚函数表,因为 父类是抽象类,抽象类不能实例化对象,也就不存在虚函数表了。

抽象类当中的多态 和 普通父类的多态在这里多做了一件什么事情呢?

  •  我们知道,父类当中的虚函数,如果子类不进行重写,那么这个虚函数是没有任何作用的;而在抽象类当中,就强制其子类要对抽象类当中的纯虚函数进行重写。
  • 而且这里是 间接性的 强制重写,和之前我们提到的 override 检车重写是不一样的。而且 override 是修饰在派生类当中的,抽象类强制重写,语法是建立在父类当中的。

 多态当中需要注意的点

  •  inline(内联)函数能不能是虚函数?可以,但是,当一个 inline函数 称为虚函数之后,这个函数就不在是inline函数了,因为虚函数需要把地址放到虚表当中,而且内联函数是没有地址的。
  • 静态成员函数不能是 虚函数。如果 把 static 和 virtual 放在一起修饰的话,编译器会直接报错。这是因为,静态成员函数没有 this 指针,静态成员函数是使用 类型::成员函数名 的方式调用的,这样的方式是不能访问到对象当中的虚表的,所以静态成员函数是无法放进虚表的;还有个解释是,静态成员函数是属于类的,不是属于对象的,而只有实例化对象出来之后才能构造处虚表。
  •  构造函数不能是虚函数,如果在构造函数前加 virtual 修饰,就会报错。虚函数表是在编译的时候生成的,而指向虚表的指针是在 构造函数初始化列表的最端初始化的,初始化之后才会指向虚函表, 初始化之前都是随机值。那么,如果构造函数成为了虚函数,而虚函数的作用就是多态,那么在构造函数调用前,虚函数表指针都没有初始化,怎么去找这个构造函数的虚函数呢?所以,构造函数是不能成为虚函数的。
  • 析构函数可以是虚函数。而且,我们最好把父类当中的析构函数定义为虚函数,让子类进行重写。比如这个例子(A是父类,B是子类):A* p = new B;    delete p; 此时,因为 p 指针的类型是 父类A的类型,所以,在调用 detele 的时候,所调用的析构函数就会是 父类 A 的析构函数,那么就会出现问题,但是如果 重写之后,就会调用子类的析构函数。
  • 一个类当中调用普通函数快还是调用虚函数快?如果是普通对象,一样快;如果是指针函数或引用函数,普通函数快。因为此时构成多态。但是,其实两者之间调用时间,差别不大。

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

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

相关文章

docker gitlab+jenkins搭建

一&#xff1a;gitlab搭建: 1&#xff1a;docker部署 2&#xff1a;修改root密码 3&#xff1a;创建普通账户 4&#xff1a;设置sshken 二&#xff1a;jenkins搭建 配置脚本 bash -x /var/jenkins_home/shell/game01.sh

图解数据结构

&#x1f31e;欢迎来到数据结构的世界 &#x1f308;博客主页&#xff1a;卿云阁 &#x1f48c;欢迎关注&#x1f389;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f31f;本文由卿云阁原创&#xff01; &#x1f4c6;首发时间&#xff1a;&#x1f339;2023年9月17日&…

【探索Linux】—— 强大的命令行工具 P.8(进程地址空间)

阅读导航 前言一、内存空间分布二、什么是进程地址空间1. 概念2. 进程地址空间的组成 三、进程地址空间的设计原理1. 基本原理2. 虚拟地址空间 概念 大小和范围 作用 虚拟地址空间的优点 3. 页表 四、为什么要有地址空间五、总结温馨提示 前言 前面我们讲了C语言的基础知识&am…

性能测试-性能调优主要方向和原则(15)

性能调优主要方向明确性能瓶颈之后,就需要进行性能调优了,调优主要从图所示的多个方向入手。能优化手段并不一定是独立应用的,在一次优化过程中很可能应用了多种优化技巧。 硬件层面优化 硬件层面优化更偏向于监控,当定位到硬件资源成为瓶颈后,更多是采用扩容等手段来解决…

代码随想录算法训练营第三十六天| 435. 无重叠区间 763.划分字母区间 56. 合并区间

今天的三道题目&#xff0c;都算是 重叠区间 问题&#xff0c;大家可以好好感受一下。 都属于那种看起来好复杂&#xff0c;但一看贪心解法&#xff0c;惊呼&#xff1a;这么巧妙&#xff01; 还是属于那种&#xff0c;做过了也就会了&#xff0c;没做过就很难想出来。 不过大…

synchronized实战:synchronized 锁升级过程

下面程序通过对加锁前后Object对象字节码的打印验证了对象由无锁到偏向锁的过程。 public class T01 {public static void main(String[] args) {Object o new Object();System.out.println(ClassLayout.parseInstance(o).toPrintable());o.hashCode();System.out.println(Cl…

Linux界的老古董

Slackware 是由 Patrick Volkerding 制作的 Linux 发行版&#xff0c;从 1993 年发布至今也一直在 Patrick 带领下进行维护。7 月 17 日&#xff0c;Slackware 才刚刚过完它 24 岁的生日&#xff0c;看似年纪轻轻的它&#xff0c;已然是 Linux 最古老的发行版。 Slackware 的发…

laravel框架 - 安装初步使用学习 composer安装

一、什么是laravel框架 Laravel框架可以开发各种不同类型的项目&#xff0c;内容管理系统&#xff08;Content Management System&#xff0c;CMS&#xff09;是一种比较典型的项目&#xff0c;常见的网站类型&#xff08;如门户、新闻、博客、文章等&#xff09;都可以利用CM…

【Linux学习笔记】权限

1. 普通用户和root用户权限之间的切换2. 权限的三个w2.1. 什么是权限&#xff08;what&#xff09;2.1.1. 用户角色2.1.2. 文件属性 2.2. 怎么操作权限呢&#xff1f;&#xff08;how&#xff09;2.2.1. ugo-rwx方案2.2.2. 八进制方案2.2.3. 文件权限的初始模样2.2.4. 进入一个…

Linux基础操作

ls [-a -l -h] [Linux路径] 当不使用选项和参数&#xff0c;直接使用ls命令本体&#xff0c;表示以平铺的方式&#xff1a;列出当前工作目录下的内容 ls -a -a表示all的意思&#xff0c;即列出所有文件&#xff08;包含隐藏的文件和文件夹&#xff09; ls -l 以竖列的形式展示信…

linux C语言 socket的server、client 实现

讲解&#xff1a; 在Linux中&#xff0c;使用socket与另一端建立连接通常涉及到以下步骤&#xff1a; 1. 创建Socket&#xff1a;首先&#xff0c;你需要创建一个套接字(socket)。你可以使用socket()系统调用来创建套接字。通常&#xff0c;你需要指定套接字的类型&#xff0…

ssh服务登录原理与配置

文章目录 前言一、基于口令的认证&#xff08;用户名密码&#xff09;二、基于公钥的认证&#xff08;免密登录&#xff09;三、禁止用户登录和修改端口四、免密登录具体操作 前言 非对称加密是在认证用户连接的时候使用的&#xff0c;对称加密是在用户连接之后开始传输数据的…

【C++】深拷贝和浅拷贝 ④ ( 深拷贝示例 )

文章目录 一、深拷贝示例1、浅拷贝问题2、自己实现深拷贝 二、深拷贝完整代码示例 一、深拷贝示例 1、浅拷贝问题 在上一篇博客 【C】深拷贝和浅拷贝 ③ ( 浅拷贝内存分析 ) 中 , 使用了浅拷贝 , 将 原始对象 Students 赋值给了 拷贝对象 Student s2 ; 使用 C 编译器 生成的 默…

Mysql的基本查询练习

目录 一、Create 1.1单行数据全列插入 1.2 多行数据指定列插入 1.3插入否则更新 1.4 替换 二、Retrieve 2.1全列查询 2.2指定列查询 2.3查询字段为表达式 2.4为查询结果指定别名 2.5 结果去重 2.6 where 条件 2.6 NULL的查询 2.7 结果排序 三、 Update 四、Dele…

电力系统直流潮流分析【N-1】(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

VHOST-SCSI代码分析(0)VHOST概述

与VIRTIO框架相比&#xff0c;VHOST将设备放到HOST上&#xff0c;让Guest和Host Kernal Space之间共享virtqueue&#xff0c;减少Exception Level切换。 对于数据的传递&#xff0c;依次经历&#xff1a;Guest UserSpace&#xff08;EL0&#xff09;-> Guest KernelSpace&am…

MySQL索引,事务及存储引擎

目录 MySQL索引 创建索引的依据&#xff1a; 索引的类型 普通索引 唯一索引 主键索引 组合索引 全文索引 查看索引 删除索引 事务 事务的 ACID 特性 原子性 一致性 隔离性 持久性 隔离级别 设置隔离级别 事务管理操作 自动提交事务 存储引擎 M…

GODIVA论文阅读

论文链接&#xff1a;GODIVA: Generating Open-DomaIn Videos from nAtural Descriptions 文章目录 摘要引言相关工作Video-to-video generationText-to-image generationText-to-video generation GODIVA方法逐帧视频自动编码器GODIVA视频生成器 实验数据集评价指标自动评估指…

QT基础教程(对话框1)

文章目录 前言一、对话框概念二、模态对话框三、非模态对话框总结 前言 本篇文章我们来讲解QT中的对话框。 资料合集地微信公众号&#xff1a;优质程序猿一、对话框概念 在Qt中&#xff0c;对话框&#xff08;Dialog&#xff09;是一种用于与用户进行交互、收集输入或展示信…

适用于 Android 的 Windows 子系统™️发行说明

&#x1f3ac; 岸边的风&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 内部版本 2304.40000.3.0 内部版本 2303.40000.3.0 内部版本 2302.4000 内部版本 2301.40000.4.0 内部版本 221…