当前位置: 首页 > news >正文

继承与多态 - 继承机制、虚函数、纯虚函数

引言

C++ 是一种支持面向对象编程(OOP)的编程语言,继承和多态是 OOP 的两个核心概念。通过继承,我们可以创建新的类,这些新类可以重用现有类的代码,并且可以根据需要进行扩展或修改。多态则允许我们编写更加通用和灵活的代码,使得程序可以在运行时根据对象的实际类型执行不同的操作。

本文将详细介绍 C++ 中的继承机制、虚函数和纯虚函数的概念及其使用方法,帮助读者理解并掌握这些重要的 OOP 特性。


1. 继承机制

1.1 定义继承

继承是面向对象编程中的一个重要特性,它允许一个类(子类)从另一个类(父类或基类)继承属性和行为。通过继承,子类不仅可以重用父类的代码,还可以添加新的功能或修改已有的功能。

在 C++ 中,使用 class 关键字定义类,并通过冒号和关键字 publicprotected 或 private 来指定继承方式:

class BaseClass {
public:void baseFunction() {std::cout << "Base function called." << std::endl;}
};class DerivedClass : public BaseClass {
public:void derivedFunction() {std::cout << "Derived function called." << std::endl;}
};

在这个例子中,DerivedClass 继承了 BaseClass,因此它可以访问 BaseClass 中的公共成员函数 baseFunction()

1.2 继承方式

C++ 支持三种继承方式:

  • 公有继承 (public):子类可以访问父类的公有和保护成员,但不能访问私有成员。子类的对象也可以访问父类的公有成员。
  • 保护继承 (protected):子类可以访问父类的公有和保护成员,但不能访问私有成员。子类的对象不能访问父类的任何成员。
  • 私有继承 (private):子类只能访问父类的公有和保护成员,但这些成员在子类中变为私有成员。子类的对象不能访问父类的任何成员。

选择合适的继承方式取决于具体的设计需求。通常情况下,公有继承是最常用的继承方式。

1.3 构造函数和析构函数

当一个类继承自另一个类时,构造函数和析构函数的行为也会受到影响。子类的构造函数会先调用父类的构造函数,然后再初始化自己的成员变量。同样,子类的析构函数会在父类的析构函数之前被调用。

class BaseClass {
public:BaseClass() {std::cout << "Base constructor called." << std::endl;}~BaseClass() {std::cout << "Base destructor called." << std::endl;}
};class DerivedClass : public BaseClass {
public:DerivedClass() {std::cout << "Derived constructor called." << std::endl;}~DerivedClass() {std::cout << "Derived destructor called." << std::endl;}
};int main() {DerivedClass obj;return 0;
}

输出结果:

Base constructor called.
Derived constructor called.
Derived destructor called.
Base destructor called.

2. 虚函数

2.1 定义虚函数

虚函数是实现多态的关键。通过虚函数,我们可以在派生类中重写基类的函数,并在运行时根据对象的实际类型调用相应的函数版本。

在 C++ 中,使用 virtual 关键字来声明虚函数:

class BaseClass {
public:virtual void show() {std::cout << "Base class show function." << std::endl;}
};class DerivedClass : public BaseClass {
public:void show() override {std::cout << "Derived class show function." << std::endl;}
};

在这个例子中,BaseClass 中的 show() 函数被声明为虚函数,而 DerivedClass 重写了这个函数。当我们通过基类指针或引用来调用 show() 函数时,实际调用的是派生类的版本:

int main() {BaseClass* ptr = new DerivedClass();ptr->show(); // 输出: Derived class show function.delete ptr;return 0;
}

2.2 虚函数表

C++ 编译器为每个包含虚函数的类生成一个虚函数表(vtable),其中包含了该类所有虚函数的地址。当通过基类指针或引用调用虚函数时,编译器会根据对象的实际类型查找对应的虚函数地址并调用它。

2.3 override 和 final 关键字

  • override:用于显式声明派生类中的函数是重写基类的虚函数。如果派生类中的函数名称或签名不匹配基类的虚函数,编译器会报错。
  • final:用于禁止派生类进一步重写某个虚函数。
class BaseClass {
public:virtual void show() = 0; // 纯虚函数
};class DerivedClass : public BaseClass {
public:void show() override final {std::cout << "Derived class show function." << std::endl;}
};

3. 纯虚函数

3.1 定义纯虚函数

纯虚函数是一种特殊的虚函数,它没有具体的实现,只提供函数声明。包含纯虚函数的类被称为抽象类,不能直接实例化。纯虚函数的作用是为派生类提供一个接口,要求派生类必须实现该函数。

在 C++ 中,使用 = 0 来声明纯虚函数:

