news 2026/7/4 15:31:38

如何使用`typeid`判断指针或引用所指对象的实际类型?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
如何使用`typeid`判断指针或引用所指对象的实际类型?

核心前提:typeid判断实际类型的条件

typeid能否识别指针 / 引用指向的实际类型,唯一的关键是:被判断的类是否是多态类(包含至少一个虚函数,通常是虚析构函数)

  • 非多态类:typeid只能识别编译期的声明类型(静态类型)。
  • 多态类:typeid会解析运行时的实际对象类型(动态类型)。

一、判断指针指向对象的实际类型

关键注意点

使用typeid判断指针时,必须解引用指针typeid(*ptr)),如果直接写typeid(ptr),得到的只是 “指针类型” 本身(如Base*),而非指向对象的类型。

代码示例(对比多态 / 非多态类)

cpp

运行

#include <iostream> #include <typeinfo> // 1. 非多态基类(无虚函数) class NonPolymorphicBase { public: void func() {} // 普通成员函数 }; class NonPolymorphicDerived : public NonPolymorphicBase {}; // 2. 多态基类(有虚函数) class PolymorphicBase { public: virtual ~PolymorphicBase() = default; // 虚析构,使类多态 virtual void func() {} }; class PolymorphicDerived : public PolymorphicBase {}; int main() { // ---------------------- 非多态类测试 ---------------------- NonPolymorphicBase* np_base_ptr = new NonPolymorphicDerived(); // 错误:直接判断指针类型(得到的是指针本身的类型) std::cout << "非多态-直接判断指针: " << typeid(np_base_ptr).name() << std::endl; // 结果:NonPolymorphicBase*(编译器可能简写为P19NonPolymorphicBase) // 非多态类:即使解引用,仍返回编译期声明类型(Base) std::cout << "非多态-解引用指针: " << typeid(*np_base_ptr).name() << std::endl; // 结果:NonPolymorphicBase(而非Derived) // ---------------------- 多态类测试 ---------------------- PolymorphicBase* p_base_ptr = new PolymorphicDerived(); // 错误:直接判断指针类型(得到的是指针本身的类型) std::cout << "多态-直接判断指针: " << typeid(p_base_ptr).name() << std::endl; // 结果:PolymorphicBase*(编译器可能简写为P16PolymorphicBase) // 多态类:解引用后,返回运行时实际类型(Derived) std::cout << "多态-解引用指针: " << typeid(*p_base_ptr).name() << std::endl; // 结果:PolymorphicDerived // ---------------------- 类型比较 ---------------------- // 判断指针指向的对象是否是指定的实际类型 if (typeid(*p_base_ptr) == typeid(PolymorphicDerived)) { std::cout << "指针指向的是PolymorphicDerived类型对象" << std::endl; } // 释放内存 delete np_base_ptr; delete p_base_ptr; return 0; }

二、判断引用所指对象的实际类型

引用的特性是 “别名”,不存在空引用,因此使用typeid判断引用时:

  • 无需解引用(引用本身就是对象的别名);
  • 同样遵循 “多态类识别实际类型,非多态类识别声明类型” 的规则。
代码示例

cpp

运行

#include <iostream> #include <typeinfo> // 多态基类 class Base { public: virtual ~Base() = default; }; class Derived1 : public Base {}; class Derived2 : public Base {}; void check_ref_type(Base& ref) { // 直接判断引用,多态类会返回实际类型 if (typeid(ref) == typeid(Derived1)) { std::cout << "引用指向Derived1对象" << std::endl; } else if (typeid(ref) == typeid(Derived2)) { std::cout << "引用指向Derived2对象" << std::endl; } else { std::cout << "引用指向Base对象" << std::endl; } } int main() { Derived1 d1; Derived2 d2; Base b; Base& ref1 = d1; Base& ref2 = d2; Base& ref3 = b; check_ref_type(ref1); // 输出:引用指向Derived1对象 check_ref_type(ref2); // 输出:引用指向Derived2对象 check_ref_type(ref3); // 输出:引用指向Base对象 return 0; }

