c++ - 抽象类 和 多态当中一些问题

news2025/1/23 7:17:38

 抽象类

纯虚函数 

 在虚函数的后面写上 =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/996368.html

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

相关文章

124个Python案例,完整源代码!

大家好&#xff0c;我是涛哥。 很多小伙伴为了掌握爬虫这门技术&#xff0c;投入了大量的时间和精力。他们在深夜里独自码字&#xff0c;他们在周末的时候熟读代码&#xff0c; 但独自学习&#xff0c;没有朋友的陪伴和指导&#xff0c;学习的过程就像是在一条无尽的道路上徘…

【多线程】wait 、notify 和 notifyAll 讲解

wait 、notify 和 notifyAll 讲解 一. wait二. wait 和 sleep 的对比三. notify四. notifyAll五. notify 与 notifyAll 的原理 由于线程之间是抢占式执行的, 因此线程之间执行的先后顺序难以预知. 但是实际开发中有时候我们希望合理的协调多个线程之间的执行先后顺序. 完成这个…

军队状态出现的六种结果,是将帅的过失

军队状态会出现六种坏结果&#xff0c;是将帅的过失 【安志强趣讲《孙子兵法》第35讲】 【原文】 故兵有走者&#xff0c;有弛者&#xff0c;有陷者&#xff0c;有崩者&#xff0c;有乱者&#xff0c;有北者。凡此六者&#xff0c;非天之灾&#xff0c;将之过也。 【趣讲白话】…

【代码分析】初学解惑C++:函数适配器

文章目录 前置知识 运算符的重载“&#xff08;&#xff09;”一、函数适配器是什么&#xff1f;由遇到的问题引出适配器模式类模式对象模式例1例2例3例4二、实现函数适配器1.定义函数2.定义函数适配器3.使用函数适配器 三、带模板的函数适配器1、自定义unary_function2、改写带…

alibaba按关键字搜索商品 API

为了进行电商平台 的API开发&#xff0c;首先我们需要做下面几件事情。 1&#xff09;开发者注册一个账号 2&#xff09;然后为每个alibaba应用注册一个应用程序键&#xff08;App Key) 。 3&#xff09;下载alibaba API的SDK并掌握基本的API基础知识和调用 4&#xff09;利…

vue3中,调接口,渲染数据

1. 封装接口文档 // src/apis/xxx.js中 // 1. 导入 封装的axios实例 import request from /utils/http // 2. 封装接口 --获取轮播图数据 export const getBannerAPI (params {})>{// 传默认参数->&#xff08;传参 默认参数&#xff09;const { distributionSite…

Reids的安装使用

Windows 版本的 Redis 是 Microsoft 的开源部门提供的 Redis. 这个版本的 Redis 适合开发人员学习使用&#xff0c;生产环境中使用 Linux 系统上的 Redis, 这里讲解了这两种的安装和下载。按照你们需要的liunx 或window步骤来 就可以了&#xff08;也可以留言&#xff0c;后面看…

c++ explicit关键作用

explicit 概念引入1.explicit 介绍1.1 显示调用和隐式调用1.2 explicit意义 概念引入 构造函数不仅可以构造并初始化对象&#xff0c;对于具有单个参数或者除第一个参数无默认值其余均有默认值的构造函数&#xff0c;还具有类型转换作用。 而explicit关键字&#xff0c;恰恰可…

useGetState自定义hooks解决useState 异步回调获取不到最新值

setState 的两种传参方式 1、直接传入新值 setState(options); const [state, setState] useState(0); setState(state 1); 2、传入回调函数 setState(callBack); const [state, setState] useState(0); setState((prevState) > prevState 1); // prevState 是改变之…

BUUCTF reverse2 1

使用die查看文件信息&#xff0c;发现是ELF64位程序&#xff0c; 也就是说这是linux上的运行程序 再linux上运行 使用IDA64打开文件 F5 反编译 可以看到这里和flag进行对比 点击flag 点击这个7Bh&#xff0c;然后按r flag出来了 {hacking_for_fun}加上flag头提交 flag{h…

