C++学习笔记-基类、派生类与虚函数关系

在C++的面向对象编程中,基类(Base Class)、派生类(Derived Class)以及虚函数(Virtual Functions)构成了多态性的基石。这三者之间的关系错综复杂而又紧密相连,它们共同支撑起C++中复杂而灵活的类继承体系。

一、基类与派生类的基础

1.1 基类的定义与作用

基类(Base Class)是面向对象编程中继承的起点,它定义了派生类将继承的属性和行为。基类可以包含数据成员和成员函数,这些数据成员和成员函数可以被派生类继承和使用。基类的主要作用是为派生类提供一个共同的接口和一组基本的实现,使得派生类可以共享基类的代码和数据结构。

1.2 派生类的定义与继承方式

派生类(Derived Class)是从一个或多个基类继承而来的类。在C++中,派生类通过继承机制获得基类的成员(包括数据成员和成员函数),并且可以在此基础上添加新的成员或修改继承而来的成员。C++支持三种继承方式:公有继承(public inheritance)、保护继承(protected inheritance)和私有继承(private inheritance)。

  • 公有继承:基类的公有成员和保护成员在派生类中保持原有的访问级别(公有或保护),而基类的私有成员在派生类中仍然不可访问。
    保护继承:基类的公有成员和保护成员在派生类中都将变为保护成员,私有成员仍然不可访问。
  • 私有继承:基类的所有成员(公有成员、保护成员和私有成员)在派生类中都将变为私有成员,这意味着派生类外部的代码无法直接访问这些成员。

1.3 继承与多态性的关系

继承是面向对象编程中实现多态性的基础。多态性允许通过基类类型的指针或引用来调用派生类中的成员函数,而具体调用哪个函数则是在运行时根据对象的实际类型来确定的。这种机制使得程序更加灵活和可扩展。

二、虚函数与多态性

2.1 虚函数的定义与作用

虚函数是C++中实现多态性的关键机制之一。在基类中,使用virtual关键字声明的成员函数称为虚函数。虚函数允许在派生类中被重写(Override),即派生类可以提供一个与基类虚函数具有相同签名的函数,以替换基类中的实现。

虚函数的主要作用是实现多态性。通过基类指针或引用来调用虚函数时,将根据实际对象的类型来决定调用哪个版本的函数。这种机制使得我们可以在不知道具体对象类型的情况下,编写出能够处理多种类型的代码。

2.2 虚函数的实现机制

虚函数的实现依赖于C++的虚函数表(Virtual Table,简称vtable)和虚指针(Virtual Pointer,简称vptr)。每个包含虚函数的类都有一个虚表,虚表中存储了该类中所有虚函数的地址。当对象被创建时,编译器会在对象的内存布局中添加一个指向其虚表的指针(vptr)。通过这个指针,程序可以在运行时确定要调用的虚函数的具体地址。

2.3 虚析构函数

虚析构函数是一个特殊的虚函数,它用于在通过基类指针删除派生类对象时,确保能够调用到派生类的析构函数,从而正确释放派生类对象所占用的资源。如果基类的析构函数不是虚函数,那么在删除派生类对象时,只会调用基类的析构函数,而不会调用派生类的析构函数,这可能导致资源泄露或其他问题。

三、基类、派生类与虚函数的关系

3.1 继承与虚函数的关系

在C++中,虚函数通常定义在基类中,并在派生类中被重写。通过基类指针或引用来调用虚函数时,将根据实际对象的类型来调用相应的函数版本。这种机制使得我们可以在不知道具体对象类型的情况下,编写出能够处理多种类型的代码。

3.2 多态性的实现

多态性的实现依赖于基类中定义的虚函数和派生类中对这些虚函数的重写。当通过基类类型的指针或引用来调用虚函数时,程序会在运行时根据对象的实际类型来确定要调用的函数版本。这种机制使得我们可以编写出更加灵活和可扩展的代码。

3.3 虚函数与纯虚函数

在C++中,纯虚函数是一种特殊的虚函数,它在基类中只声明而不实现,并且在类声明结束时使用= 0来标识。包含至少一个纯虚函数的类被称为抽象类(Abstract Class),抽象类不能被实例化。纯虚函数的主要作用是为派生类提供一个必须实现的接口,从而确保派生类具有某种特定的行为。
###3. 4. 虚函数与抽象基类
虽然虚函数可以定义在基类中并在派生类中被重写,但基类本身并不需要是抽象的。然而,当基类中包含至少一个纯虚函数时,该基类就变成了抽象基类。纯虚函数是一种特殊的虚函数,它在基类中只声明而不实现(使用= 0来标识)。抽象基类不能被实例化,但它可以作为派生类的基类。通过定义纯虚函数,抽象基类为派生类提供了一个必须实现的接口,从而确保了派生类具有某种特定的行为。

四、程序示例

