I am creating a mixin between two classes using the boost::enable_shared_from_this template. So I am adding a new functionality to this class:
class MyOldClass :
public Connection,
public boost::enable_shared_from_this<MyOldClass>
{ ... };
I did use this before with a normal class (not a QtObject, just a C++ plain class) and everything works.
But now I am doing the same with a QMainWindow and it basically crash:
class MainWindow :
public QMainWindow,
public Connection,
public boost::enable_shared_from_this<MainWindow>
{ Q_OBJECT ... };
Is it possible that there is any problem doing this with a QObject? Not sure why this is happening.
Thank you.
You mentioned in the comments that you don't create a shared_ptr before you call shared_from_this(). But that's the problem. x.shared_from_this() only works once a shared_ptr to x exists. If you never create one, you're violating a precondition of shared_from_this(), so your program has undefined behaviour.
shared_from_this() only serves to retrieve a pointer sharing ownership with existing shared pointers; it cannot be used to create the first one.
Ok folks, it has been my fault but the answer could help to someone:
As Angew said it is necessary to create the first instance of MainWindow using a shared_ptr (I didn't understand your question the first time).
I was doing this but I was using the std::shared_ptr implementation instead of the boost::shared_ptr one. Mixing both was producing this results.
It works now but as Angew said one has to be very careful using shared_ptr's with the Qt ownership scheme.
The inheritance order specified in the MainWindow declaration is the only one valid. As Angew said: "When inheriting from QObject or a class derived from it, QObject (or that derived class) must be the first one in the base class list. So that won't work"
Thank you
Related
I am pretty new to Qt and C++ (been working on C# and Java all my life) and I have been reading almost everywhere that I shouldn't use raw pointers anymore (beside the ones in constructors and destructors, following RAII principle).
I am okay with it but there is a problem that I cannot easily resolve without pointers.
I'll try to explain my problem.
I am creating a QList of a custom class created by me (MyClass) that will act as a model for my application:
QList<MyClass> modelList;
This QList is updated (items added, removed or updated) by a worker thread on the basis of the information arriving from the network.
So far so good.
Now I have another thread (GUI one) that has a QList of drawable items (MyDrawableItem). Each of these items has a member that must point to one of the items in the first QList (modelList), like this:
QList<MyDrawableItem> listToDraw;
where:
class MyDrawableItem
{
private:
MyObject *pointedObject;
//List of many other members related to drawing
}
because everytime a timer in the GUI thread expires I have to update the drawing related members on the basis of the pointed object. Must note that it is safe to keep a pointer to members of QList as stated in the documentation:
Note: Iterators into a QLinkedList and references into heap-allocating
QLists remain valid as long as the referenced items remain in the
container. This is not true for iterators and references into a
QVector and non-heap-allocating QLists.
Internally, QList is represented as an array of T if sizeof(T) <=
sizeof(void*) and T has been declared to be either a Q_MOVABLE_TYPE or
a Q_PRIMITIVE_TYPE using Q_DECLARE_TYPEINFO. Otherwise, QList is
represented as an array of T* and the items are allocated on the heap.
How could this be feasible without using pointers? Or even better what should be the best way to do this kind of work?
I found three possible solutions:
Instead of keeping pointedObject as member of MyDrawableItem, keep the index of the pointed object in the modelList. Then on the update go look inside the QList. But what if the item in the list is removed? I could signal it but if the update happens before the slot is called?
Don't keep anything at all as a member and connect two signals to MyDrawableItem. One signal is updateDrawing(const MyObject&) that updates the drawing-related members and another signal is removeDrawing() that simply deletes the object. This way I don't have to worry about the syncronization between the threads because the MyDrawableItem object won't ever look at the content of the QList. In this case I could be updating the item very often with lots of signals while I only want to update the GUI once in a while (timer of 500 ms).
Simply use pointers.
Evolve and use QSharedPointers but I have never used those and I don't know if that is the best option.
I think that neither of these solutions is the perfect one so I am here asking for your help.
How do the standard views in Qt (tableview, listview, ecc.) deal with this problem?
How should I deal with it?
Please help me, I am thinking about this from yesterday and I don't want to make a mess.
Thanks a lot!
An addition to #Benjamin T's answer:
If you do decide to go for option 4 and use QSharedPointer (or the std variant), you can actually control ownership somewhat using "weak pointers". Weak pointers store a reference to the object, but do not own it. Once the last "strong pointer" gets destroyed, all the weak pointers drop the reference and reset themselves to nullptr.
For your concrete example, you could use a QList<QSharedPointer<MyClass>> for the model and use QWeakPointer<MyClass> in the drawable classes. Before drawing you would create a local QSharedPointer<MyClass> in the drawing function and check if it is valid.
I would still recommend you to use 2/3, as recommended by Benjamin. Just a small addition.
It is the current trend among the C++ community, especially if you look at all the CppCon conferences to discourage the use of raw pointers.
This trend is not without sold basis, as the use of std::shared_ptr and std::unique_ptr as well as std::make_unique and std::make_shared can help a lot memory management and prevent some pitfalls (like having an exception thrown during a call to a constructor).
However, there is nothing absolute in this "do not use raw pointers" trend and raw pointers can still be used and smart pointers do not solve all memory management problems.
Concerning the case of Qt, if you are dealing with QObject derived class and you properly parent your objects you are kind of safe as you have an owning hierarchy and parents QObjects will destroy their children. This is very important if you are also using QThread as QObject instances are associated with a QThread and all instances in a QObject hierachy are associated with the same thread.
Regarding your solutions:
Bad idea, you need to sync your list and the indexes all the time.
It could be an idea, but it changes the architecture of your software. Does MyObject really needs to know about MyObject ? If the answer is 'no', signal/slots seems a better solution. It might indeed require some work to solve your refresh rate issue, but this is off-topic.
It might look like a good idea, especially if your objects are inheriting QObject. Also you may want to use QVector<T *> and std::vector<T *> and let the QObject hierarchy deals with life span of your objects. You can listen to the destroyed() signal to know when the object are destroyed, or use QPointer. However, it does not solve the thread safeness on your consumer side, as the object might be deleted at any point in time from another thread.
If you cannot do 2, this is the option to go for. You just have to take care to not have cyclic dependencies or you will leak memory. However, this might be a bad idea if you want that when you delete an object in your list then it gets removed from your GUI object. If you simply keep a shared pointer, you will never know that it was removed from the list. As stated by #Felix, you can store weak pointers and convert them to shared pointers only when needed, but if you have consumers in multiple threads, then you may never delete the object. Also you have to make MyObject thread-safe as you are mutating it states from one thread and reading it from another thread. Using option 4 does change the owning model of your software: in the current state the QList owns the instances, with option 4 the ownership is shared with anyone getting a shared pointer.
My personal choice would be to replace the QList with a QVector of pointers.
If your objects inherit from QObject, then I would parent all the objects in the QVector to the object that owns the QList/QVector. This is to ensure proper parenting and thread association.
Then I would try option 2, and only if option 2 fails go for option 4.
Here is an exemple:
class MyClass : public QObject
{
Q_OBJECT
public:
explicit MyClass(QObject *parent = nullptr);
signals:
void stateChanged(int state);
};
class Owner : public QObject
{
Q_OBJECT
public:
explicit Owner(QObject *parent = nullptr);
void addObject(MyClass *obj) {
obj->setParent(this);
m_objects.append(obj);
}
void removeObject() {
delete m_objects.takeFirst();
}
private:
QVector<MyClass *> m_objects;
};
class Consumer : public QObject
{
Q_OBJECT
public:
explicit Consumer(QObject *parent = nullptr);
public slots:
void onStateChanged(int state) {
m_cachedState = state;
}
private:
int m_cachedState = 0;
};
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QThread thread;
thread.start();
Owner owner;
Consumer consumer;
consumer.moveToThread(&thread);
MyClass *object = new MyClass();
owner.addObject(object);
QObject::connect(object, &MyClass::stateChanged, &consumer, &Consumer::onStateChanged);
return app.exec();
}
This question already has answers here:
Do I have to delete it? [Qt]
(3 answers)
Closed 4 years ago.
When looking at Qt examples (on Qt documentation like movieplayer example, or here), I never see the member destructors explicitly called.
A class definition is like:
class foo : public QParent {
Q_OBJECT
QStuff stuff;
foo (QWidget *parent) : QParent(parent)
{
stuff = new QStuff(this);
}
};
My problem is that I never see something like delete stuff;
So my questions are:
Are QObject derived class instances which parent is not NULL automatically deleted when their parent is?
Is it dangerous to delete a QObject derived member without setting it to NULL?
I guess the answers are Yes and No, but I'm not sure.
For the first question yes. You can check the Qt docs here
where it is stated clearly:
QObjects organize themselves in object trees. When you create a
QObject with another object as parent, the object will automatically
add itself to the parent's children() list. The parent takes ownership
of the object; i.e., it will automatically delete its children in its
destructor. You can look for an object by name and optionally type
using findChild() or findChildren().
For the second question, the answer deserves a little bit more of explanation. If you have QObject pointers members that are not children of your object, you have to handle their disposal manually in the destructor of your class.
You can in theory use delete on any QObject* to invoke its destructor, but since Qt objects have a powerfull event system based on signals/slots, you must be aware of the interactions with event loops. If you brutally delete a QObject connected to another QObject while the latter one is still processing a signal coming from the first one, you may end up with some problems.
This holds in both mono and multi-threaded applications. You should therefore avoid the use of delete in favor of QObject::deleteLater() that will defer the deletion of the QObject until all the signal/slots related to it have been processed.
Lastly, in the context of the implementation of a destructor it doesn't really matter if you set the pointer to null, because it will be unavailable for further use anyway. It may be important if you delete the pointee in some other method, while your instance is still alive, and you set the pointer to null to flag it as uninitialized.
No, you do not need to delete member objects. They will get destroyed automatically when the parent class object gets destroyed.
See this FAQ.
In the case of Qt QObject pointer members, then the parent is the owner and is responsible for deleting the QObject. See here.
I have a startup class as such which sets up a SystemControllerin the construct:
m_systemController(new SystemController(this,
Provider::getSettingsAsSingleton())),
Essentially this satisfies:
public:
explicit SystemController(QObject *parent,
Settings& config);
I've recently though wanted to use this class in a threaded class, which doesn't like me passing me the SystemController as the threaded class doesn't have a parent. I tried passing it as such:
public:
explicit DataTestWorker(QObject *parent=0);//,
//SystemController &sysCtrl); //Obviously in my setup, it would complain about this
Where the DataTestWorker class is in fact the threaded class, initialised in a DataTest class. The reason I want to pass the memory location of the SystemController, is the Controller class has important data already setup in the class, which I wish to access without having to run all my initialisation methods within it again.
Is there a way to somehow pass it some sort of "shared" pointer - in which not only this class - but other classes can access it. The only way around this I can think of is I could use signals and slots between the DataTest and the DataTestWorker class to manipulate the values in the SystemController, but this would be long and verbose.
Any ideas? If you need anymore information, just ask.
Is It Possible to Use a Shared Pointer for the Parent of a QObject?
No. There is no shared pointer which is a subclass of QObject. And I don't see why it will make sense.
The reason I want to pass the memory location of the SystemController,
is the Controller class has important data already setup in the class,
which I wish to access without having to run all my initialisation
methods within it again.
Why don't you separate the notion of SystemController settings into another POD class\struct. Then you can have either
class SystemController : public QObject, public SystemSettings
or
class SystemController : public QObject
{
SystemSettings m_settings;
SystemSettings systemSettings() {m_settings};
}
and play around with the settings as you wish.
You can shape your SystemController to Singleton and put QMutex guards to access SystemController's private data used in concurrent threads.
I have recently began working with the Qt framework and realized there may be a bit about the syntax of C++ that I do not quite understand. Take for example this code that is given as a foundation when starting a Widget project in Qt.
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
Where the class MainWindow is defined as:
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
Class declaration
Stepping through this, I can see that a new namespace, Ui, is created. I imagine this to be an implementation effort to avoid naming conflicts with other user-implemented classes.
A new class definition follows; it inherits QMainWindow, so we are essentially creating a custom window object.
Q_OBJECT is apparently a macro that allows the user to use signals and slots in the class definitions, but I am not too worried about that code right now.
We define the constructor to be explicit thereby disallowing any implicit conversions of this class type. There is also a destructor shown.
In the private accesses, we look to the Ui namespace and create a MainWindow pointer.
Class definition
We are using an initialization list I see, but I get lost here. I see that we have a default parameter of NULL ( or 0 ) for the parent of this widget, but if a class inherents another class why must you explicitly call the constructor for said inherited class? That is:
class A {
}
class B : public A {
}
B testObject;
Does this not automatically allocate memory on the stack sufficient memory to contain both classes A and B? Why does the Qt code shown above call the constructor for an inherited class within its own constructor?
Continuing to the second parameter of the initialization list, I must say that I am confused on the syntax used here. Why do we have a pointer to a QMainWindow that we initialize by calling QMainWindow's constructor with a further call to new thereby creating an instance of itself? This initialization method seems circular.
We then call a setupUi function and pass this object for initialization.
And finally, in the destructor we simply deallocate the memory associated with the MainWindow.
As a final question, if an additional object is created, say a QPushButton, does the software automatically deallocate the memory assocated with these objects or must that be included in the destructor alongside delete ui? I have not seen a tutorial that actually does this, so I am not sure if the framework is designed such that it is handled for you.
I know there are few direct questions here, but is there any flaw in my logic for each statement?
tl;dr, skip to the first and second bullet under Class definition.
Please note that you should not ask so many sub-questions in a question, but I will try to answer your questions regardless ...
Does this not automatically allocate memory on the stack sufficient memory to contain both classes A and B?
It allocates memory for the base class, yes.
Why does the Qt code shown above call the constructor for an inherited class within its own constructor?
Because that is how C++ inheritance works. You need to initialize the base class explicitly in cases like this It could be implicit in an ideal with default constructors, but you are not even using that in here which is good.
Why do we have a pointer to a QMainWindow that we initialize by calling QMainWindow's constructor with a further call to new thereby creating an instance of itself? This initialization method seems circular.
As you explained in the beginning, you have two separate MainWindows, one generated by the Qt Designer, and one class implementation in your code, thus the namespaces you mentioned.
As a final question, if an additional object is created, say a QPushButton, does the software automatically deallocate the memory assocated with these objects or must that be included in the destructor alongside delete ui? I have not seen a tutorial that actually does this, so I am not sure if the framework is designed such that it is handled for you.
If you allocate it on the stack, it is not necessary since it will be destroyed automatically when running out of scope. If you allocate that on the heap, in the Qt world, you specify the parent as the argument for the constructor so that it gets deleted automatically when the parent gets deleted. This is done transparently for you by the Qt parent-child hierarchy and mechanism. That is why you do not see explicit delete usually in examples.
I know that Qobjects are supposed to be identities not values eg you cannot copy them and by default the copy constructor and assignment are disabled as explained in qt documentation. But is it possible to create a new QObject from an existing one using a clone method? Would this be a logic error ?
If I say
QObject b;
QObject a;
b.cloneFrom(a);
or
QObject a = new QOBject();
QObject b = new QOBject();
b->cloneFrom(a);
and the clone method copies stuff like members etc would this be wrong?
And if this is ok can I write my own copy constructor and assignment operator that does just that?
Note: I actually want to try this with classes that inherit qobject.
in my opinion cloning QObjects is almost always semantically broken and leads to unwanted side-effects, due to them having an "identity" as you already said. Therefore, cloning breaks all the assumptions one has about QObjects, like their signal/slot connections and dynamic properties. You should consider if the objects to clone really need to be QObjects, or if the "value-part" you want to have cloned could be factored out.
And if at all, cloning makes only sense for your specific subclasses of QObjects, not for QObjects themselves (which have no real "value-like" properties).
also, A; B; A.cloneFrom( B ) looks broken, as it doesn't work if B is instance of a subclass of B instead of B itself.
Clone should be done via a virtual B* B::clone() const I'd say.
I think that the best practice in this case to create class with the data you want to copy between QObjects. This class should not be derived from QObject or any class derived from QObject. And this class will be "value container". In this case you should be able to solve your problem in really good way.
One more tip: for this class you can use implicit data sharing with copy on write to reduce overhead of unnecessary copying: http://doc.qt.io/qt-5/implicit-sharing.html