Python入门教程35:使用email模块发送HTML和图片邮件

smtplib模块实现邮件的发送功能&#xff0c;模拟一个stmp客户端&#xff0c;通过与smtp服务器交互来实现邮件发送的功能&#xff0c;可以理解成Foxmail的发邮件功能&#xff0c;在使用之前我们需要准备smtp服务器主机地址、邮箱账号以及密码信息。 #我的Python教程 #官方微信公…

用Canape配置VX1000的工程,在DA中绘制各个传感器目标的方法

参考本文档可帮助读者,快速安装VX1000软件,根据自己的需求,实现传感器目标在canape中DA的绘制。 介绍 Driver assistance (DA)系统是通过各种传感器(如视频、雷达、激光雷达等)获取有关车辆环境的信息。根据传感器对物体检测的结果(例如与前方车辆的距离)对驾驶员发…

《C++ Core Guidelines解析》:揭示现代C++最佳实践的深层原理

本书旨在深入解析C Core Guidelines&#xff0c;这是C社区中权威的编程指南。我们将探索其中所包含的现代C最佳实践&#xff0c;从底层原理和设计理念角度剖析其背后的思想。通过对Guidelines的逐条解析和实例说明&#xff0c;读者将深入理解如何编写更安全、高效和可维护的C代…

滑动窗口的最大值(双端队列,单调队列)

力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 class Solution {public int[] maxSlidingWindow(int[] nums, int k) {LinkedList<Integer> deque new LinkedList<>();//双端队列&#xff0c;存储单调队列的下标int ans[] new int[nu…

Android Studio 导入工程Gradle和JDK配置修改工程名称修改包名

一、Gradle 配置 经常遇到导入的工程却编译不过&#xff0c;很多情况下就是因为配置不一样导致有问题&#xff0c;主要有两个配置&#xff1a; Android Gradle Plugin Version Gradle Version 找一个能正常运行的项目&#xff0c;把它两配置成一样&#xff0c;一般都能解决问…

openssl命令行:RSA的用法-- 终极版

1、生成密钥 openssl genrsa -out test2048_priv.pem 2048 openssl rsa -pubout -in test2048_priv.pem -out test2048_pub.pem openssl genrsa -out test3072_priv.pem 3072 openssl rsa -pubout -in test3072_priv.pem -out test3072_pub.pem openssl genrsa -out test4096…

双系统 + Ubuntu20.04 + ros2 (foxy) git clone -b连接不成功的解决

一、问题描述 虚拟机已经跑通turtlebot3&#xff0c;能成功进行编译&#xff0c;进而执行自主避障&#xff0c;启动house地图&#xff0c;SLAM建图&#xff0c;SLAM导航等任务。但由于虚拟机加载gazebo模型太慢&#xff0c;且考虑到后面计划进行多机通讯&#xff0c;故配置双系…

解决table 操作栏塌陷的问题

1. el-table 塌陷 2. 解决办法 是通过查看官网,看见有一个重新布局的方法 https://element.eleme.cn/#/zh-CN/component/table 3. 代码实现 先将table 绑定ref 调用ref 方法 就ok了

Tomcat服务的部署及配置优化

文章目录 1. Tomcat的相关介绍1.1 Tomcat简介1.2 Tomcat的核心组件1.2.1 Web容器1.2.2 Servlet容器1.2.3 JSP容器 1.3 Tomcat的功能组件1.3.1 connector连接器1.3.2 container容器1.3.2.1 子容器及其相关功能 1.4 主要作用1.5 Tmocat处理请求的过程 2. Tomcata服务部署2.1 安装…

阻塞队列《——》特殊的队列(先进先出)

所谓的阻塞队列&#xff1a;就是带有阻塞特性的《——》线程安全的 如果队列为空&#xff0c;尝试出队列&#xff0c;就会阻塞等待&#xff0c;等到队列不为空为止如果队列为满&#xff0c;尝试入队列&#xff0c;也会阻塞等待&#xff0c;等到队列不为满为止 这个东西非常有…