下面是一个简单的C++示例,它展示了基类、派生类和虚函数之间的关系。这个示例包括一个基类Animal,它定义了一个虚函数makeSound(),以及两个派生类Dog和Cat,它们分别重写了makeSound()函数。

#include <iostream>  
#include <string>  // 基类  
class Animal {  
public:  // 虚函数  virtual void makeSound() const {  std::cout << "Some generic animal sound" << std::endl;  }  // 虚析构函数(好习惯,尽管在这个简单示例中可能不是必需的)  virtual ~Animal() {}  
};  // 派生类 Dog  
class Dog : public Animal {  
public:  // 重写虚函数  void makeSound() const override {  std::cout << "Woof!" << std::endl;  }  
};  // 派生类 Cat  
class Cat : public Animal {  
public:  // 重写虚函数  void makeSound() const override {  std::cout << "Meow!" << std::endl;  }  
};  // 主函数,展示多态性  
int main() {  // 基类指针,指向派生类对象  Animal* myAnimal1 = new Dog();  Animal* myAnimal2 = new Cat();  // 通过基类指针调用虚函数,展示多态性  myAnimal1->makeSound(); // 输出: Woof!  myAnimal2->makeSound(); // 输出: Meow!  // 清理资源  delete myAnimal1;  delete myAnimal2;  return 0;  
}
  • 基类 Animal:

定义了一个虚函数 makeSound(),该函数在基类中有一个默认实现,输出一个通用的动物声音。
定义了一个虚析构函数,这是一个好习惯,因为它允许通过基类指针删除派生类对象时,能够调用到派生类的析构函数,从而正确释放资源。然而,在这个简单的示例中,由于我们没有在基类或派生类中分配任何动态内存,所以虚析构函数可能不是必需的。但在更复杂的场景中,它是非常重要的。

  • 派生类 Dog 和 Cat:

分别从基类 Animal 继承而来。
重写了基类中的虚函数 makeSound(),提供了各自的实现(狗叫“Woof!”和猫叫“Meow!”)。

  • 主函数 main:

创建了两个基类类型的指针 myAnimal1 和 myAnimal2,但它们分别指向 Dog 和 Cat 类型的对象。
通过这两个基类指针调用 makeSound() 函数时,由于 makeSound() 是虚函数,所以调用的是指针所指向对象的实际类型(即 Dog 或 Cat)中的函数版本,这展示了多态性。

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

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

相关文章

《后端程序猿 · @Value 注释说明》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

定制ESXi 8镜像教程

本文将详细说明从安装 PowerCLI 到定制 ESXi 8 镜像的整个过程。 安装 VMware PowerCLI 1. 打开 PowerShell 打开 PowerShell&#xff1a; 在 Windows 搜索栏中输入 PowerShell&#xff0c;然后右键点击“Windows PowerShell”&#xff0c;选择“以管理员身份运行”。你会看…

【Unity PC端打包exe封装一个并添加安装引导】

Unity PC端打包exe封装一个并添加安装引导 比特虫在线制作ico图标ico图标转换工具 选中打包出来的所有文件和ico图标 右键 使用RAR软件 添加到压缩文件 两个名称要相同 设置完点击确认等待压缩完成 然后就可以使用 Smart Install Maker制作引导安装程序了

过滤出List集合的元素是Person对象,过滤出每个元素非null的name字段得到String类型的集合

