继承与多态 - 继承机制、虚函数、纯虚函数
引言
C++ 是一种支持面向对象编程(OOP)的编程语言,继承和多态是 OOP 的两个核心概念。通过继承,我们可以创建新的类,这些新类可以重用现有类的代码,并且可以根据需要进行扩展或修改。多态则允许我们编写更加通用和灵活的代码,使得程序可以在运行时根据对象的实际类型执行不同的操作。
本文将详细介绍 C++ 中的继承机制、虚函数和纯虚函数的概念及其使用方法,帮助读者理解并掌握这些重要的 OOP 特性。
1. 继承机制
1.1 定义继承
继承是面向对象编程中的一个重要特性,它允许一个类(子类)从另一个类(父类或基类)继承属性和行为。通过继承,子类不仅可以重用父类的代码,还可以添加新的功能或修改已有的功能。
在 C++ 中,使用 class
关键字定义类,并通过冒号和关键字 public
、protected
或 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 是一种支持面向对象编程(OOP)的编程语言,继承和多态是 OOP 的两个核心概念。通过继承,我们可以创建新的类,这些新类可以重用现有类的代码,并且可以根据需要进行扩展或修改。多态则允许我们编写更加…...

【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 中,EventEmitter 是一个非常核心的类,它提供了一种事件驱动的机制。几乎所有的 Node.js 核心模块(如 fs, http, net 等)都采用了事件驱…...

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

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

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

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

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

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

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

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

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

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

如何在没有 iCloud 的情况下将联系人从 iPhone 传输到 iPhone
概括 近期iOS 13.5的更新以及苹果公司发布的iPhone SE在众多iOS用户中引起了不小的轰动。此外,不少变化,如暴露通知 API、Face ID 增强功能以及其他在 COVID-19 期间与公共卫生相关的新功能,吸引了 iPhone 用户尝试新 iPhone 并更新到最…...

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

行为模式2.命令模式------灯的开关
行为型模式 模板方法模式(Template Method Pattern)命令模式(Command Pattern)迭代器模式(Iterator Pattern)观察者模式(Observer Pattern)中介者模式(Mediator Pattern…...

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

【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...

Flutter Android修改应用名称、应用图片、应用启动画面
修改应用名称 打开Android Studio,打开对应项目的android文件。 选择app下面的manifests->AndroidManifest.xml文件,将android:label"bluetoothdemo2"中的bluetoothdemo2改成自己想要的名称。重新启动或者重新打包,应用的名称…...

Nginx rewrite 执行顺序(草稿,下次继续编辑)
个人结论: 1.server层ngx_http_rewrite_module模块相关指令按照配置顺序依次执行; 2.server层执行完break指令后,该层级所有跟ngx_http_rewrite_module模块相关的指令都不再被执行,但是不影响其他模块(例如:https://zhuanlan.zhihu.com/p/357…...

01.03周五F34-Day44打卡
文章目录 1. 这家医院的大夫和护士对病人都很耐心。2. 她正跟一位戴金边眼镜的男士说话。3. 那个人是个圆脸。4. 那个就是传说中的鬼屋。5. 他是个很好共事的人。6. 我需要一杯提神的咖啡。7. 把那个卷尺递给我一下。 ( “卷尺” 很复杂吗?)8. 他收到了她将乘飞机来的消息。9.…...

数字货币支付系统开发搭建:构建未来的区块链支付生态
随着数字货币的迅猛发展,越来越多的企业和机构开始关注如何搭建一个高效、安全、可扩展的数字货币支付系统。区块链技术因其去中心化、安全性高、透明性强等优势,已成为开发数字货币支付系统的首选技术。本文将深入探讨数字货币支付系统的开发和搭建过程…...

NLP CH3复习
CH3 3.1 几种损失函数 3.2 激活函数性质 3.3 哪几种激活函数会发生梯度消失 3.4 为什么会梯度消失 3.5 如何解决梯度消失和过拟合 3.6 梯度下降的区别 3.6.1 梯度下降(GD) 全批量:在每次迭代中使用全部数据来计算损失函数的梯度。计算成本…...

BurpSuite2024.11
新增功能 2024 年 11 月 25 日,版本 24.11 此版本引入了站点地图过滤器 Bambdas、匹配和替换 Bambdas、用于 API 扫描的动态身份验证令牌,以及用于入侵者攻击的增强负载管理。我们还进行了多项用户体验改进、性能改进和一些错误修复。 使用 Bambdas 过…...

亚信安全2025年第1期《勒索家族和勒索事件监控报告》
本周态势快速感知 本周全球共监测到勒索事件51起,本周勒索事件数量降至近一年来最低,需注意防范。从整体上看Ransomhub依旧是影响最严重的勒索家族;本周Acrusmedia和Safepay也是两个活动频繁的恶意家族,需要注意防范。本周&#…...

【工具进阶】使用 Nmap 进行有效的服务和漏洞扫描
在渗透测试中,Nmap 是一款功能强大的经典工具。其应用场景广泛,包括主机发现、端口扫描、服务检测等。然而,要充分发挥 Nmap 的潜力,需要遵循科学的流程和规范。本文将为您详细介绍如何使用 Nmap 进行高效的渗透测试,同…...

【工具推荐】XSS 扫描器-XSStrike
介绍 XSStrike 是一个跨站点脚本检测套件,配备四个手写解析器、一个智能有效载荷生成器、一个强大的模糊测试引擎以及速度极快的爬虫。XSStrike 不会像其他工具一样注入有效载荷并检查其是否有效,而是使用多个解析器分析响应,然后通过与模糊…...

Spring Boot 各种事务操作实战(自动回滚、手动回滚、部分回滚)
概念 事务定义 事务,就是一组操作数据库的动作集合。事务是现代数据库理论中的核心概念之一。如果一组处理步骤或者全部发生或者一步也不执行,我们称该组处理步骤为一个事务。当所有的步骤像一个操作一样被完整地执行,我们称该事务被提交。…...