C++面向对象三大特性--多态
C++面向对象三大特性–多态
文章目录
- C++面向对象三大特性--多态
- 1.虚函数(Virtual Function)
- 2.纯虚函数(Pure Virtual Function)和抽象类(Abstract Class)
- 3.重写(Override)
- 4.动态绑定(Dynamic Binding)或迟绑定(Late Binding)
- 5.虚析构函数和纯虚析构
- 5.1虚析构函数
- 5.2纯虚析构函数
- 5.3总结
C++中的多态(Polymorphism)是一种面向对象编程的重要特性,它允许你使用一个接口来表示不同的类型。C++中的多态主要通过虚函数(Virtual Functions)来实现,包括静态多态(编译时多态,主要是函数重载和模板)和动态多态(运行时多态)。下面将介绍C++中动态多态的基础语法:
1.虚函数(Virtual Function)
虚函数是实现动态多态的关键。在基类中声明函数为虚函数,使得派生类可以重写该函数。虚函数的声明需要在基类的函数声明前加上virtual关键字。
class Base {
public:virtual void display() { /* 默认实现 */ }// 注意:析构函数建议声明为虚函数,以确保通过基类指针删除对象时能正确调用派生类的析构函数virtual ~Base() {}
};class Derived : public Base {
public:void display() override { /* 重写实现 */ }
};//
// Created by 86189 on 2024/6/22.
//
#include <iostream>using namespace std;class Animal {
public:virtual void speak() {cout << "Animal speak" << endl;}
};class Dog : public Animal {void speak() override {cout << "Dog speak" << endl;}
};class Cat : public Animal {void speak() override {cout << "Cat speak" << endl;}
};void doWork(Animal &p) {p.speak();
}int main() {Animal *p = new Dog(); // 动态绑定 父类的指针指向子类对象p->speak();Animal *p2 = new Cat();p2->speak();Cat c;Dog d;doWork(c); //父类的引用指向子类对象doWork(d);delete p;delete p2;return 0;
}
2.纯虚函数(Pure Virtual Function)和抽象类(Abstract Class)
纯虚函数是在基类中没有具体实现的虚函数,要求派生类必须提供实现。含有纯虚函数的类称为抽象类,不能实例化。
class Base {
public:virtual void func() = 0; // 纯虚函数
};// Base类现在是一个抽象类,不能直接创建对象
// Base b; // 错误class Derived : public Base {
public:void func() override { /* 实现 */ }
};//
// Created by 86189 on 2024/6/22.
//
#include <iostream>
using namespace std;class Base {
public:virtual void func() = 0; //纯虚函数
};//派生类必须重写纯虚函数 否则无法实例化对象
class Derived : public Base {
public:void func() override {cout << "Derived::func()" << endl;}
};int main() {Base *p = new Derived();p->func();return 0;
}
3.重写(Override)
在派生类中重新定义基类的虚函数称为重写。使用override关键字可以明确指出某个函数是重写的意图,同时编译器会进行检查,确保该函数确实是在重写基类的一个虚函数。
class Derived : public Base {
public:void display() override { /* 重写实现 */ }
};
4.动态绑定(Dynamic Binding)或迟绑定(Late Binding)
动态绑定是运行时根据对象的实际类型来决定调用哪个函数的机制。这要求通过基类指针或引用来调用虚函数。如果直接通过对象名调用,则仍然是静态绑定。
Base* basePtr = new Derived();
basePtr->display(); // 运行时会调用Derived类的display()
delete basePtr;
5.虚析构函数和纯虚析构
5.1虚析构函数
基类的析构函数应该声明为虚函数,以确保当通过基类指针删除派生类对象时,能够正确地调用派生类的析构函数,避免内存泄漏。
在多态场景中,如果基类的析构函数不是虚函数,当通过基类指针删除派生类对象时,只会调用基类的析构函数,而派生类特有的资源可能不会被正确释放,从而导致资源泄漏或更严重的问题。
解决这个问题的方法很简单,就是确保所有包含纯虚函数的抽象基类,其析构函数也应该是虚函数。这样,无论通过基类指针指向的是基类对象还是派生类对象,都能够保证调用到正确的析构函数链,从派生类开始,逐级向上调用到基类的析构函数,彻底释放资源。
//
// Created by 86189 on 2024/6/23.
//
#include <iostream>
using namespace std;class Base {
public:virtual void func () = 0;virtual ~Base() {cout << "Base::~Base()" << endl;}
};class Derived : public Base {
public:void func() override {cout << "Derived::func()" << endl;p = new int(10);}~Derived() override {cout << "Derived::~Derived()" << endl;delete p;}int *p{};
};int main() {Derived d;Base *p = new Derived();p->func();delete p;return 0;
}
- 定义:当在基类中将析构函数声明为虚函数时,它就成为了虚析构函数。声明时不需要赋值为0,格式为
virtual ~ClassName() {}。 - 用途:确保当通过基类指针或引用删除派生类对象时,能够调用到派生类的析构函数,从而正确释放派生类特有的资源。如果不声明为虚析构,那么仅基类的析构函数会被调用,可能导致派生类的资源泄露。
- 实例化:声明了虚析构函数的类仍然可以实例化对象,不是抽象类。
5.2纯虚析构函数
- 定义:在基类中将析构函数声明为纯虚函数,即在声明后加上
= 0,格式为virtual ~ClassName() = 0;。需要注意的是,纯虚函数需要在类外提供定义。 - 用途:与虚析构函数类似,用于确保多态销毁时调用正确的析构函数。但除此之外,声明了纯虚析构函数的类自动成为抽象类。
- 实例化:拥有纯虚析构函数的类是抽象类,这意味着不能直接实例化此类的对象。抽象类的主要目的是作为其他类的基类,强制要求派生类实现某些纯虚函数(不仅仅是析构函数)。
//
// Created by 86189 on 2024/6/23.
//
#include <iostream>
using namespace std;class Base {
public:virtual ~Base() = 0; // 纯虚析构函数 确保了派生类中内存可以被释放
};
class Derived : public Base {
public:void func() {cout << "func()" << endl;p = new int(10);}~Derived() override {cout << "~Derived()" << endl; //纯虚析构保证了释放派生类中申请的内存delete p;p = nullptr;}int *p{};
};Base::~Base() {cout << "Base()" << endl;
}int main() {Derived d;d.func();Base *p = new Derived();delete p;return 0;
}
5.3总结
两者都用于支持多态性下的正确资源管理,但纯虚析构函数额外具有将类定义为抽象类的特性。选择使用哪一种取决于你的设计需求:如果你希望基类可以实例化,并且需要多态性的析构,使用虚析构函数;如果你的基类根本就不应该直接实例化,而总是作为派生类的基类,并且同样需要多态性的析构,那么纯虚析构函数更为合适。
相关文章:
C++面向对象三大特性--多态
C面向对象三大特性–多态 文章目录 C面向对象三大特性--多态1.虚函数(Virtual Function)2.纯虚函数(Pure Virtual Function)和抽象类(Abstract Class)3.重写(Override)4.动态绑定&am…...
啥移动硬盘格式能更好兼容Windows和Mac系统 NTFS格式苹果电脑不能修改 paragon ntfs for mac激活码
对于同时使用Windows和Mac操作系统的用户而言,选择一个既能确保数据互通又能满足大容量存储需求的移动硬盘格式尤为重要。下面我们来看看啥移动硬盘格式能更好兼容Windows和Mac系统,NTFS格式苹果电脑不能修改的相关内容。 一、啥移动硬盘格式能更好兼容…...
【面试】i++与++i的区别
目录 1. 情况11.1 i1.2 i 2. 情况23. 情况34. 情况4 1. 情况1 1.1 i 1.代码块 public void test(){int i 10;i;System.out.println(i);}2.字节码 0 bipush 102 istore_13 iinc 1 by 16 getstatic #2 <java/lang/System.out : Ljava/io/PrintStream;>9 iload_1 10 inv…...
使用 devtool 本地调试 nodejs
安装 # 全局安装 $ npm install devtool -g # 或临时安装 $ npx devtool [file] [opts]用法 Usage:devtool [入口文件] [opts]Options:--watch, -w enable file watching (for development) # 动态检测文件变更,不用每次手动重启--quit, -q …...
element-plus 表单组件 之element-form
elment-plus的表单组件的标签有el-form,el-form-item。 单个el-form标签内包裹若干个el-form-item,el-form-item包裹具体的表单组件,如输入框组件,多选组件,日期组件等。 el-form组件的主要作用是:提供统一的布局给其他表单组件&…...
redis持久化主从哨兵分片集群
文章目录 1. 单点Redis的问题数据丢失问题并发能力问题故障恢复问题存储能力问题 2. Redis持久化 -> 数据丢失问题RDB持久化linux单机安装Redis步骤RDB持久化与恢复示例(详细)RDB机制RDB配置示例RDB的fork原理总结 AOF持久化AOF配置示例(详…...
IOS Swift 从入门到精通: 结构体的访问控制、静态属性和惰性
文章目录 初始化器引用当前实例惰性属性静态属性和方法访问控制总结初始化器 初始化器是一种特殊方法,可提供创建结构体的不同方式。所有结构体都默认带有一个初始化器,称为成员初始化器- 它会要求您在创建结构体时为每个属性提供一个值。 User如果我们创建一个具有一个属性…...
SQL题:未完成率较高的50%用户近三个月答卷情况
SQL题:未完成率较高的50%用户近三个月答卷情况 这是一道牛客网上SQL进阶图库中的一道困难题目,个人花了近两个小时才通过所有用例。之所以想记录下来是因为这道题算是一个很考验基本功的题目,也不乏一些SQL中的技巧。下面我们逐步分析&#…...
挑战与机遇的交织
AI与音乐创作:挑战与机遇的交织 引言 近年来,人工智能技术的迅猛发展使得其在各个领域都展现出了巨大的潜力和影响力,音乐创作领域也不例外。最近上线的音乐大模型,无疑是这一趋势的一个重要节点,它极大地降低了素人…...
Java项目:基于SSM框架实现的精品酒销售管理系统分前后台【ssm+B/S架构+源码+数据库+毕业论文】
一、项目简介 本项目是一套基于SSM框架实现的精品酒销售管理系统 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试,eclipse或者idea 确保可以运行! 该系统功能完善、界面美观、操作简单、功…...
[论文笔记]Are Large Language Models All You Need for Task-Oriented Dialogue?
引言 今天带来论文Are Large Language Models All You Need for Task-Oriented Dialogue?的笔记。 主要评估了LLM在完成多轮对话任务以及同外部数据库进行交互的能力。在明确的信念状态跟踪方面,LLMs的表现不及专门的任务特定模型。然而,如果为它们提…...
Django 模版过滤器
Django模版过滤器是一个非常有用的功能,它允许我们在模版中处理数据。过滤器看起来像这样:{{ name|lower }},这将把变量name的值转换为小写。 1,创建应用 python manage.py startapp app5 2,注册应用 Test/Test/sett…...
计算机组成原理 —— 存储系统(DRAM和SRAM,ROM)
计算机组成原理 —— 存储系统(DRAM和SRAM) DRAM和SRAMDRAM的刷新DRAM地址复用ROM(Read-Only Memory(只读存储器)) 我们今天来看DRAM和SRAM: DRAM和SRAM DRAM(动态随机存取存储器&…...
第22篇 Intel FPGA Monitor Program的使用<五>
Q:如何用Intel FPGA Monitor Program创建C语言工程并运行呢? A:总体过程与创建汇编语言工程类似,不同的是在指定程序类型时选择C Program。 后续用到DE2-115开发板的硬件如LED、SW和HEX等外设时,还需要将描述定义这些…...
网信办公布第六批深度合成服务算法备案清单,深兰科技大模型入选
6月12日,国家互联网信息办公室发布了第六批深度合成服务算法备案信息,深兰科技硅基知识智能对话多模态大模型算法通过相关审核,成功入选该批次《境内深度合成服务算法备案清单》。同时入选的还有腾讯混元大模型多模态算法、支付宝图像生成算法…...
ES 8.14 向量搜索优化
参考:https://blog.csdn.net/UbuntuTouch/article/details/139502650 检索器(standard、kNN 和 RRF) 检索器(retrievers)是搜索 API 中的一种新抽象概念,用于描述如何检索一组顶级文档。检索器被设计为可以…...
查看 MAC 的 shell 配置文件
在Mac上,shell的配置文件主要取决于您当前使用的shell。从macOS Catalina开始,Mac使用zsh作为默认登录Shell和交互式Shell。以下是关于Mac上zsh shell配置文件的一些详细信息: 查看当前使用的shell: 要查看当前正在使用的shell&am…...
前端下载文件流,axios设置responseType: arraybuffer/blob无效
项目中调用后端下载文件接口,设置responseType: arraybuffer,实际拿到的数据data是字符串 axios({method: post,url: /api/v1/records/recording-file/play,// 如果有需要发送的数据,可以放在这里data: { uuid: 06e7075d-4ce0-476f-88cb-87fb0a1b4844 }…...
动手学深度学习(Pytorch版)代码实践 -卷积神经网络-14模型构造
14模型构造 import torch from torch import nn from torch.nn import functional as F#通过实例化nn.Sequential来构建我们的模型, 层的执行顺序是作为参数传递的 net1 nn.Sequential(nn.Linear(20, 256), nn.ReLU(), nn.Linear(256,10)) """ nn.…...
Django 模版转义
1,模版转义的作用 Django模版系统默认会自动转义所有变量。这意味着,如果你在模版中输出一个变量,它的内容会被转义,以防止跨站脚本攻击(XSS)。例如,如果你的变量包含HTML标签,这些…...
实战演练:三种常见办公文档加密破解技巧(ZIP密码/ZIP伪加密/DOC密码)
1. ZIP密码破解实战:从入门到精通 工作中经常会遇到这种情况:同事发来的压缩包设置了密码,但对方忘记告诉你密码是什么;或者多年前自己加密的压缩包,现在怎么也打不开了。这时候就需要掌握一些ZIP密码破解的技巧。 我遇…...
5分钟搞定Phi-4-mini-reasoning:轻量级推理模型部署与使用教程
5分钟搞定Phi-4-mini-reasoning:轻量级推理模型部署与使用教程 1. 模型简介 Phi-4-mini-reasoning是一个专注于高质量推理任务的轻量级开源模型,属于Phi-4模型家族。这个140亿参数的模型经过专门训练,擅长处理需要复杂推理的任务࿰…...
实战指南:用LLNet深度学习模型提升夜间监控画质(附Python代码)
实战指南:用LLNet深度学习模型提升夜间监控画质(附Python代码) 夜间监控画质提升一直是安防和无人机航拍领域的核心挑战。当光线不足时,传统ISP(图像信号处理器)往往难以平衡亮度增强与噪声抑制,…...
Reloadium数据库回滚功能:SQLAlchemy和Django ORM的10个最佳实践指南
Reloadium数据库回滚功能:SQLAlchemy和Django ORM的10个最佳实践指南 【免费下载链接】reloadium Hot Reloading, Profiling and AI debugging for Python 项目地址: https://gitcode.com/gh_mirrors/re/reloadium Reloadium是一款强大的Python热重载工具&am…...
Qwen3.5-9B部署教程:GPU内存映射优化+O_DIRECT加速模型加载
Qwen3.5-9B部署教程:GPU内存映射优化O_DIRECT加速模型加载 1. 项目概述 Qwen3.5-9B是一款拥有90亿参数的开源大语言模型,具备强大的逻辑推理、代码生成和多轮对话能力。该模型支持多模态理解(图文输入)和长上下文处理࿰…...
7步突破Cursor Pro限制:多语言环境下的AI编程工具全功能解锁指南
7步突破Cursor Pro限制:多语言环境下的AI编程工具全功能解锁指南 【免费下载链接】cursor-free-vip [Support 0.45](Multi Language 多语言)自动注册 Cursor Ai ,自动重置机器ID , 免费升级使用Pro 功能: Youve reache…...
Ubuntu 20.04 下 LVI-SAM 复现全记录:从 gtsam 版本踩坑到 OpenCV 头文件修改
Ubuntu 20.04 下 LVI-SAM 复现实战:从 gtsam 版本适配到 OpenCV 接口升级全解析 在机器人感知与定位领域,LVI-SAM 作为融合激光雷达与视觉信息的 SLAM 系统,因其优异的实时性和鲁棒性备受关注。然而其复杂的依赖环境配置常常让开发者陷入&quo…...
POIKit 2024:如何用5步实现大规模POI数据采集与智能处理
POIKit 2024:如何用5步实现大规模POI数据采集与智能处理 【免费下载链接】AMapPoi POI搜索工具、地理编码工具 项目地址: https://gitcode.com/gh_mirrors/am/AMapPoi 当你面对需要采集某个城市所有餐饮店铺、分析竞争对手门店分布、或者研究城市设施空间布局…...
重构时间选择体验:flatpickr的现代前端实践指南
重构时间选择体验:flatpickr的现代前端实践指南 【免费下载链接】flatpickr lightweight, powerful javascript datetimepicker with no dependencies 项目地址: https://gitcode.com/gh_mirrors/fl/flatpickr 问题引入:你的时间选择器是否还在制…...
手把手教你用Strongswan App通过IKEv2 EAP认证连接Freeradius(附调试技巧)
移动端安全连接实战:Strongswan与Freeradius的IKEv2 EAP认证深度配置指南 在移动办公日益普及的今天,企业级VPN解决方案需要兼顾安全性与易用性。Strongswan作为开源的IPsec实现,配合Freeradius进行EAP认证,能够为Android设备提供…...