三、常见坑点与注意事项

  1. 不要直接判断指针类型typeid(ptr)得到的是 “指针类型”(如Base*),而非指向对象的类型,必须写typeid(*ptr)
  2. 空指针处理:如果指针是nullptr,对非多态类使用typeid(*ptr)会直接崩溃;对多态类,typeid(*ptr)仍会返回指针的声明类型(不会崩溃)。

    cpp

    运行

    PolymorphicBase* null_ptr = nullptr; std::cout << typeid(*null_ptr).name() << std::endl; // 输出PolymorphicBase(不会崩溃) NonPolymorphicBase* null_np_ptr = nullptr; std::cout << typeid(*null_np_ptr).name() << std::endl; // 未定义行为,大概率崩溃
  3. 类型名的可读性typeid(...).name()的返回值是编译器相关的(比如 GCC 会简写类型名,MSVC 会返回完整名),不要直接依赖字符串内容判断类型,优先用typeid(A) == typeid(B)的方式。
  4. 运行时开销:对多态类使用typeid会查询虚函数表(vtable),有轻微运行时开销,频繁使用会影响性能。

总结

  1. 核心条件:只有对多态类(含虚函数)的指针 / 引用,typeid才能识别指向对象的实际类型;非多态类仅能识别编译期声明类型。
  2. 指针判断:必须解引用(typeid(*ptr)),否则得到的是指针类型本身。
  3. 引用判断:直接使用typeid(ref)即可,多态类会返回实际对象类型。
  4. 安全建议:判断类型时优先用typeid(A) == typeid(B),而非解析name()字符串;空指针场景需先判空再使用typeid(*ptr)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/1 1:50:50

go语言对phone脱敏显示

在Go语言中实现手机号脱敏显示主要有以下几种方式&#xff0c;从简单到完整逐步推荐&#xff1a; 一、基础实现&#xff08;字符串切片&#xff09; 最常用且高效的方式是直接使用字符串切片操作&#xff0c;保留前3位和后4位&#xff0c;中间用*替换&#xff1a; go 复制 …

作者头像 李华
网站建设 2026/6/30 11:16:28

开源模型新选择:AnimeGANv2宫崎骏风格迁移实战指南

开源模型新选择&#xff1a;AnimeGANv2宫崎骏风格迁移实战指南 1. 引言 随着深度学习在图像生成领域的持续突破&#xff0c;风格迁移技术已从实验室走向大众应用。其中&#xff0c;AnimeGANv2 作为轻量级、高效率的动漫风格迁移模型&#xff0c;凭借其出色的画质表现和极低的…

作者头像 李华
网站建设 2026/7/3 10:31:21

Windows 10/11 优化大师 Windows Manager

一、前言&#xff1a;为什么 Windows 10/11 越用越卡&#xff1f; 相信很多朋友都有这样的体验&#xff1a; 新装的 Windows 10 / Windows 11 用着很流畅用了一段时间后&#xff1a; 开机变慢系统反应迟钝后台服务越来越多磁盘空间被莫名其妙占满 即便你不安装乱七八糟的软…

作者头像 李华
网站建设 2026/6/26 8:56:42

VibeThinker-1.5B-WEBUI权限管理:多用户场景下的配置建议

VibeThinker-1.5B-WEBUI权限管理&#xff1a;多用户场景下的配置建议 1. 引言 1.1 业务场景描述 随着轻量级大模型在开发者社区的广泛应用&#xff0c;VibeThinker-1.5B-WEBUI 因其低成本、高推理效率的特点&#xff0c;逐渐成为个人开发者和小型团队进行数学推导与编程辅助…

作者头像 李华
网站建设 2026/6/29 22:05:37

【性能测试】2_JMeter _JMeter文件目录

文章目录一、Bin目录二、docs目录三、printable_docs目录四、lib目录一、Bin目录 Bin目录:存放可执行文件和配置文件。 examples&#xff1a;目录下包含Jmeter使用实例ApacheJMeter.jar&#xff1a;JMeter源码包jmeter.bat&#xff1a;windows下启动文件jmeter.sh&#xff1a…

作者头像 李华
网站建设 2026/7/1 1:03:22

计算机毕设 java 基于 java 青少年篮球俱乐部管理系统设计与实现 基于 Java 的青少年篮球俱乐部管理平台 赛事组织与运动员服务系统

计算机毕设 java 基于 java 青少年篮球俱乐部管理系统设计与实现&#xff08;配套有源码、程序、MySQL 数据库、论文&#xff09;&#xff0c;本套源码可先查看功能演示视频&#xff0c;文末有联系方式可领取。传统青少年篮球俱乐部管理存在赛事信息传递不及时、报名流程繁琐、…

作者头像 李华