import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { List people Arrays.asList( new Person(“Alice”, 30), new Person(null, 25), new Person(“Charlie”, 35) ); //…

Thinkphp5实现前后端通过接口通讯基本操作方法

在ThinkPHP5框架中&#xff0c;实现前后端通过接口通讯是一个常见的需求&#xff0c;尤其是在开发RESTful API时。下面是一个基本的步骤指南&#xff0c;用于设置ThinkPHP5来创建API接口&#xff0c;并使前端能够通过HTTP请求与后端进行通讯。 1. 创建API模块 首先&#xff0…

解决Pycharm找不到conda可执行文件

解决&#xff1a; 在 ‘Conda 可执行文件’ 的输入框里面&#xff0c;找到并选中 anaconda\library\bin 路径下的“ conda.bat ” ,再点击‘ 加载环境 ’&#xff0c;即可出现 ‘ 使用现有环境 ’ 的输入框&#xff0c;如图所示。

【实现100个unity特效之8】使用ShaderGraph实现2d贴图中指定部分局部发光效果

最终效果 寒冰法师 火焰法师 文章目录 最终效果寒冰法师火焰法师 素材一、功能分析实现方法基本思路Unity的Bloom后处理为什么关键部位白色&#xff1f;最终结果 二、 新建URP项目三、合并图片四、使用PS制作黑白图片方法一 手动涂鸦方法二 魔棒工具1. 拖入图片进PS&#xff0…

Unity3d打包到Android

本文参考&#xff1a; Unity3D新手教程&#xff1a;如何打包发布到Android_哔哩哔哩_bilibili 一、Unity 打包Android的环境搭建 1、工具安装 Unity Hub已经集成了Android的环境搭建。 选择Add modules 然后安装Android Build Support下的所有工具。 如果各个工具都安装成功…

如何使用 win32com 库

以下是如何使用 win32com 库的基本步骤&#xff1a; 1. 安装 pywin32 win32com 是 pywin32 库的一部分&#xff0c;首先需要安装 pywin32&#xff1a; pip install pywin322. 导入 win32com.client import win32com.client3. 连接到 COM 对象 使用 win32com.client.Dispat…

给Windows系统中注入服务,即windwos守护进程

最近总是在windwos环境下测试nginx&#xff0c;总是需要频繁重启nginx服务。于是考虑有没有可能把nginx加入到系统服务的操作。在网上找了一大堆资料&#xff0c;现在来总结一下&#xff01; 方法1&#xff1a;利用nssm工具实现 这是一个守护进程的软件&#xff0c;可以在win…

FastGPT 知识库搜索测试功能解析(二)

目录 一、代码解析 1.1 searchTest.ts 1.2 controller.ts 本文接上一篇文章FastGPT 知识库搜索测试功能解析 对具体代码进行解析。 一、代码解析 FastGPT 知识库的搜索测试功能主要涉及两个文件,分别是 searchTest.ts 和 controller.ts 文件,下面分别进行介绍。 1.1 se…

关于海康网络摄像头使用VLC或者Opencv拉流有延迟的问题

环境&#xff1a;Windows VLC / Opencv-Python 先说结论&#xff0c;我用VLC或者Pyhton opencv直接拉取海康网络摄像头的rtsp流&#xff0c;会有1-2s延时&#xff0c;特别明显。后来搜到这边文章&#xff0c;解决了问题&#xff1a; 如何降低海康、大华等网络摄像头调用的高…

Optima: 一个用于 Tapestri 平台的单细胞多组学数据分析的开源 R 包

分子条形码技术的最新进展使得在单细胞水平进行下一代转录组测序成为可能&#xff0c;例如10 Genomics Chromium和DropSeq。此外&#xff0c;CITE-seq 的出现使得可以在对单个细胞进行转录组分析的基础上同时对表面蛋白进行分析。同时&#xff0c;为了表征 DNA 和蛋白质谱&…

ubuntu那些ppa源在哪

Ubuntu中的 PPA 终极指南 - UBUNTU粉丝之家 什么是PPA PPA 代表个人包存档。 PPA 允许应用程序开发人员和 Linux 用户创建自己的存储库来分发软件。 使用 PPA&#xff0c;您可以轻松获取较新的软件版本或官方 Ubuntu 存储库无法提供的软件。 为什么使用PPA&#xff1f; 正如…

添加动态云层

<template> <div class"topbox"> xx卫星管理 </div> <div class"selectbox"> <div class"title"> 卫星列表 </div> <el-table :data"tableData" style"width: 100%;height:230px;" …

亚信安慧AntDB-M负载均衡

负载均衡是分布式系统中常用的技术&#xff0c;主要是将工作任务均衡分布到系统的各个资源点上&#xff0c;可以充分利用系统资源。 AntDB-M分布式内存数据库节点角色可以分为管理节点(MN)、计算节点(CN)和数据节点(DN)三种。管理节点收到客户端连接请求后&#xff0c;会经由负…

IEEE官方列表会议 | 第三届能源与环境工程国际会议(CFEEE 2024)

会议简介 Brief Introduction 2024年第三届能源与环境工程国际会议(CFEEE 2024) 会议时间&#xff1a;2024年12月2日-4日 召开地点&#xff1a;澳大利亚凯恩斯 大会官网&#xff1a;CFEEE 2024-2024 International Conference on Frontiers of Energy and Environment Engineer…

elementPuls 表格反选实现

真的在网上搜了很多资料发现根本实现不了反选 最下面有示例 然后去看了下官网 发现官网有教你怎么选中某个值的方法 官网中的”多选“ 官网地址 <template><el-tableref"multipleTableRef":data"tableData"style"width: 100%"selectio…

MySQL 和 SQL Server 中的连表更新 UPDATE JOIN 写法比较

MySQL 和 SQL Server 中的连表更新 UPDATE JOIN 写法比较 一、前言1. MySQL 写法1.1 解释 2. SQL Server 写法2.1 解释 二、总结 一、前言 在关系型数据库管理系统&#xff08;RDBMS&#xff09;中&#xff0c;使用 UPDATE 语句进行表格更新是非常常见的操作。特别是当需要根据…

【C#】visual studio打包winForm(依赖DLL)为安装程序exe

0.简介 IDE&#xff1a;VS2022 平台&#xff1a;C# .NetFramework4.7 WinForm界面 有GDAL、EEplus库的依赖&#xff0c;所以在其他未安装环境的电脑中功能无法使用。 1. 安装 1.1 运行文件 在VS扩展中选择管理扩展&#xff0c;Microsoft Visual Studio Installer Projects …