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

C++类型判断

一、编译期类型判断(静态类型检查)

这类判断在编译阶段完成,零运行时开销,主要用于模板编程、类型萃取等场景。

1.typeid运算符(基础)

typeid可以获取类型信息,返回std::type_info对象,常用于判断两个类型是否相同。

代码示例

cpp

运行

#include <iostream> #include <typeinfo> // 必须包含此头文件 class Base {}; class Derived : public Base {}; int main() { // 1. 判断基本类型 int a = 10; double b = 3.14; std::cout << "type of a: " << typeid(a).name() << std::endl; // 输出:int(不同编译器可能简写,如i) std::cout << "type of b: " << typeid(b).name() << std::endl; // 输出:double(如d) // 2. 判断自定义类型 Base base; Derived derived; std::cout << "base type: " << typeid(base).name() << std::endl; // Base std::cout << "derived type: " << typeid(derived).name() << std::endl; // Derived // 3. 判断类型是否相同 if (typeid(a) == typeid(int)) { std::cout << "a is int type" << std::endl; } // 注意:非多态类型,指针/引用不会触发动态类型判断 Base& ref = derived; std::cout << "ref type: " << typeid(ref).name() << std::endl; // 输出Base(非多态) return 0; }

关键说明

  • typeid返回的name()结果是编译器相关的(比如 GCC 会简写类型名),不能直接依赖字符串内容判断类型。
  • 对于非多态类型(类中无虚函数),typeid仅判断编译期类型,不会解析实际指向的对象类型。
2. 模板类型萃取(C++11 及以上)

通过标准库的std::is_samestd::is_pointerstd::is_class等模板,在编译期精准判断类型属性。

代码示例

cpp

运行

#include <iostream> #include <type_traits> // 必须包含此头文件 template <typename T> void check_type(T value) { // 判断是否为指定类型 if constexpr (std::is_same_v<T, int>) { // C++17的is_same_v,等价于std::is_same<T, int>::value std::cout << "Type is int" << std::endl; } else if constexpr (std::is_same_v<T, double>) { std::cout << "Type is double" << std::endl; } // 判断类型属性 std::cout << "Is pointer: " << std::boolalpha << std::is_pointer_v<T> << std::endl; std::cout << "Is floating point: " << std::is_floating_point_v<T> << std::endl; std::cout << "Is arithmetic: " << std::is_arithmetic_v<T> << std::endl; // 算术类型(int/float等) } int main() { check_type(10); // int,非指针,非浮点,算术类型 check_type(3.14); // double,非指针,浮点,算术类型 check_type(&10); // int*,指针,非浮点,非算术类型 // 自定义类型判断 class MyClass {}; std::cout << "Is class: " << std::is_class_v<MyClass> << std::endl; // true return 0; }

关键说明

  • std::is_same<T, U>:判断 T 和 U 是否是完全相同的类型(包括 const/volatile 修饰)。
  • if constexpr(C++17):编译期条件判断,不会为不满足的分支生成代码,避免运行时开销。
  • 常用类型萃取模板:std::is_pointer(指针)、std::is_reference(引用)、std::is_const(常量)、std::is_base_of(基类判断)。

二、运行期类型判断(动态类型检查)

适用于多态类(含虚函数),在运行时判断对象的实际类型,核心是dynamic_cast

1.dynamic_cast类型转换(核心)

dynamic_cast用于多态类型的向下转换(子类→基类)或交叉转换,转换失败时:

  • 指针类型:返回nullptr
  • 引用类型:抛出std::bad_cast异常。

代码示例

cpp

运行

#include <iostream> #include <typeinfo> #include <exception> // 多态基类(必须有虚函数) class Base { public: virtual ~Base() = default; // 虚析构函数,使类成为多态 }; class Derived1 : public Base {}; class Derived2 : public Base {}; void check_dynamic_type(Base* ptr) { // 判断是否为Derived1类型 if (Derived1* d1_ptr = dynamic_cast<Derived1*>(ptr)) { std::cout << "Object is Derived1 type" << std::endl; } // 判断是否为Derived2类型 else if (Derived2* d2_ptr = dynamic_cast<Derived2*>(ptr)) { std::cout << "Object is Derived2 type" << std::endl; } else { std::cout << "Unknown type" << std::endl; } } int main() { Base* b1 = new Derived1(); Base* b2 = new Derived2(); Base* b3 = new Base(); check_dynamic_type(b1); // Derived1 check_dynamic_type(b2); // Derived2 check_dynamic_type(b3); // Unknown type // 引用类型的dynamic_cast(失败抛异常) try { Base& ref = *b2; Derived1& d1_ref = dynamic_cast<Derived1&>(ref); } catch (const std::bad_cast& e) { std::cout << "Cast failed: " << e.what() << std::endl; } delete b1; delete b2; delete b3; return 0; }

