我使用Qt QGraphicsScene类,添加预先定义的项目,如QGraphicsRectItem,QGraphicsLineItem等我想现场的内容序列化到磁盘.但是,基QGraphicsItem类(我使用的其他项派生自)不支持序列化,所以我需要滚动自己的代码.问题是所有对这些对象的访问都是通过基QGraphicsItem指针进行的,所以我的序列化代码很糟糕:
QGraphicsScene* scene = new QGraphicsScene;
scene->addRect(QRectF(0, 0, 100, 100));
scene->addLine(QLineF(0, 0, 100, 100));
...
QList<QGraphicsItem*> list = scene->items();
foreach (QGraphicsItem* item, items)
{
if (item->type() == QGraphicsRectItem::Type)
{
QGraphicsRectItem* rect = qgraphicsitem_cast<QGraphicsRectItem*>(item);
// Access QGraphicsRectItem members here
}
else if (item->type() == QGraphicsLineItem::Type)
{
QGraphicsLineItem* line = qgraphicsitem_cast<QGraphicsLineItem*>(item);
// Access QGraphicsLineItem members here
}
...
}
Run Code Online (Sandbox Code Playgroud)
这不是好的代码恕我直言.所以,我可以像这样创建一个ABC类:
class Item
{
public:
virtual void serialize(QDataStream& strm, int version) = 0;
};
class Rect : public QGraphicsRectItem, public Item
{
public:
void serialize(QDataStream& strm, int version)
{
// Serialize this object
}
...
};
Run Code Online (Sandbox Code Playgroud)
然后我可以使用添加Rect对象 QGraphicsScene::addItem(new Rect(,,,));
但这并没有真正帮助我,因为以下将崩溃:
QList<QGraphicsItem*> list = scene->items();
foreach (QGraphicsItem* item, items)
{
Item* myitem = reinterpret_class<Item*>(item);
myitem->serialize(...) // FAIL
}
Run Code Online (Sandbox Code Playgroud)
我能以任何方式使这项工作?
我同意其他海报的观点,QGraphicsItem确实可以被视为一个视图项,因此将模型数据分离到它自己的类中可能会更好。
也就是说,我认为你的崩溃是由于演员阵容不当造成的。
如果您执行以下操作:
Rect *r = new Rect();
QGraphicsItem *qi = reinterpret_cast<QGraphicsItem*>(r);
QGraphicsRectItem *qr = reinterpret_cast<QGraphicsRectItem*>(r);
Item *i = reinterpret_cast<Item*>(r);
qDebug("r = %p, qi = %p, qr = %p, i = %p", r, qi, qr, i);
Run Code Online (Sandbox Code Playgroud)
您应该看到 r == qi,r == qr,但是 r != i。如果您考虑如何在内存中表示多重继承的对象,则第一个基类在内存中第一个,第二个基类在第二个,依此类推。因此,指向第二个基类的指针将偏移第一个基类的大小[大约]。
因此,要修复您的代码,我认为您需要执行以下操作:
QList<QGraphicsItem*> list = scene->items();
foreach (QGraphicsItem* item, items)
{
Rect* myrect = reinterpret_class<Rect*>(item); // needed to figure out the offset to the Item part
Item* myitem = reinterpret_class<Item*>(myrect);
myitem->serialize(...);
}
Run Code Online (Sandbox Code Playgroud)
这是众多原因之一,我喜欢尽可能避免多重继承。我强烈建议按照之前的建议分离模型数据。