Results 1 to 7 of 7

Thread: regarding qgraphicsitem_cast

  1. #1
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default regarding qgraphicsitem_cast

    Hello guys,
    I am facing some problems with qgraphicsitem_cast which casts in a wrong manner resulting in crashes.
    Because of this now I am forced to check manually the value of type() function and then cast.
    I am using Qt4.2.2 on linux.

    The following working example illustrates my problem.
    Is there something wrong in my code or is it a Qt bug ??

    Qt Code:
    1. #include <QtGui>
    2.  
    3. class Item : public QGraphicsItem
    4. {
    5. public:
    6. enum ItemTypes {
    7. ItemType = UserType+5,
    8. ComponentType,
    9. WireType,
    10. };
    11.  
    12. Item() : QGraphicsItem(0,0) { }
    13.  
    14. QRectF boundingRect() const { return QRectF(-20,-20,40,40); }
    15.  
    16. void paint(QPainter *p,const QStyleOptionGraphicsItem *, QWidget *)
    17. {
    18. p->drawLine(-20,-20,20,20);
    19. }
    20. int type() const { return ItemType; }
    21. };
    22.  
    23. class Component : public Item
    24. {
    25. public:
    26. int type() const { return Item::ComponentType; }
    27. };
    28.  
    29. class Resistor : public Component
    30. {
    31. };
    32.  
    33.  
    34. class Wire : public Component
    35. {
    36. public:
    37. int type() const { return Item::WireType; }
    38. };
    39.  
    40. int main(int argc,char *argv[])
    41. {
    42. QApplication app(argc,argv);
    43. QGraphicsScene sc(0,0,500,500);
    44.  
    45. Resistor * r= new Resistor();
    46.  
    47. sc.addItem(r);
    48. r->setPos(50,50);
    49. v.setScene(&sc);
    50. v.show();
    51.  
    52. // The problematic part
    53. Wire *w = qgraphicsitem_cast<Wire*>(r);
    54. if(w != 0l) // this always happens
    55. {
    56. qDebug("WRONGLY CASTED");
    57. Q_ASSERT(0);
    58. }
    59.  
    60. return app.exec();
    61. };
    To copy to clipboard, switch view to plain text mode 

    I checked the source of qgraphicsitem_cast but I couldn't understand how it works. Can somebody enligten me ?

    Qt Code:
    1. template <class T> inline T qgraphicsitem_cast(QGraphicsItem *item)
    2. {
    3. return int(static_cast<T>(0)->Type) == int(QGraphicsItem::Type)
    4. || (item && int(static_cast<T>(0)->Type) == item->type()) ? static_cast<T>(item) : 0;
    5. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by Gopala Krishna; 23rd December 2006 at 08:38. Reason: changed inappropriate title

  2. #2
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: buggy qgraphicsitem_cast

    Sorry for the above post. I didn't read the documentation properly. Now i understand that "Type" enum should be declared in custom class to point to custom value.

    Well anyway I still have doubt about the second question I asked.

  3. #3
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: buggy qgraphicsitem_cast

    First you have:
    Qt Code:
    1. Resistor * r= new Resistor();
    To copy to clipboard, switch view to plain text mode 
    and then:
    Qt Code:
    1. Wire *w = qgraphicsitem_cast<Wire*>(r);
    To copy to clipboard, switch view to plain text mode 
    You're trying to cast a Resistor object to a Wire object, but Resistor doesn't inherit Wire, thus the cast returns 0 and you're dereferencing a null pointer, so the branch is triggered.

  4. #4
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: regarding qgraphicsitem_cast

    Quote Originally Posted by wysota View Post
    You're trying to cast a Resistor object to a Wire object, but Resistor doesn't inherit Wire, thus the cast returns 0 and you're dereferencing a null pointer, so the branch is triggered.
    Thanks for the reply.
    Sorry, i think you got it otherway. (it was if(w != 0l))
    Actually I wanted the cast to fail but it didn't used to since I hadn't declared Type to point to return value of corresponding type() in my subclasses.
    This resulted in cast from Resistor to Wire succesful causing crashes and I not having understood the doc well posted an example to show that there was bug in qt !! (how dumb of me)
    Also I couldn't understand the source of qgraphicsitem_cast.

  5. #5
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: regarding qgraphicsitem_cast

    Quote Originally Posted by Gopala Krishna View Post
    Sorry, i think you got it otherway. (it was if(w != 0l))
    The "l" mislead me. In C++ you don't have to cast nulls to long so the "l" is not necessary.

    Actually I wanted the cast to fail but it didn't used to since I hadn't declared Type to point to return value of corresponding type() in my subclasses.
    Yes, the Resistor class lacks the type() method and the Type is not set correctly.

    Also I couldn't understand the source of qgraphicsitem_cast.
    This is quite easy once you know what static_cast<T>(0)->Type means.

    This is the same as T::Type (the static member Type of class T). So essentially what the cast does is that it checks whether you're not casting the pure abstract class QGraphicsItem and that the Type member of the target class matches the type value returned by the source object.

  6. The following user says thank you to wysota for this useful post:

    Gopala Krishna (23rd December 2006)

  7. #6
    Join Date
    Dec 2006
    Posts
    9
    Thanked 6 Times in 5 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: regarding qgraphicsitem_cast

    I checked the source of qgraphicsitem_cast but I couldn't understand how it works. Can somebody enligten me ?
    I'll give it a try.

    At first one could rewrite the ternary conditional to an if-then-else clause, it would look like:
    Qt Code:
    1. if( int(static_cast<T>(0)->Type) == int(QGraphicsItem::Type) )
    2. return static_cast<T>(item);
    3. else if( item && int(static_cast<T>(0)->Type) == item->type()
    4. return static_cast<T>(item);
    5. else
    6. return 0;
    To copy to clipboard, switch view to plain text mode 


    I think the most interesting part of it is the
    Qt Code:
    1. int(static_cast<T>(0)->Type)
    To copy to clipboard, switch view to plain text mode 
    expression. It blesses/casts a 0 to type T. This ensures that T is a pointer. Basically one can give any type to the template but if it is not a pointer this cast would fail. Than the member Type is requested from it. This is okay cause Type behaves like a static member of class *T.

    Then again the value of Type is casted to int this is done so it can compared with the other Type vars, as you know normally members of different enum can't be compared.

    So the first comparison
    Qt Code:
    1. int(static_cast<T>(0)->Type) == int(QGraphicsItem::Type)
    To copy to clipboard, switch view to plain text mode 
    simply checks if the Type of T is equal to the Type of the basic QGraphicsItem.
    If thats the case item will be casted to T and returned.

    If thats not the case
    Qt Code:
    1. (item && int(static_cast<T>(0)->Type) == item->type())
    To copy to clipboard, switch view to plain text mode 
    will be evaluated. It checks if item is a NULL pointer if thats the case the evaluation fails, else it checks if the type of item is equal to the type of the target for the cast operation, IOW if the cast is possible. If thats the case the cast operation is performed if not the whole cast fails.

    Please correct me if I'm mistaken somewhere.

  8. The following 2 users say thank you to ggrinder for this useful post:

    Gopala Krishna (23rd December 2006), niko (21st September 2007)

  9. #7
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: regarding qgraphicsitem_cast

    Thanks wysota and ggrinder for explaining me. Now I know how it works. This really helped learn an important c++ concept.
    Going through qt source helps you fine tune your basic skills too. Thanks to trolls and all those who contributed to qt.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.