1

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.

leemes
  • 44,967
  • 21
  • 135
  • 183

1 Answers1

3

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.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • I think you misunderstood my diagram. It is not a inheritance diagram but a QObject relationship diagram (the QObject tree). I'll clarify this in my question, sorry to be a bit inaccurate in this point. – leemes Oct 04 '12 at 20:56
  • @leemes - yes, I realized that right after I posted. See my edit, in a minute or two. Essentially the same logic, though. – Pete Becker Oct 04 '12 at 20:58
  • Thanks. I never understood the difference between C-style casting and `static_cast` somehow... If the ownership graph *will* change, the assertions are alert enough, that's why I put them there although I'm sure for now that the types will match. – leemes Oct 04 '12 at 21:00
  • 1
    @leemes - a C-style cast is a sledge-hammer. C++ casts have more finesse. If you think of a `static_cast` as undoing an implicit conversion you won't be far wrong. In this case, a `House` is derived from a `QObject`, so the `House*` gets converted internally into a `QObject*`; the `static_cast` just goes the other way. – Pete Becker Oct 04 '12 at 21:02