I am learning Qt framework (C++) and was wondering if QT has any mechanisms to protect slots from being called before an object is fully initialized.
Consider Class A constructor:
A::A() {
mTreeView = new QTreeView();
...
connect(mTreeView, &QTreeView::customContextMenuRequested,
this, &A::OnContextMenuRequested);
...
}
My worry is the user would be able to right-click on the tree-view before A's constructor has finished. Another context is as follows:
A::A() {
mQObj = new MyQObject();
connect(mQObj, &MyQObject::SomeEvent, this, &A::OnEvent);
}
A::InitB() { mB = new B(); }
A::OnEvent() { mB.doSomething(); }
Here, the doSomething() method can be called before InitB() runs.
Do I have to worry about such scenarios? And if so, is there a way to avoid these issues without having to initialize all your objects first, then going back and connecting the events afterwards separately?
You don't have to worry about such scenarios in most cases, because events are delivered in the same thread. There's no "hidden multithreading" going on you have to care about. If you don't explicitly call a function in the constructor of A that causes events to be processed, you're safe and your current method, slot etc.'s execution is completed before the next event is processed.
That said, the cases where a new event is processed and thus other code (event handlers, slots) is executed, are:
A
) and Qt returns to the event loop to wait for the next event. In your case, that's after the A instance is fully constructed.1) is the normal mode Qt operates in: You start app.exec(), which starts the event loop. Everything after that is directly or indirectly triggered by an event (user input, timer, I/O). Event happens and is added to the event loop's event queue. The event loop calls the event handlers for the event. When the event handlers are completed, the event loop picks the next event and calls the handlers for it.
So everything happens in an orderly fashion, one event after another, unless one of the event handlers (say, a slot listening to a button's clicked() signal) does one of 2, 3 or 4. Then Qt processes the next event in-place, .i.e. where exec() or processEvents() is called. The event handlers/slots are executed accordingly. Then exec()/processEvents() returns. Now all the certainties one would have without calling exec()/processEvents() are gone, unfortunately: The user could have done random stuff, things could be arbitrarily changed or deleted (even the this
pointer, if the user closed the window, for example). Thus especially 2) and 3) are error-prone and usually lead to major headaches, so I would avoid them whenever possible, or at least be aware of the potential issues.
Now there's the case that you use multithreading yourself. As all the actual UI and related user events is handled in a single main thread, multithreading here usually means that you have threads doing non-UI work and that interacts with your UI thread by calling functions on objects living in the UI thread, modifying data shared by both threads, or using cross-thread signal/slot connections.