C++语法——多态,虚函数,纯虚函数,虚函数表,虚继承

news/2024/10/4 6:27:00 标签: 开发语言, c++

多态:

C++实现多态的方法主要包括虚函数、纯虚函数和模板函数

其中虚函数、纯虚函数实现的多态叫动态多态,模板函数、重载等实现的叫静态多态。

区分静态多态和动态多态的一个方法就是看决定所调用的具体方法是在编译期还是运行时,运行时就叫动态多态。

虚函数:

声明:在基类中声明函数为 virtual重写:在派生类中重写基类的虚函数。

当我们使用基类指针或引用指向派生类对象时,通过虚函数的机制,可以调用到派生类中重写的函数,从而实现多态。

构造函数为什么不能是虚函数?

构造函数负责初始化类的对象,每个类都应该有自己的构造函数。

语法:在派生类中,基类的构造函数会被自动调用,用于初始化基类的成员。因此,构造函数没有被覆盖的必要,不需要使用虚函数来实现多态。

虚表:虚函数使用了一种称为虚函数表(vtable)的机制。然而,在调用构造函数时,对象还没有完全创建和初始化,所以虚函数表可能尚未设置。这意味着在构造函数中使用虚函数表会导致未定义的行为。

基类析构函数为什么需要是虚函数?

如果基类析构函数没有定义为虚函数,那么在用基类指针或者引用指向派生类对象,析构时只会调用基类析构函数。定义为虚析构,就会先调用派生类析构函数,再调用基类析构函数。

 纯虚函数:

声明:使用 =0 声明一个纯虚函数。含义:含有纯虚函数的类称为抽象类,不能实例化。

纯虚函数是一种在基类中声明但没有实现的虚函数。它的作用是定义了一种接口,这个接口需要由派生类来实现。

包含纯虚函数的类称为抽象类(Abstract Class)。抽象类仅仅提供了一些接口,但是没有实现具体的功能。作用就是制定各种接口,通过派生类来实现不同的功能,从而实现代码的复用和可扩展性。

虚函数表:

每个拥有虚函数的类都有一个虚函数表,这个表包含了指向每个虚函数最具体的版本的指针。

虚函数表指针指向一个数组,数组的元素就是函数指针,指向各个虚函数的地址,通过函数的索引,我们就能直接访问对应的虚函数。

虚函数表指针(vptr)通常位于对象的起始位置。这意味着它是对象内存块中的第一个成员。

每个派生类对象都有一个vptr,指向其自己的虚函数表。当通过基类指针调用派生类重写的虚函数时,使用的是派生类对象的虚函数表指针(vptr)。

当派生类重写基类的虚函数时,派生类的虚函数表会包含指向派生类版本的函数指针,而不是基类的版本。这样,即使通过基类的指针或引用调用虚函数,也会调用到派生类中重写的版本。

虚继承:

虚继承(Virtual Inheritance)是C++中的一种多重继承机制,用于解决多重继承中的菱形继承问题(钻石继承问题)。在没有虚继承的情况下,如果两个基类都继承自同一个基类,那么派生类会从两个基类中继承两份基类的成员,这可能导致数据冗余和不一致性。

     Base
     /   \
    /     \
  Derived1 Derived2
     \     /
      \   /
       Derived

使用虚继承,Derived就只会继承一份Base类成员。

虚基类指针:

每个使用虚继承的派生类对象都会包含一个虚基类指针(vbptr)。这个指针指向一个指针数组,该数组包含了虚基类的地址和可能的其他信息(如偏移量)。vbptr 允许派生类对象访问其虚基类部分。

内存布局

使用虚继承时,虚基类部分在内存中只有一个实例,并且位于派生类对象的起始位置。基类和派生类的数据成员会按照声明的顺序排列在虚基类部分之后。

vbptr的作用

定位虚基类:vbptr 允许派生类对象定位其虚基类部分的位置。

访问虚基类成员:通过vbptr,可以间接访问虚基类的成员。

解决二义性:确保虚基类在派生类对象中只有一个实例,避免二义性。


http://www.niftyadmin.cn/n/5689610.html

相关文章

arduino点亮墨水屏

前言 入学后有了自己的工位,越发想要用墨水屏做一个自己的工牌。于是开始在淘宝寻找墨水屏,发现所有的墨水屏都是排线接口,不会焊板子的我只能继续寻找其他方案。后来在床上一想,我再买个驱动板不就行了吗?又开始在淘…

知识图谱入门——5:Neo4j Desktop安装和使用手册(小白向:Cypher 查询语言:逐步教程!Neo4j 优缺点分析)

Neo4j简介 Neo4j 是一个基于图结构的 NoSQL 数据库,专门用于存储、查询和管理图形数据。它的核心思想是使用节点、关系和属性来描述数据。图数据库非常适合那些需要处理复杂关系的数据集,如社交网络、推荐系统、知识图谱等领域。 与传统的关系型数据库…

配置Nginx以支持通过HTTPS回源到CDN

要配置Nginx以支持通过HTTPS回源到CDN,你需要确保Nginx已正确配置SSL,并且能够处理来自CDN的HTTPS请求。以下是一个简化的Nginx配置示例,它配置了SSL并设置了代理服务器参数以回源到CDN: server {listen 443 ssl;server_name you…

Linux基础命令reboot详解

reboot 命令用来重新启动 Linux 系统。它是一个非常重要的命令,在需要重启系统进行更新、修复或其他维护任务时使用。以下是 reboot 命令的基本用法及其相关参数的详解。 基本用法 reboot [选项] 常用选项详解 -f, --force 强制重启系统,忽略正常的关…

C++(string类的实现)

1. 迭代器、返回capacity、返回size、判空、c_str、重载[]和clear的实现 string类的迭代器的功能就类似于一个指针,所以我们可以直接使用一个指针来实现迭代器,但如下图可见迭代器有两个,一个是指向的内容可以被修改,另一个则是指…

灰度图像重心(质心)求取算法

1、图像的重心坐标计算 假设我们有一个二维图像,其中 (x, y) 表示图像中每个像素的坐标。I(x, y) 表示图像在 (x, y) 处的亮度(或像素值),通常是灰度值。 图像的重心坐标 (X, Y) 可以通过以下公式计算: X = Σ [x * I(x, y)] / Σ I(x, y) Y = Σ [y * I(x, y)] / Σ I(…

基于深度学习的视频内容理解

基于深度学习的视频内容理解(Video Content Understanding, VCU)是一项关键技术,旨在通过神经网络模型自动分析、解读和提取视频中的语义信息。深度学习方法能够利用视频的时序和空间特性,提取多模态信息(如图像、音频…

进程第四章:环境变量

1.铺垫 1.1环境变量是系统提供的一组namevalue形式的变量,不同的环境变量有不同的用户,通常具有全局属性 1.2多个可执行程序的运行,他们的环境变量的部分数据是不同的,比如说PWD等数据 1.3环境变量里的数据,多为K-V…