But they also can't be deleted easily, they are not thread-safe, can't participate as equals in multiple inheritence, can not be used at all in virtual inheritence.
If you have not explicitly connected any signals or slots, and the only events you might get are dispatched with qApp->postEvent(), not qApp->sendEvent(), then it is safe to delete the QObject in the Qt event thread. If your QObject is a GUI object you've passed given to Qt for it to delete all is good. If your object is only deleted in response to a posted event or a signal from the Qt event thread (say from a QTimer()) then you are OK as well.
If your class may be deleted outside a Qt thread, but it does not explicitly connect any signals or slots, and the only events it might get are dispatched with qApp->postEvent(), then you can safely use deleteLater() to queue your object up for deletion in the event thread.
MythTV is a very much a multithreaded program so you may need to have a QObject that may get events from another thread if you send signals but do not get any signals and or events from outside the Qt event thread, then you can use deleteLater() or delete depending on whether you are deleteing the QObject in the event thread, see above. But if you are not in the Qt event thread then you need to call disconnect() in the thread that is sending the signals, before calling deleteLater(). This prevents your object from sending events after you consider it deleted (and begin to delete other QObjects that may still be getting signals from your object.)
What about if you are getting events via qApp->sendEvent() or a signal from another thread? In this case things get complicated, so we highly discourage this in MythTV and prefer that you use callbacks if at all possible. But in say you need to do this, then you need to disconnect all the signals being sent to your QObject. But disconnect() itself is not atomic. That is you may still get a signal after you disconnect it. What you need to is disconnect the signal from your slot in the thread that is sending the signal. This prevents the signal from being emitted while you are disconnecting. Doing this gracefully is left as an excersize for the reader.
Ok, so the above is not entirely complete, for instance you could wrap every signal emit in an instance lock and reimplement a disconnect that uses that instance lock. But if you've figured this or another solution out already all you need to know is that almost all Qt objects are reenterant but not thread-safe, and that QObjects recieve events and signals from the Qt event thread and from other threads if you use qApp->sendEvent() or send signals to it from another thread.
QObject itself is pretty safe because when you assign one QObject to another you make a copy. Qt's container classes, including QString do not make a copy but rather pass a reference counted pointer to the data when you assign one to another. This reference counter is not protected by a mutex so you can not use regular assignment when passing a QString or other Qt container from one thread to another.
In order to use these classes safely you must use QDeepCopy when passing them from one thread to another. This is thankfully quite easy to use.
QString original = "hello world";
QString unsafe = original;
QString safe = QDeepCopy<QString>(original);
In this case safe and original can be used by two seperate threads, while unsafe can only be used in the same thread as originalStr.
The QDeepCopy template will work on the most popular Qt containers, for the ones it doesn't support you will have to copy manually.
For the similar reason you can not inherit a QObject derived class virtually, in this case the badness is a little more complicated. The result is the same however, signals arrive at the wrong slot. Usually, what happens is that the developer tries to inherit two QObject derived classes but gets linking errors, so they make one or more of the classes virtual, or inherit a QObject non-virtually but then also inherit one or more QObject derived classes virtually. The linker doesn't complain, but strange unexplainable behaviour ensues when the application is run and signals start showing up on the wrong slots.
1.5.1