原来 C++ 这么简单:每日十题轻松学 (Day 4 多态与 RTTI 篇)

3dMax脚本类插件:不写 C++也能造“原生”工具 从plugin关键字到场景持久化,拆解 MAXScript 插件开发全流程! 阅读详情

📘 本篇围绕 C++ 运行时多态机制(虚函数、虚表、类型识别等)展开。虚函数是类设计的灵魂,但也隐藏许多坑:对象切割、析构不虚、类型转换失败……本篇精选 10 个实际常见的问题,解释 + 示例 + 延伸练习,助你培基托底,深入内核。


🔁 Day 3 快速回顾

矩点记忆要点
构造函数类型默认、有参、拷贝、移动
explicit禁止隐式类型转换
Rule of Five自编辑资源管理类必须遵守
静态成员变量类共用,非对象的成员
对象大小受成员顺序、对齐和虚表影响

🔹 今日目标:进入 C++ 运行时多态的核心机制

  • 明确虚函数、vtable 和 vptr 的本质
  • 理解不同条件下多态是否生效
  • 识别对象切割、析构不虚等隐怪问题
  • 熟悉二连符工具:typeid 和 dynamic_cast

🎓 十大核心问题 + 深层解读

【Q1】什么是虚函数?

📅 概念:
虚函数用 virtual 关键字声明,支持运行时多态

🔎 代码示例:

class Animal {
public:
    virtual void speak() { std::cout << "Animal\n"; }
};
class Dog : public Animal {
public:
    void speak() override { std::cout << "Dog\n"; }
};

🔹 区别:

类型绑定时机是否支持多态
普通函数编译期不支持
虚函数运行期支持

【Q2】虚函数的本质是什么?

📅 原理:
C++ 通过“虚函数表 vtable ” 和 “虚表指针 vptr ” 实现多态

🔎 代码示意:

  • 每个有虚函数的类都有一个 vtable
  • 每个对象内部隐藏一个 vptr 指向对应的 vtable

🔹 调用虚函数 = 通过 vptr 查表调用


【Q3】多态生效需要哪些条件?

🔹 有效多态的 3 大条件:

  1. 基类函数是 virtual
  2. 子类重写了此虚函数
  3. 通过“基类指针/引用” 调用

🔔 错误示例:

Dog d;
d.speak(); // 非多态,编译期绑定

🔔 正确示例:

Animal* a = new Dog;
a->speak(); // 多态,运行期确定调用

【Q4】什么是对象切割 (Object Slicing) ?

📅 定义: 用子类对象输入基类对象,就会被“切割成基类部分”
在这里插入图片描述

🔎 代码示例:

void print(Animal a) {
    a.speak();  // 只有 Animal 部分,切割了
}

Cat c;
print(c);  // 调用 Animal::speak()

📈 改进:
给入参改为引用/指针,防止切割


【Q5】析构函数为什么一定要声明为 virtual?

📅 问题: 如果某类有 virtual 函数,应该把析构函数也声明为 virtual

否则后果: 通过基类指针 delete 子类对象时,只调用基类析构,子类资源泄露

解決:

virtual ~Animal(); // 完全析构

【Q6】什么是 RTTI?

RTTI = Run-Time Type Information

在运行期获取对象实际类型,仅适用于含虚函数的类

两个工具操作符:

  • typeid(expr) :获取类型对象
  • dynamic_cast<T*> :安全地转换指针

【Q7】怎么用 typeid 确认类型?

Base* p = new Derived;

if (typeid(*p) == typeid(Derived)) {
    std::cout << "It's Derived\n";
}

前提: 类中有虚函数,否则 typeid(*p) 只看指针类型


【Q8】 dynamic_cast 是怎么做安全类型转换的?

Base* b = new Derived;

if (Derived* d = dynamic_cast<Derived*>(b)) {
    d->draw();  // 转换成功
} else {
    std::cout << "Conversion failed\n";
}

特性:

  • 成功返回子类指针
  • 失败返回 nullptr
  • 仅适用于含 virtual 函数的类

【Q9】含虚函数类会增加对象大小吗?

代码比较:

class A { int x; };
class B { virtual void f(); int x; };

std::cout << sizeof(A) << " " << sizeof(B);

结果: B 比 A 大,因为多了 vptr


【Q10】如何避免对象切割并保留多态?

错误示例:

Base b = Derived(); // 切割只保留基类
b.virtualFunc();    // 调用的是 Base 版本

正确使用:
使用基类指针或引用,不用值传递


📙 结论手册:重点全记

