Reputation: 3245
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!
Upvotes: 1
Views: 989
Reputation: 3245
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.
Upvotes: 0
Reputation: 2969
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
}
Upvotes: 1