In my project I have a tree of QObjects with different types. Let me give you a simple example which should give you the idea of what I’m talking about. This could be an exemplary QObject tree (not an inheritance diagram but somewhat similar to a class diagram), where we start with the root object at the top and listing its child objects below:
City
|
Street
/ \
House ...
/ \
Floor ...
/ \
Room ...
While a QObject tree does not necessarily follow this rule, in my case very class in the tree has a parent of one particular type. So, to stay at one relation as an example, a house can have some floors and children of other types, but a floor is a child of a house and only a house.
Now if I model these as QObject derived classes, the interface of class Floor should give me its House *house() by internally looking what the QObject::parent() is. I really know that this parent will be of type House*, because I designed it to be so and the programmer(s) stick to this design.
Is it ok if I C-style cast the QObject *parent() to House* to implement House *house() const?
Qt suggests to use qobject_cast<House*>(parent()), returning 0 if the QObject* parent() doesn’t inherit from House, making the cast type-safe. But in release mode, I want to avoid such slow casts. I profiled one particular algorithm which is performing three times faster when doing C-style casts instead of qobject_casts. This is because qobject_cast asks the meta object about the type-info during runtime, resulting in considerable slowdowns when called very often.
So what I ended up with was:
House *Floor::house() const {
Q_ASSERT(qobject_cast<House*>(parent()));
return (House*)parent();
}
This will assert in debug mode that the parent really is a House, while just C-style-casting efficiently in release mode.
To come to the point: I know people will yell when C++ programmers do C-style casts, but will it be ok in this situation?
An alternative solution would be to store the parent pointers of the particular types additionally as member variables, but I think this is redundant and I also like that the tree is reflected in those methods returning the tree parents.
If you’re sure that the ownership graph won’t change, even during maintenance, then a cast that isn’t type-checked is safe. You can use
static_cast<House*>(parent()), which is fast, or, if you really want to, a C-style cast is okay. But the C-style cast is not faster than the C++static_cast.