简体   繁体   中英

Shouldn't qobject_cast fail silently in this case?

I'm trying to code an application in Qt which was going relatively well until I bumped into this stupid problem. I have a Node class which can have a pointer to a Workplace class instance. I have also defined getter/setter methods for that pointer. Something like this:

class Node : public QGraphicsItem
{
    Q_DECLARE_TR_FUNCTIONS(Node)

public:
    Node(const QString &type, Project* nodeProject);
    ~Node();

    void setWorkplace(Workplace* workplace);
    void removeWorkplace();
    Workplace* usedWorkplace();

    (...)
private:    
    Workplace* myWorkplace;
}

So, now in my code, I have to check if a certain Node has a pointer to a Workplace defined, in order to do some operations with that info. This is how I am doing it:

Workplace* currentWorkplacePointer = qobject_cast<Workplace*>(node->usedWorkplace());
if(!currentWorkplacePointer){
     // no workplace, do some stuff
}else{
     // workplace exists, do other stuff
}

This was working perfectly, but now for some reason it seg faults randomly . I say randomly because sometimes, if I try to clean and rebuild the project, it works correctly - ie, the qobject_cast fails silently and procedes as I intended; other times, even if I clean/rebuild, it seg-faults again.

The debugger console always points to the object cast line in my code above. To the best of my knowledge, shouldn't the cast simply fail silently if the casted object does not exist?

Please note that I am very new to Qt/C++, so any help and comments are appreciated - just please be gentle! :) Thanks in advance!

As well say by Sebastian Redl, it seem a nonsense to cast a pointer in itself type. Nevertheless, your code could be improve for future usage of casting. My first point come from documentation of qobject_cast that impose to call Q_OBJECT macro in your class header to be usable.

Secondly, as your Node inherits QGraphicsItem , I would suggest to use qgraphicsitem_cast instead, which is faster in different manner when processing or filtering items present in a scene. Adaptation from the doc

 class Node : public QGraphicsItem
 {
    ...
    enum { Type = UserType + 1 };

    int type() const
    {
        // Enable the use of qgraphicsitem_cast with this item.
        return Type;
    }
    ...
 }

//in your application code
Node *n = qgraphicsitem_cast<Node*>(expected_pointer_on_node);
if (n) {
//then n points a Node
}

This was actually much simpler than I thought, and my problem actually related to the fact that the node->usedWorkplace() method couldn't return anything, as the Workplace* wasn't initialized before I tried to go get it. Dumb, I know...

As such, I simply initialized the pointer as 0 (Thank you, @ratchetfreak), and work from there. Everything's working fine now.

So, when I create the instance of Node , I initialize the pointer as 0 this way:

nodeToPlace->setWorkplace(0);

Then, when I want to check for the existence of Workplace* for a Node instance:

Workplace* tempWorkplace = node->usedWorkplace();
if(!tempWorkplace){
     // do stuff
}else{
     // other stuff
}

So I didn't actually need the qobject_cast at all.

NOTE: this ended up not relating/answering to my question about the qobject_cast failing silently. What I ended up discovering is that the cast will return 0 either if it fails or if you try to cast 0 into something. I think that with my initial code the latter was occurring.

From the IBM Linux Compilers documentation (reports to C++'s dynamic_cast which according to Qt's docs is roughly equivalent):

The expression dynamic_cast(v) converts the expression v to type T. Type T must be a pointer or reference to a complete class type or a pointer to void. If T is a pointer and the dynamic_cast operator fails, the operator returns a null pointer of type T. If T is a reference and the dynamic_cast operator fails, the operator throws the exception std::bad_cast.

Therefore, I would conclude that I was refering garbage as the arg of the cast, which made my application seg fault (as @hyde mentioned in the comments, hence my +1 to him as well).

If someone has a different opinion and/or explanation, please let me know - I would like to learn more about my errors/mistakes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM