指针类型转换

目录

一、C++ 中的四类转化

1.1 dynamical_cast

1.2 static_cast

1.3 reinterpret_cast

1.4 const_cast

二、Qt中的qobject_cast 

2. 1 qobject_cast 的工作流程

2.2  qobject_cast 与 dynamic_cast比较


一、C++ 中的四类转化

1.1 dynamical_cast

  • 原理在运行时进行类型检查。它依赖于 C++ 的 RTTI(运行时类型信息)。它主要用于在多态继承体系(即含有虚函数的类)中进行安全的下行转换或交叉转换
  • 用途
    • 检查转换是否安全。如果转换失败,对于指针返回 nullptr,对于引用抛出 std::bad_cast 异常。
  • 要求必须用于含虚函数的类(多态类型)。

1.2 static_cast

static_cast的转换格式:static_cast <type-id> (expression)

  • 原理:在编译期进行类型检查。它用于编译时已知的、有一定安全性的转换。如果编译器发现转换不合理(如将 int* 转成 char,但没有继承关系的类指针转换),会报错。
  • 用途
    • 基本数据类型之间的转换(如 int 转 double)。
    • 将 void* 指针转换回原始类型指针。
    • 有继承关系的类指针或引用的上行转换(子类 -> 父类,安全)和下行转换(父类 -> 子类,不安全,但编译通过)

        将expression转换为type-id类型,主要用于非多态类型之间的转换,不提供运行时的检查来确保转换的安全性。

1.3 reinterpret_cast

reinterpret_cast的转换格式:reinterpret_cast <type-id> (expression)

  • 原理:提供低层次的、不安全的重新解释。它直接将一种类型的位模式解释为另一种类型,不进行任何检查。
  • 用途
    • 在函数指针类型之间转换。
    • 将指针转换为足够大的整数类型(如 uintptr_t)。

        允许将任何指针类型转换为其它的指针类型;听起来很强大,但是也很不靠谱。它主要用于将一种数据类型从一种类型转换为另一种类型。它可以将一个指针转换成一个整数,也可以将一个整数转换成一个指针,在实际开发中,先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原来的指针值;特别是开辟了系统全局的内存空间,需要在多个应用程序之间使用时,需要彼此共享,传递这个内存空间的指针时,就可以将指针转换成整数值,得到以后,再将整数值转换成指针,进行对应的操作。

 

1.4 const_cast

const_cast的转换格式:const_cast <type-id> (expression)

const_cast用来将类型的const、volatile和__unaligned属性移除。常量指针被转换成非常量指针,并且仍然指向原来的对象;常量引用被转换成非常量引用,并且仍然引用原来的对象。

二、Qt中的qobject_cast 

        当类定义中使用 Q_OBJECT 宏时,Qt 的元对象编译器(moc)会为这个类生成一个唯一的元对象(staticMetaObject)。同时,moc 还会为该类在其整个继承体系内分配一个唯一的整数标识符,我们通常称之为 qt_metacast_id。moc 工具通过分析所有的头文件,确保为每个类分配qt_metacast_id不重复。

qobject_cast 的 ID 机制

  • 每个 QObject 派生类通过 MOC 生成唯一的整型标识符(如 staticMetaObject 中的索引)。
  • 转换时直接比较源对象和目标类的 ID,若匹配或存在继承关系则成功。
  • 示例代码逻辑
    // 伪代码:qobject_cast 简化逻辑

template<typename T> T qobject_cast(QObject *obj)

{

   if (obj && obj->metaObject()->inherits(T::staticMetaObject()))

        return static_cast<T>(obj);

    return nullptr;

}

2. 1 qobject_cast 的工作流程

qobject_cast 的内部行为可以简化为以下高效步骤:

  1. 检查空指针:如果输入的指针为空,直接返回空指针。
  2. 获取元对象:获取源对象(例如 obj)的元对象(obj->metaObject())。
  3. 快速 ID 比较(核心步骤):询问源对象的元对象:“是否是或派生自目标类型 T
    • 这个询问是通过比较整型 ID 来完成的。
    • 元对象系统内部维护着一个查询表或使用其他高效算法(如直接比较预先生成的 ID),速度极快,接近于一次指针比较。
  4. 返回结果:如果比较成功,则进行静态转换并返回目标类型的指针;如果失败,则返回空指针。

2.2  qobject_cast 与 dynamic_cast比较

dynamic_cast 的 RTTI 机制

        依赖编译器生成的 type_info 结构,在运行时遍历类继承树。对复杂继承层次或虚基类可能需多次查找,开销较大。

特性qobject_castdynamic_cast (C++ RTTI)
基础机制Qt 元对象系统(MOC生成)C++ 运行时类型信息(RTTI)
比较依据元对象指针/标识符(高效、精确)类型信息(由编译器实现)
性能通常更快,专为 QObject 优化,开销极小相对较慢,依赖于编译器的RTTI实现
适用条件必须是 QObject 的派生类,且包含 Q_OBJECT 宏必须包含虚函数(多态类型)
跨库/动态链接更安全,因为元对象在编译时已确定在某些跨动态库的场景下可能不可靠
跨平台一致性行为在 Qt 支持的所有平台一致依赖编译器实现,可能存在平台

性能差异根源

  • qobject_cast:ID 比较是 O(1) 操作,且 MOC 提前计算继承关系,无运行时遍历。
  • dynamic_cast:需检查继承链,深度或复杂度增加时性能下降。

使用场景

  • 优先用 qobject_cast:在 Qt 项目中处理 QObject 派生类时(如界面组件、信号槽连接)。
  • 备用 dynamic_cast:非 Qt 类或需要跨编译器兼容时使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值