矩点记忆讲解
虚函数运行时绑
华科软院研究生第一学期的事项(奖学金、学业、考试等) 奖助 研究生补助 每月500,全年共6000元 每个月月底学院会打到银行卡里 碰上开学、过年会延后发放 17年10月底发了9、10两个月的钱 18年3月底发了2、3月的钱 学业奖学金 17届全日制每人都有 按照考研最后综合成绩排名 前16 10000 前80 8000 其他 4000 大概11月底发 注意:第一年如果有挂科的话,第二年就不能参加学业奖学金评... 阅读详情

相关推荐

Modem2G/3G/4G/5G:RFFE Driver(射频前端驱动):高通平台GRFC配置方法

文 | GentlemanTsao 文章目录前言1.什么是GRFC2.GRFC的配置流程概览3.msm_sig_info的配置与分析msm_sig_info Table位置:msm_sig_info Table示例:Table元素解读:rfc_msm_sig_info_type结构体signal typemsm_gpio |grfc_num:GPIO到GRFC的映射output_typefunction_select4._sig_cfg的配置与分析_sig_cfg table位置:_sig_cfg tabl

GentelmanTsao的博客 7311

动多态与RTTI

复习内容 什么是多态?(1)静多态:编译时期的多态,有被称为早绑定 代表:函数重载,模板(2)动多态:运行时期的多态,又被称为晚绑定 代表:继承中的多态 动多态的产生条件:指针或引用调用虚函数+对象必须完整 完整对象:构造函数执行完毕,析构函数还没开始 class Base { public: Base() { this->fun(); } virtual void fun() { cout ...

m0_53101047的博客 767

实战避坑:在STM32上移植AUTOSAR BSW时,MCAL、ECU抽象层和服务层配置有哪些常见‘雷区’?

本文深入解析在STM32上移植AUTOSAR BSW时MCAL、ECU抽象层和服务层配置的常见陷阱,包括时钟树配置差异、GPIO电气特性问题、定时器资源冲突等实战经验。特别针对AUTOSAR架构在资源受限MCU上的特殊挑战,提供具体解决方案和优化策略,帮助开发者规避移植过程中的典型错误。

weixin_30258901的博客 560

重构系列之对象属性的重构:《重构》重新组织数据

Self Encapsulate Field 自封装字段 间接访问类的属性:你直接访问一个字段,但与字段之间的耦合关系逐渐变得笨拙。为这个字段建立取值/设值函数,并且只以这些函数来访问字段。

有心好书 2032

ADS Layout设计实战:从参数设置到协同仿真

本文详细介绍了ADS Layout设计的完整实战流程,从新建工程、单位设置、个性化偏好配置等基础操作入手,逐步深入到基板参数配置、端口设置与电磁仿真器选择等核心环节。重点阐述了参数化版图设计与扫描优化、以及原理图与Layout协同仿真的高级技巧,并通过一个微带线低通滤波器设计案例,完整演示了从理论到实现的闭环设计方法,帮助工程师高效、准确地完成高频电路版图设计与验证。

weixin_29268637的博客 797

usb设备的定位信息获取

一个usb hub有20个口,每个口有一个标号,那么如果一个为X的标号插入了一个android设备,如何通过函数,得到这个X,代码实现如下,获取了location, 得到类似 Port_#0002.Hub_#0003 的字符串,然后,要对应一个表。

babytiger的专栏 2106

RTTI及多态的实现机制

                           C++ RTTI及多态的实现机制 RTTI中无论是dynamic_cast还是typeid,都是只对引用和指针有效。  假设实现多态的继承体系:class Base {    public:    virtual void Fun() ;}class Derived ;Base* pp = new Derived() ;Derived* pp2

zhuweisky 4631

VMware 虚拟机里连不上网的五种解决方案

在VMware虚拟机里的虚拟机系统连接不上网络 首先,注意查看适配器选项里的网络连接这两个网络连接是否存在,如果不存在可以重新装一下VM 如果存在,连不上网 解决办法一: 虚拟机设置里,找到“网络适配器”,右边的网络连接选择“NAT 模式”,如果不行的话再linux系统。还是不行的话接着看第二种解决方案。 解决方法二: 可能原因是VMware NET Service...

墨轩 18万+

理解多态和RTTI

public class ChinesePerson implements Person { @Override public void say() { // TODO Auto-generated method stub System.out.println("i am chinese"); } }public class JapanPerson implements Per

atarik@163.com 1710

企业如何开展BI建设--指标体系建设

很多企业的数字化转型工作都是从做BI项目开始的,很多企业认为,BI就是做指标大屏,所以做了很多的驾驶舱,也做了很多指标,有从系统取的,有手工填报的,甚至手工填报的比例占到了70%,最终BI沦为了填报系统,业务认为BI就是把从线下的微信沟通转到了线上录入展示,并没有给业务代来任何提升,久而久之,BI大屏就没人关心,公司高层也认为数据都是填报的,都经过了加工处理,这种数据不可信,不能反映业务开展的实际。其实在BI系统建设之前,我们首先要做的就是要梳理企业的指标,到底我们要展示哪些指标?

262

C#怼倍福TwinCAT3:ADS协议封装实战(附完整读写源码+避坑清单)

变量名大小写敏感:PLC里定义的是GVL.bStart,你写GVL.BStart绝对读不到;数组访问格式:PLC数组是,C#里读单个元素要写,读整个数组不用写索引;句柄要释放:用创建的句柄,一定要用using包起来,否则会占着资源;PLC必须运行:哪怕变量定义对了,PLC没Run(只是Login)也读不到数据;路由配置:如果上位机和PLC不在一个网段,要在TwinCAT3里添加路由(Router→Edit Routes)。倍福ADS通信其实不难,核心就是“配置对+变量名写对+数据类型匹配”。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 947

运行时多态(RTTI)

RTTI的概念:运行时的类型信息run-time type information 所有的类型信息 =》Class对象里面进行存储 类 ==》 Class(方法区进行存储) 空类的前8个地址:方法表的地址 #16 在方法表16号 Java编译器把类的实例方法都默认处理成了virtual虚函数。 Private方法无法被覆盖 Final 常量、不能被改变 fianl修饰方法不能被

transkai的博客 335

Hadoop在大数据领域的电商数据分析案例

随着电商行业的迅猛发展,每天都会产生海量的数据,如用户浏览记录、购买行为、商品信息等。如何从这些数据中提取有价值的信息,为电商企业的决策提供支持,成为了电商企业面临的重要问题。Hadoop作为一个开源的分布式计算平台,具有高可靠性、高扩展性和高效性等特点,能够很好地处理大数据。本文的目的就是通过实际案例,详细介绍Hadoop在电商数据分析中的应用,范围涵盖了从数据采集、存储到分析的整个流程。本文首先介绍背景信息,让读者了解Hadoop在电商数据分析中的重要性和应用场景。

Java大师兄的博客 1177

原来 C++ 这么简单:每日十题轻松学 (Day 5 模板基础实战篇)

📌 含义:当条件满足时生成此函数,否则该重载被忽略(替代失败但不报错)类型限制按不同类型定制行为(int/float/std::string)增加set()方法重置值增加print()方法:仅当T可用于std::cout时才可用技术点价值与说明函数模板通用算法实现,提高代码复用性类模板泛型容器和工具类的构建基础实例化机制控制生成,支持延迟逻辑与优化SFINAE提供选择性重载,简化约束写法默认模板参数提升接口友好性,减少使用者负担📌模板特化与偏特化。

Interview_TC的博客 680

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

多态与RTTI

Java 多态是如何实现的 通过运行时动态绑定, 动态判定当前引用的类型, 调用本类对应的函数,如果没有,则调用父类的函数。 需要根据RTTI需要多对应的信息, 和C++不一样,C++有一种虚表的东西在起作用,是一种前期绑定,而Java属于后期绑定,所以Java的动态其实更简单。 RTTI: JAVA RTTI的核心是.Class,Class对象存放着对应类所需要的所有的类型信息

oCrazyTiger的博客 921

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

选型笔记:Type‑C 扩展坞方案评估|DP1.4 转 HDMI2.0 桥接芯片 GSV2201S@ACP

本文记录 GSV2201S 这款 DP1.4a 转 HDMI2.0 桥接芯片评估,梳理视频、HDCP、PD 集成能力,总结 Type‑C 转接 Dongle、扩展坞方案的适配边界,以及差分走线、PD 时序、HDCP 握手等高频调试问题,为 C 口视频转接方案选型提供参考。

ACP广源盛的博客 213

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

C++移动构造函数详解

移动构造函数是C++11引入的一种特殊构造函数,用于从临时对象(右值)"窃取"资源来初始化新对象,而不是进行昂贵的深拷贝。char* data;public:// 移动构造函数:参数是右值引用 &&// 关键:把源对象的资源置空。

拒绝AI文,努力在AI时代写出感动人心的好文章 385

ThunderKittens 深度解析:一个不基于 MLIR 的 C++ 模板 GPU DSL

Triton 是"让更多人能写 GPU kernel",ThunderKittens 是"让会写的人写得更爽"。前者用 MLIR 换易用性,后者用 C++ 模板换可控性。它们不是替代关系,而是覆盖了 GPU 编程光谱的两端。ThunderKittens 的出现,本质上是对"GPU DSL 必须基于 MLIR"这一默认假设的挑战。编译期类型系统本身就可以是一个强大的 DSL 基础设施,不需要中间 IR,不需要黑盒 pass,也能实现 tile 级抽象和零运行时开销。

Maxwell_Newton的博客 310

[C++]:6.STL:vector

今天就要开始学vector容器,这节课我们主要学习vector中经常会用到的函数,并且给出该函数的模拟实现。话不多说,直接上干货。下面是本章的思维导图,那么,让我们开始吧!

2301_80817679的博客 136

蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级:倍增法求最近公共祖先LCA解析

蓝桥杯报名正在火热进行(软件赛报名 2026-10-08—12-18,省赛 2027-04-10),电子学会 12 月软件编程(C/C++ 一级至十级、Python 一级至六级)考级报名也已开启(9/23—12/2),全国青少年信息素养大赛算法应用主题赛同步推进——把 LCA 这个模板练熟,正是冲刺这些赛事树型考点的关键一步。所谓「最近公共祖先」:在一棵以某个节点为根的树里,两个节点 u、v 向上追溯,最早交汇的那个祖先就叫它们的 LCA。比如家谱里,你和你表哥最近的共同长辈就是你们的祖父。

IT_Scratch的博客 530

C++ 多态详解:作用、原理与实战用法

多态是C++面向对象的核心特性,通过虚函数实现运行期动态绑定,使同一接口在不同对象上表现出不同行为。其核心作用包括统一接口、提升可扩展性、降低耦合、支持运行时分派与批量处理。实现依赖虚函数表(vtable)和虚指针(vptr),需注意虚析构函数、对象切片等陷阱。相比编译期多态(模板),运行期多态灵活性高但有调用开销。合理结合两者,可兼顾代码的灵活性与性能,是构建可扩展、低耦合系统的关键。

2402_85743155的博客 367

【C语言】字符与字符串函数

C语言中字符串为以\0结尾的字符数组,标准库函数基于此约定。本文解析字符串内存布局,详解ctype.h与string.h中字符分类、长度计算、拷贝、比较等函数的使用要点,强调长度判断与越界风险,最后通过命令行待办事项示例整合fgets、sscanf、strncpy、strcmp,展示实际应用中的关键细节。

记录在学习过程中学到的知识 334

C++ 函数模版

模板参数:● template ,T 就是类型占位符,名字可以自定义,习惯用T● 占位符可以在函数返回值、形参、函数内部当作类型使用使用要点模板代码一般写在头文件:编译器需要看到完整模板源码,才能在每个编译单元完成实例化全局函数、类内成员函数都可以写成模板实例化发生在编译阶段,不是运行时隐式实例化:调用时编译器自动推导实参类型,生成对应版本函数。

2501_94041724的博客 184

C++ 运行时多态与虚函数机制全面剖析【面试重点】

构成C++ 运行时多态必须是基类的指针或者引用调用虚函数。被调用的函数必须是虚函数,并且派生类必须对该虚函数完成重写/覆盖(Override)。只有基类的指针或引用才能既指向基类对象,又指向派生类对象(切片机制);而只有完成了虚函数重写,派生类与基类才具备不同的函数行为,达到“指向谁就调用谁”的效果。在类成员函数的前面加上virtual关键字修饰,该成员函数就成为了虚函数。public:// 成员函数前加 virtual 修饰,声明为虚函数。

Fuyo_0209的博客 433

C++ 求抛物线的顶点、焦点和准线(Finding the vertex, focus and directrix of a parabola)

已知抛物线方程 $ y = ax^2 + bx + c $,可利用公式求其顶点、焦点和准线。顶点为 $ \left( -\frac{b}{2a}, \frac{4ac - b^2}{4a} \right) $,焦点为 $ \left( -\frac{b}{2a}, \frac{4ac - b^2 + 1}{4a} \right) $,准线方程为 $ y = c - \frac{b^2 + 1}{4a} $。以 $ a=5, b=3, c=2 $ 为例,计算得顶点 $(-0.3, 1.55)$,焦点 $(-0

csdn_aspnet的专栏,请点击博客主页右上角三个点中的私信联系 163

c++ 超级大坑未定义行为如何避免(下)

尤其是通过。

拒绝AI文,努力在AI时代写出感动人心的好文章 141
上一篇: syslog 与 Linux 内核日志系统全面解析
下一篇: 驱动开发硬核特训 · Day 1
嵌入式孙老师
博客等级 码龄7年 5686粉丝 898原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值