class BaseClass {
public:virtual void show() = 0; // 纯虚函数
};class DerivedClass : public BaseClass {
public:void show() override {std::cout << "Derived class show function." << std::endl;}
};

3.2 抽象类

包含纯虚函数的类称为抽象类。抽象类不能直接实例化,但可以通过派生类来实现其接口。

int main() {// BaseClass obj; // 错误:不能实例化抽象类DerivedClass obj;obj.show(); // 正确:通过派生类实例化并调用return 0;
}

3.3 混合使用虚函数和纯虚函数

有时我们希望某些函数在基类中有默认实现,而另一些函数则强制派生类实现。这时可以混合使用虚函数和纯虚函数:

class BaseClass {
public:virtual void show() = 0; // 纯虚函数virtual void display() {std::cout << "Base class display function." << std::endl;}
};class DerivedClass : public BaseClass {
public:void show() override {std::cout << "Derived class show function." << std::endl;}
};

总结

继承和多态是 C++ 面向对象编程的核心特性。通过继承,我们可以重用代码并扩展功能;通过虚函数和纯虚函数,我们可以实现多态,编写更加灵活和通用的代码。理解这些概念对于编写高质量的 C++ 程序至关重要。

希望本文能够帮助您更好地理解 C++ 中的继承机制、虚函数和纯虚函数。如果您有任何问题或建议,请随时留言讨论!


参考资料:

  • C++ Primer
  • Effective Modern C++

相关文章:

继承与多态 - 继承机制、虚函数、纯虚函数

引言 C 是一种支持面向对象编程&#xff08;OOP&#xff09;的编程语言&#xff0c;继承和多态是 OOP 的两个核心概念。通过继承&#xff0c;我们可以创建新的类&#xff0c;这些新类可以重用现有类的代码&#xff0c;并且可以根据需要进行扩展或修改。多态则允许我们编写更加…...

【QT】C++线程安全的单例模板

模板代码 #pragma once #include <mutex> #include <atomic>// CRTP基类模板 Curiously Recurring Template Parttern—奇异递归模板模式。 template <typename T> class SingletonCRTP { public:// 禁止拷贝构造和赋值操作SingletonCRTP(const SingletonCR…...

node.js内置模块之---EventEmitter 类

EventEmitter 类什么作用 EventEmitter 类的主要方法 EventEmitter 类什么作用 在 Node.js 中&#xff0c;EventEmitter 是一个非常核心的类&#xff0c;它提供了一种事件驱动的机制。几乎所有的 Node.js 核心模块&#xff08;如 fs, http, net 等&#xff09;都采用了事件驱…...

SWM221系列芯片之电机应用及控制

经过对SWM221系列的强大性能及外设资源&#xff0c;TFTLCD彩屏显示及控制进行了整体介绍后&#xff0c;新迎来我们的电控篇---SWM221系列芯片之电机应用及控制。在微控制器市场面临性能、集成度与成本挑战的当下&#xff0c;SWM221系列芯片以其卓越性能与创新设计&#xff0c;受…...

单片机-静动态数码管实验

P0控制数码管 &#xff0c;P0低电平 P1,P2,P3高电平 1、静态数码管 需求&#xff1a;数码管显示0&#xff0c;即让p0端口输出数字0的段码0x3f(共阴) #include "reg52.h" typedef unsigned int u16; typedef unsigned char u8; //数码管显示数字的数组 共阴极 …...

Fabric环境部署

官方下载文档&#xff1a;A Blockchain Platform for the Enterprise — Hyperledger Fabric Docs main documentation 1.1 创建工作目录 将Fabric代码按照GO语言的推荐方式进行存放&#xff0c;创建目录结构并切换到该目录下。具体命令如下&#xff1a; mkdir -p ~/go/src/g…...

VisualRules规则引擎语法介绍

VisualRules规则引擎是一款用于处理复杂业务规则的引擎&#xff0c;广泛应用于金融、保险、医疗等领域。它通过将业务逻辑从代码中分离出来&#xff0c;以可配置的方式管理和执行规则。以下是VisualRules规则引擎的基本语法和使用方法&#xff1a; 1. 规则定义 规则通常由 条件…...

enzymejest TDD与BDD开发实战

一、前端自动化测试需要测什么 1. 函数的执行逻辑&#xff0c;对于给定的输入&#xff0c;输出是否符合预期。 2. 用户行为的响应逻辑。 - 对于单元测试而言&#xff0c;测试粒度较细&#xff0c;需要测试内部状态的变更与相应函数是否成功被调用。 - 对于集成测试而言&a…...

Statistic for ML