关键说明

  • dynamic_cast仅对多态类(含虚函数)有效,否则编译报错。
  • 运行时开销:dynamic_cast会查询类型信息表(vtable),有轻微运行时开销,应避免频繁使用。
2. 结合typeid实现动态类型判断

对于多态类,typeid会解析对象的实际类型(而非编译期类型):

cpp

运行

#include <iostream> #include <typeinfo> class Base { virtual ~Base() = default; }; class Derived : public Base {}; int main() { Base* ptr = new Derived(); std::cout << typeid(*ptr).name() << std::endl; // Derived(实际类型) delete ptr; return 0; }

三、常见使用场景

  1. 模板编程:用std::is_same/std::is_pointer等编译期判断,实现类型分支逻辑。
  2. 多态场景:用dynamic_cast判断基类指针 / 引用实际指向的子类类型。
  3. 类型安全检查:避免错误的类型转换(如将非多态类强制转换)。

总结

  1. 编译期判断:用std::is_same/std::is_pointer等模板(<type_traits>),零运行时开销,适合模板编程。
  2. 运行期判断:仅适用于多态类,用dynamic_cast(推荐)或typeid,有轻微运行时开销。
  3. 核心注意dynamic_cast依赖虚函数表,仅对多态类有效;typeid对非多态类仅返回编译期类型。
http://www.jsqmd.com/news/245402/

相关文章:

  • Python 内置 venv 虚拟环境工具完全指南(附 uv 工具无缝升级教程)
  • 2026机器视觉同轴光源品牌甄选指南:解锁高精度检测的照明密钥
  • 如何使用`typeid`判断指针或引用所指对象的实际类型?
  • C++ RAII封装结构体成员变量自动加锁性能开销分析
  • 凤希AI提出FXPA2P:下一代点对点AI服务架构-2026年1月14日
  • 智能指针的生命周期控制
  • AI原生应用开发:相似度匹配的模型压缩技巧
  • 6款AI论文降重神器实操教程:AI率从72%降至13%
  • Python + uiautomator2 手机自动化控制教程
  • Python 学生管理系统实战:从基础功能到数据持久化(附完整源码)
  • 【Python库和代码案例:第一课】Python 标准库与第三方库实战指南:从日期处理到 Excel 操作
  • 数独优化求解C库tdoku-lib的使用
  • AI原生应用云端推理的故障排查与恢复
  • dlx求解数独duckdb插件的编写和使用
  • 我用 XinServer 做了个文件系统,比想象简单
  • 大数据领域数据产品的安全保障策略
  • 避坑指南:通义千问2.5-7B-Instruct本地部署常见问题解决
  • 【RuoYi-SpringBoot3-Pro】:使用 Dify + AI 快速生成多数据库建表语句
  • AnimeGANv2版本回滚机制:模型更新失败应急部署教程
  • 【RuoYi-SpringBoot3-Pro】:多租户功能上手指南
  • 这份无线联网智能门锁系统清单非常专业,清晰地勾勒出了一套适用于多业态、高流动性、强管理场景的现代化出入口解决方案。这不仅是设备清单,更是一套“去中心化部署、云端化管理”的智慧运营蓝图。
  • 对象库未注册-VB6企业版控件加载不了MSCOMCTL.ocx
  • 提示工程架构师经验:如何用Prompt解决客服复杂问题?
  • 动漫生成服务SLA保障:AnimeGANv2高可用部署架构
  • go语言对phone脱敏显示
  • 通义千问2.5-7B-Instruct优化技巧:RTX 3060流畅运行指南
  • AnimeGANv2如何提高边缘清晰度?后处理滤波技术实战
  • 农业机械收割机拖拉机数据集6340张VOC+YOLO格式
  • 开源模型新选择:AnimeGANv2宫崎骏风格迁移实战指南
  • keil5安装包下载通俗解释:新手也能轻松掌握