最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - QGraphicsTextItem * and void * conversion error - Stack Overflow

programmeradmin0浏览0评论

I want to use void * to store the pointer of the QGraphicsTextItem object created, and in another function, convert the void * pointer to a QGraphicsItem pointer for easy removal from the scene. However, I found that during the conversion, item and item2 point to different addresses; When converting QGraphicsSimpleTextItem pointers, there is no such problem. May I ask why this is happening or where I am using the problem , here is my demo:

MainWindow::MainWindow(QWidget* parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    m_pScene = new QGraphicsScene(this);
    m_pView = new QGraphicsView(ui->viewWidget);
    m_pView->setScene(m_pScene);

    m_pView->setWindowTitle("Graphics View");
    m_pView->resize(500, 500);

    auto x = new QPixmap(R"(D:\desktop\Data\2D\2.bmp)");
    pV = new QGraphicsPixmapItem(*x);
    m_pScene->addItem(pV);
    // QGraphicsTextItem
    auto pTextItem = new QGraphicsTextItem("QGraphicsTextItem", pV);
    auto pItem = (void*)pTextItem;

    auto items = m_pScene->items();
    auto item = (QGraphicsItem*)pItem;
    auto b1 = items.contains(item);

    auto item2 = (QGraphicsItem*)pTextItem;
    auto b2 = items.contains(item2);

    // QGraphicsSimpleTextItem
    auto pSimpleTextItem = new QGraphicsSimpleTextItem("QGraphicsSimpleTextItem", pV);
    auto pSimpleItem = (void*)pSimpleTextItem;

    auto SimpleItems = m_pScene->items();
    auto SimpleItem = (QGraphicsItem*)pSimpleItem;
    auto b3 = SimpleItems.contains(SimpleItem);

    auto Simpleitem2 = (QGraphicsItem*)pSimpleItem;
    auto b4 = SimpleItems.contains(Simpleitem2);

    int i = 0;
}

I want to use void * to store the pointer of the QGraphicsTextItem object created, and in another function, convert the void * pointer to a QGraphicsItem pointer for easy removal from the scene. However, I found that during the conversion, item and item2 point to different addresses; When converting QGraphicsSimpleTextItem pointers, there is no such problem. May I ask why this is happening or where I am using the problem , here is my demo:

MainWindow::MainWindow(QWidget* parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    m_pScene = new QGraphicsScene(this);
    m_pView = new QGraphicsView(ui->viewWidget);
    m_pView->setScene(m_pScene);

    m_pView->setWindowTitle("Graphics View");
    m_pView->resize(500, 500);

    auto x = new QPixmap(R"(D:\desktop\Data\2D\2.bmp)");
    pV = new QGraphicsPixmapItem(*x);
    m_pScene->addItem(pV);
    // QGraphicsTextItem
    auto pTextItem = new QGraphicsTextItem("QGraphicsTextItem", pV);
    auto pItem = (void*)pTextItem;

    auto items = m_pScene->items();
    auto item = (QGraphicsItem*)pItem;
    auto b1 = items.contains(item);

    auto item2 = (QGraphicsItem*)pTextItem;
    auto b2 = items.contains(item2);

    // QGraphicsSimpleTextItem
    auto pSimpleTextItem = new QGraphicsSimpleTextItem("QGraphicsSimpleTextItem", pV);
    auto pSimpleItem = (void*)pSimpleTextItem;

    auto SimpleItems = m_pScene->items();
    auto SimpleItem = (QGraphicsItem*)pSimpleItem;
    auto b3 = SimpleItems.contains(SimpleItem);

    auto Simpleitem2 = (QGraphicsItem*)pSimpleItem;
    auto b4 = SimpleItems.contains(Simpleitem2);

    int i = 0;
}
Share Improve this question edited Nov 20, 2024 at 9:19 Marek R 38.3k6 gold badges67 silver badges161 bronze badges asked Nov 20, 2024 at 8:38 user12660456user12660456 32 bronze badges 3
  • 1 Why converting to void* at all? Why not just store pointer to QGraphicsItem and then use qgraphicsitem_cast? What is rationale to abandon type system? Are you using some C-API which uses void*? – Marek R Commented Nov 20, 2024 at 9:21
  • Related/dupe: stackoverflow/a/5445220/4165552 cast from void* to base class is incorrect; The difference between those 2 poitners: item2 = (QGraphicsItem*)pTextItem can be explained by the class layout. – pptaszni Commented Nov 20, 2024 at 9:46
  • yes, I am using c style API – user12660456 Commented Nov 20, 2024 at 10:07