statistical concept 統計學概念 免費完整內容 PMF and CDF PMF定義的值是P(Xx)&#xff0c;而CDF定義的值是P(X < x)&#xff0c;x為所有的實數線上的點。 probability mass function (PMF) 概率質量函數 p X ( x ) P ( X x ) pX(x)P(Xx) pX(x)P(Xx) 是離散隨機變數…...

Django 中数据库迁移命令

在 Django 中&#xff0c;python manage.py makemigrations、python manage.py sqlmigrate polls 0003 和 python manage.py migrate 是与数据库迁移相关的重要命令。它们的作用和对应内容如下&#xff1a; 1. python manage.py makemigrations 功能: 此命令会根据你的模型文…...

【机器学习】 卷积神经网络 (CNN)

文章目录 1. 为什么需要 CNN2. CNN 的架构3. 卷积层4. 池化层5. CNN 的应用 1. 为什么需要 CNN 前提&#xff1a;利用前置知识&#xff0c;去掉全连接神经网络中的部分参数&#xff0c;提升学习效率。本质&#xff1a;在 DNN 之前加上 CNN&#xff0c;先去除不必要的参数&…...

Linux中操作中的无痕命令history技巧

当我们需要查看Linux下的操作记录时&#xff0c;就可以用history命令来查看历史记录 1、关闭history记录功能&#xff0c;如果不想让别人看到自己在Linux上的操作命令&#xff0c;可以用这个命令 set o history 2、打开history记录功能 set -o history3、清空记录 histor…...

在CE自动汇编里调用lua函数

CE自动汇编模板里有一个是调用lua函数&#xff0c;但是关于如何使用的资料很少&#xff0c;结果问AI也是各种错误回答&#xff0c;还各种误导... 下面是32位游戏的例子&#xff1a; loadlibrary(luaclient-i386.dll) luacall(openLuaServer(CELUASERVER))CELUA_ServerName: d…...

如何在没有 iCloud 的情况下将联系人从 iPhone 传输到 iPhone

概括 近期iOS 13.5的更新以及苹果公司发布的iPhone SE在众多iOS用户中引起了不小的轰动。此外&#xff0c;不少变化&#xff0c;如暴露通知 API、Face ID 增强功能以​​及其他在 COVID-19 期间与公共卫生相关的新功能&#xff0c;吸引了 iPhone 用户尝试新 iPhone 并更新到最…...

欧科云链研究院:ChatGPT 眼中的 Web3

编辑&#xff5c;OKG Research 转眼间&#xff0c;2024年已经进入尾声&#xff0c;Web3 行业经历了热闹非凡的一年。今年注定也是属于AI的重要一年&#xff0c;OKG Research 决定拉上 ChatGPT 这位“最懂归纳的AI拍档”&#xff0c;尝试把一整年的研究内容浓缩成精华。我们一共…...

行为模式2.命令模式------灯的开关

行为型模式 模板方法模式&#xff08;Template Method Pattern&#xff09;命令模式&#xff08;Command Pattern&#xff09;迭代器模式&#xff08;Iterator Pattern&#xff09;观察者模式&#xff08;Observer Pattern&#xff09;中介者模式&#xff08;Mediator Pattern…...

Kerberos用户认证-数据安全-简单了解-230403

hadoop安全模式官方文档&#xff1a;https://hadoop.apache.org/docs/r2.7.2/hadoop-project-dist/hadoop-common/SecureMode.html kerberos是什么 kerberos是计算机网络认证协议&#xff0c;用来在非安全网络中&#xff0c;对个人通信以安全的手段进行身份认证。 概念&#…...

【Multisim用74ls92和90做六十进制】2022-6-12

缘由Multisim如何用74ls92和90做六十进制-其他-CSDN问答 74LS92、74LS90参考...

滴滴工作流引擎Turbo与logicFlow研究

目录 logicFlow turbo 工作流引擎很多,也都提供了前端UI库,但是太过于冗杂了,元数据表都几十个,logincFlow和Turbo的组合提供了轻量化方式,turbo后端代码只有5个元数据表,logicFlow也提供了bpm的相关扩展功能,但缺点是turbo社区不活跃,logicFlow个人认为跟echarts这种…...

AE Pinnacle 10x6 kW DeviceNet MDXL User r Manual

AE Pinnacle 10x6 kW DeviceNet MDXL User r Manual...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式&#xff0c;然后找到相应的网卡&#xff08;可以查看自己本机的网络连接&#xff09; windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置&#xff0c;选择刚才配置的桥接模式 静态ip设置&#xff1a; 我用的ubuntu24桌…...

搭建DNS域名解析服务器(正向解析资源文件)

正向解析资源文件 1&#xff09;准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2&#xff09;服务端安装软件&#xff1a;bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...

STM32HAL库USART源代码解析及应用

STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解

文章目录 一、开启慢查询日志&#xff0c;定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...