You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

QGraphicsTextItem与void*转换后地址不一致问题咨询

QGraphicsTextItem与void*转换后地址不一致问题咨询

嘿,我来帮你拆解下这个问题的根源和解决办法~

问题本质:C++多重继承的指针地址调整

你遇到的差异,核心原因是QGraphicsTextItem和QGraphicsSimpleTextItem的继承结构不同,导致编译器处理指针转换的逻辑不一样:

  • QGraphicsSimpleTextItem是单一继承:它直接继承自QGraphicsItem,内存布局里QGraphicsItem的子对象是整个派生类对象的起始位置。
  • QGraphicsTextItem是多重继承:它除了继承QGraphicsItem,还继承了其他Qt类(比如和文本文档相关的类)。这时候QGraphicsItem的子对象在QGraphicsTextItem的内存布局里,并不是第一个位置。

当你做指针转换时:

  1. 直接把QGraphicsTextItem*转成QGraphicsItem*:编译器会自动调整指针地址,指向内存布局中QGraphicsItem子对象的位置,这也是m_pScene->items()中存储的指针地址。
  2. 先转void*再转回QGraphicsItem*:void*只保存了QGraphicsTextItem对象的原始起始地址,转回时编译器没有类型信息,无法自动完成地址调整,所以得到的指针和直接转换的结果不一样。

对应你的代码来看:

auto pTextItem = new QGraphicsTextItem("QGraphicsTextItem", pV);
auto pItem = (void*)pTextItem; // 保存的是QGraphicsTextItem对象的起始地址

auto item = (QGraphicsItem*)pItem; // 无自动地址调整,指向对象起始地址
auto item2 = (QGraphicsItem*)pTextItem; // 编译器自动调整到QGraphicsItem子对象地址

这就导致item和item2地址不同,而场景中存储的是item2对应的地址,所以b1为false,b2为true。

而QGraphicsSimpleTextItem是单一继承,QGraphicsItem子对象就在派生类的起始位置,所以两种转换方式得到的地址完全一致,b3和b4都是true。

解决办法

  1. 优先直接用QGraphicsItem*存储
    既然所有图形项都继承自QGraphicsItem,完全不需要用void*来存储,直接用QGraphicsItem*就可以,类型安全又不会有地址问题。

  2. 如果必须用void,转换时要先转回派生类*
    如果你因为某些场景必须用void*中转,那么转回时要先转成原始的派生类指针,再转成QGraphicsItem*,让编译器完成地址调整:

    // 正确的转换流程
    auto item = static_cast<QGraphicsItem*>(static_cast<QGraphicsTextItem*>(pItem));
    

    这样得到的指针就和item2的地址一致,能被items.contains()识别。

备注:内容来源于stack exchange,提问作者user12660456

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 10:50:29