Add a comment  | 

2 Answers 2

Reset to default 0

When you convert the void* back to a strong pointer type, it must be the same type that you began with. But you do not do that.

Here

auto pTextItem = new QGraphicsTextItem("QGraphicsTextItem", pV);
auto pItem = (void*)pTextItem;

you convert a QGraphicsTextItem* to void*.

But here

auto item = (QGraphicsItem*)pItem;

you convert the void* back to a different type. This is wrong. You must convert it back to a QGraphicsTextItem*.

If you cannot do the back-conversion to QGraphicsTextItem*, then you must change the forward conversion such that you first convert the QGraphicsTextItem* to a QGraphicsItem* and then to void*:

auto pTextItem = new QGraphicsTextItem("QGraphicsTextItem", pV);
auto pGraphicsItem = static_cast<QGraphicsItem*>(pTextItem);
auto pItem = static_cast<void*>(pGraphicsItem);

The reason is that QGraphicsTextItem has multiple inheritance in the class hierarchy. On the other hand, QGraphicsSimpleTextItem only has single inheritance in the class hierarchy, which is the reason why your scheme works with the latter class.

This can be much simplified, not even need to have any UI:

#include <iostream>

#include <QApplication>
#include <QGraphicsTextItem>
#include <QDebug>

int main(int argc, char** argv) {
    QApplication app(argc, argv);
    auto pTextItem         = new QGraphicsTextItem("QGraphicsTextItem");
    auto pGrItem           = static_cast<QGraphicsItem*>(pTextItem);
    auto castedThroughVoid = static_cast<QGraphicsItem*>((void*)pTextItem);

    std::cout << "pTextItem: " << pTextItem << '\n';
    std::cout << "pGrItem: " << pGrItem << '\n';
    std::cout << "castedThroughVoid: " << castedThroughVoid << '\n';

    qDebug() << "pTextItem: " << pTextItem;
    qDebug() << "pGrItem: " << pGrItem;
    qDebug() << "castedThroughVoid: " << castedThroughVoid;
}

Sample output:

pTextItem: 0x5617e148cd20
pGrItem: 0x5617e148cd30
castedThroughVoid: 0x5617e148cd20
pTextItem:  QGraphicsTextItem(0x5617e148cd20, pos=0,0, flags=(ItemUsesExtendedStyleOption))
pGrItem:  QGraphicsTextItem(0x5617e148cd30, pos=0,0, flags=(ItemUsesExtendedStyleOption))
castedThroughVoid:  QGraphicsItem(0x5617e148cd20, parent=0x4d00000001, pos=1.63042e-322,2.122e-314, z=6.64185e-312)

The difference between pTextItem and pGrItem is due to multiple inheritance. QGraphicsTextItem is a QGraphicsObject and QGraphicsObject inherits both QObject and QGraphicsItem, so casting correctly to 2nd parent introduces an offset. Similar issue with multiple inheritance explained in this answer.

Then, your pTextItem and castedThroughVoid point to the same memory, but the cast is wrong (like explained already in the other answer), so dereferencing castedThroughVoid is Undefined Behavior, you can indeed see that the last qDebug print is showing garbage.

发布评论

评论列表(0)

  1. 暂无评论