qgraphicsitem_cast vs. dynamic_cast

Alles rund um die Programmierung mit Qt
Antworten
phlox81
Beiträge: 97
Registriert: 7. Juli 2009 12:30
Kontaktdaten:

qgraphicsitem_cast vs. dynamic_cast

Beitrag von phlox81 »

Moin,

ich habe gerade einen etwas komischen Fall.
Ein Item wird mit qgraphicsitem_cast gecastet, und ist danach das was es nicht ist.

Code: Alles auswählen

EndItem* end = qgraphicsitem_cast<EndItem*>(item);
if(end)
    ar & end;
else
{
    StartItem* start = qgraphicsitem_cast<StartItem*>(item);
    if(start)
        ar & start;
}
End und StartItem Erben jeweils von BaseItem<QGraphicsEllipseItem>, welches von seinem Parameter erbt, sind also beides von QGraphicsEllipseItem abgeleitete Klassen. Paint ist überschrieben, das wars auch schon.
Dynamic_cast funktioniert hier ohne Probleme, wieso schlägt qgraphicsitem_cast also hier fehl, und castet mein StartItem zu einem EndItem?

phlox
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

also, nur ob ich es recht verstehe:

Code: Alles auswählen

template <typename Base>
class BaseItem : public Base
{
 ///
};

class StartItem : public BaseItem<QGraphicsEllipseItem>
{
 ///
};
Der qgraphicsitem_cast schaut so aus:

Code: Alles auswählen

template <class T> inline T qgraphicsitem_cast(QGraphicsItem *item)
{
    return int(static_cast<T>(0)->Type) == int(QGraphicsItem::Type)
        || (item && int(static_cast<T>(0)->Type) == item->type()) ? static_cast<T>(item) : 0;
}
Ist also ein "leichter Wrapper um static_cast". dynamic_cast ist ja recht langsam.

Die einzige Lösung, die mir einfällt, ist mit den types rumzuspielen ;)
Z.B.:

Code: Alles auswählen

class StartItem : public BaseItem<QGraphicsEllipseItem>
{
public:
    enum { Type = QGraphicsItem::UserType + 1 }
    int type() const { return Type; }
};

class EndtItem : public BaseItem<QGraphicsEllipseItem>
{
public:
    enum { Type = QGraphicsItem::UserType + 2 }
    int type() const { return Type; }
};
Um das zu vereinfachen, wäre es auch sicher schön, den type schon in BaseItem zu verarbeiten:

Code: Alles auswählen

template <typename Base, int UserTypeOffset>
class BaseItem
{
public:
    enum { Type = QGraphicsItem::UserType + UserTypeOffset };
    int type() const { return Type };
};

class StartItem : public BaseItem<QGraphicsEllipseItem, 1>
{};
Ist aber ungetestet ;)

// edit:
Juppidu, funktioniert ;)

Code: Alles auswählen

#include <QtGui>
#include <QDebug>

template <typename Base, const int UserTypeOffset>
class BaseItem : public Base
{
    public:
        enum { Type = QGraphicsItem::UserType + UserTypeOffset };
        int type() const { return Type; }
};

class StartItem : public BaseItem<QGraphicsEllipseItem, 1>
{};

class EndItem : public BaseItem<QGraphicsEllipseItem, 2>
{};

int main(int argc, char** argv)
{
    QApplication app(argc, argv);
    QGraphicsItem *si = new StartItem;
    QGraphicsItem *ei = new EndItem;
    qDebug() << qgraphicsitem_cast<EndItem*>(ei);
    qDebug() << qgraphicsitem_cast<EndItem*>(si);
    qDebug() << qgraphicsitem_cast<StartItem*>(ei);
    qDebug() << qgraphicsitem_cast<StartItem*>(si);
}
phlox81
Beiträge: 97
Registriert: 7. Juli 2009 12:30
Kontaktdaten:

Beitrag von phlox81 »

Hatte immer noch nicht funktioniert, daher hab ich alles auf dynmic_cast umgestellt, die Kosten sind ok.
Problem was es ausgelöst hat war aber ein anderes.
Ich habe einen eigenen Object Tracker, der beim speichern und laden jeweils mit trackt. Und da hab ich vergessen ihn zu resetten.
Ungültige void* in dynamic_cast machen spass. :lol:
Antworten