Qt: Creating QStackedLayout - c++

Please take a look at the following code:
QStackedLayout stackLayout(this);
QStackedLayout stackLayout = QStackedLayout(this);
I have two questions:
Why is the second statement not possible?
How can I call the constructor of QStackedLayout when I declare the variable in a header file not as a pointer?

First of all, I think you are misinterpreting the constructor. Qt takes a parent for its elements because it will manage their storage duration when created on the heap:
// here you need this constructor, so Qt will free the resource for you
QStackedLayout * layout = new QStackedLayout(this);
// here you don't need it, the object has automatic storage duration
QStackedLayout layout;
Then, if you want to call a certain constructor for an object declared in your header file, use the initialization list:
struct foo
{
foo()
: s("demo")
{}
std::string s;
};
The object derives from QObject and thus is not copyable - that's why your second statement does not work.

you should define stackLayout as a pointer
QStackedLayout* stackLayout = new QStackedLayout(this);

The first question is easy: QStackedayout inherites QObject. You can never copy or assign QObjects.
The second question what you do is to call the constructor of QStackedLayout. But I suppose you really want to know, how to do this in your .h file? There only the default constructor is possible. Pointers are fine in this case. Or you put QStackedLayout layout in your .h file and add something like layout.setParent(this) in your constructor. I never did this. It looks strange to me. So I don't know if there are any drawbacks.
Edit: Erm... blush... the 'only default constructor' is of course nonsense. Sometimes it pays to think a second or two longer. Especially about constructs, which oneself rarely uses. :-)

Related

Where shall I put new/delete when creating a class

I have a portion of code that I tested and works, and now I would like to make it a class in order to have something cleaner.
The following code creates a scene containing a rectangle and displays it on the widget 'graphicview'
QGraphicsScene *scene = new QGraphicsScene;
QGraphicsRectItem *rect = new QGraphicsRectItem();
rect->setRect(0,0,100,100);
scene->addItem(rect);
ui->graphicsView->setScene(scene);
What I would like now is to create a class that contains this scene, so that I just have to call :
MyClass *myscene = new MyClass;
ui->graphicsView->setScene(myscene->scene)
The quetion is, in the class MyClass, shall I have a private argument declared as QGraphicsScene *scene = new QGraphicsScene;, or just a private argument QGraphicsScene *scene and then within the constructor *scene=new QGraphicsScene
And the same for where I should put the delete, within the destructor of MyScene?
edit : Based on answer, I tried to rework my code without new:
QGraphicsScene scene;
QGraphicsRectItem rect;
rect.setRect(0,0,100,100);
scene.addItem(&rect);
ui->graphicsView->setScene(&scene);
But this code doesn't work (widget 'graphicView' displays nothing), and all the example I found of Qt use the new operator. What I am missing ?
Avoid (Raw) pointers as much as your performance and clarity considerations allow. For example, In your code, It's not necessary to use pointers. Instead, define your scene as a member of your class:
class MyCalss
{
...
QGraphicsScene scene;
};
And then set it for a view:
MyClass myscene;
ui->graphicsView->setScene(&myscene.scene);
So, from now on, before using pointers, ask this question from yourself, Is it necessary to use pointers? If you have to use pointers, put smart pointers in your considerations too.
There is no "specific" place to put new and delete. It entirely depends on where you need a dynamic allocation of memory (new) and once the job od dynamically allocated memory(the variable) is over you need to free that (delete) keeping in mind that the variable won't be used anywhere else as it would lead to undesired behavior.
If at every object creation of a class, the class variable needs to be dynamically allocated right from starting, do it in constructor. Similarily if the variable is used throughout object lifetime delete it in destructor. This is just a very high level idea. I would suggest reading this and also reading more about pointers (smart pointers) and dynamic memory allocation

Qt code questions perhaps pertaining to C++ in general

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.

C++ - Why do I create these widgets on the heap?

When creating a GUI with C++ and Qt you can create a label for example like this :
QLabel* label = new QLabel("Hey you!", centralWidgetParent);
This creates the object on the heap and will stay there until I either delete it manually or the parent gets destroyed. My question now is why do I need a pointer for that? Why not create it on the stack?
//Create a member variable of Class MainWindow
QLabel label;
//Set parent to show it and give a text so the user can see it
QWidget* centralWidget = new QWidget(this); //Needed to add widgets to the window
this->setCentralWidget( centralWidget );
label.setParent(centralWidget);
label.setText( "Haha" );
This works fine, I can see the label and it did not vanish.
We use pointers in C++ to let something live longer so we can use an object in various scopes. But when I create a member variable, won't it stay until the object gets destroyed?
Edit:
Maybe I didn't clarify it enough. This is the MainWindow class:
class MainWindow : public QMainWindow
{
Q_OBJECT
QLabel label; //First introduced here...
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
};
//Constructor
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QWidget* centralWidget = new QWidget(this);
this->setCentralWidget( centralWidget );
label.setParent(centralWidget);
label.setText( "Haha" );
}
If your label gets out of the scope, the destructor (QLabel::~QLabel) will be called. From the docs:
Destroys the object, deleting all its child objects.
It is not necessary to create object on the heap - you could put the object on the stack, but then you need to be responsible about lifetime of the object (the one of the most problematic issues about allocating data on the heap is the question of "who and when should delete these objects?", and in Qt it is handled by the hierarchy - whenever you delete your widget, all the child widgets will be deleted).
Why your program works - I don't know - it may just not work (label is destroyed at the end of the scope). Another issue is - how will you change the text of the label (from some slot, for example) if you don't have a reference to it?
Edit I just saw that your label is a member of the MainWindow. It is perfectly fine to have a complete objects, and not the pointer to the objects as the member of your class, as it will not be destroyed before MainWindow is. Please note that if you create instance of your MainWindow like this:
MainWindow *w = new MainWindow();
label will be created on the heap.
Because that is how Qt was designed. I realize that's not a very satisfying answer, but Qt was simply designed as "widgets are created on the heap, and parents are responsible for deleting their children".
Realize that the origins of Qt are old, older than what we consider "modern C++".
Another thing to keep in mind is that Qt uses the so called pimpl paradigm where object data is implicitly shared and managed behind the class you actually instantiate. See here: http://qt-project.org/wiki/Dpointer
The bottom line is that if you are allocating on the stack in order to avoid using the heap, Qt is just pulling a fast one on you and using the heap anyway.
Allocating a widget as a local variable typically is not a good idea, since usually it will go out of scope before being useful in any way; since QObject supports the composition pattern via its "parent-child" relationships (that are well integrated with C++ destructors), usually the simplest thing is just to exploit such a feature.
On the other hand, you can make it a member of your MainWindow class, or in general allocate it in any way such that it has a lifetime less than the lifetime of its parent. In facts, when such QLabel is destroyed, it automatically deregisters from its parent, avoiding double deallocation. But often is more comfortable just to allocate the widgets on the heap, registering them as children of the current window, since usually you don't actually need to access many widgets after you created them (e.g. labels), so it's not necessary to clutter your class with useless data members. You just do new QLabel(this, ...) into your window constructor and that's it.
What you should not do, instead, is to allocate your widgets without new if their lifetime gets longer than the lifetime of their parent (e.g. putting them in a global or static variable) - doing this will cause the parent to try to delete them on its destruction, which will cause a crash at best, silent memory corruption at worst. This can be fixed (by manually deregistering the widgets in your class destructor), but I can't imagine any scenario where such a thing would be useful.
Main reason - possibility of dynamic creating / removing widgets. QObject (and QWidget) desing as classes that could not have copy constructor, so you couldn't pass is in arguments (by value/reference). So using pointers in all cases makes code more simple and clear.

conflicting instantiation - memory leak?

I've been lurking about these questions for awhile and learned alot but recently have come up against a problem that I don't understand. I'm using Qt and need to create/replace a QMovie object in various class methods (which is ultimately set in a QLabel). I've defined the object using the new keyword. Thus in the header I have
QMovie * movie;
For simplicity I'll put the equivalent code in a single method. This is equivalent to the two lines of code
QMovie * movie = new QMovie(QByteArray1,this);
QMovie * movie = new QMovie(QByteArray2,this);
This works (I don't know why) but since it is a repeated operation I worry about memory leaks. It appears that the second definition replaces the first one successfully but since presumably they each have diffeent pointers I don't know how to delete the pointer to the first definition. I delete movie in the class destructor but don't know if it will delete everything. Anyone know what is happening here?
P.S. I do this because the only way (I've found in Qt) to create a QMovie object using data in a QByteArray (which was downloaded from the web) is to use the QMovie constructor. If I just wanted to replace the current movie data with new data from a file I could use the method
movie->setFileName(fileName);
but this isn't an option when using binary data. Note: QMovie also has a constructor that has a filename instead of a QByteArray as an argument. Using filenames also works using the above code and is easier to test.
Any help will be appreciated.
Generally speaking, if anything derived from QObject is contained in a hierarchy of QObjects, they are automatically destructed when the parent is destructed. In your case, you are giving the QMovie a parent through the constructor, so the cleanup should be taken care of for you. If you want to confirm, derive a class from QMovie, implement a destructor that prints a message, and make sure it is called when you expect (i.e. when the parent is destructed).
The idiomatic way of doing it in C would be:
Initialize the pointer to zero.
Before assigning to it, free() the object pointed to by the old pointer. You do not need to check for zero: free() on a zero pointer is a safe no-op.
free() the object when the pointer goes out of scope.
The idiomatic way of doing it in Qt is even simpler.
Use QSharedPointer<> or QScopedPointer<>. It will automatically delete the pointed-to object when it goes out of scope.
If only one pointer is supposed to own the object, use QScopedPointer. It will delete the pointed-to object when it goes out of scope. This is similar to std::auto_ptr.
For shared ownership, use QSharedPointer. It will delete the pointed-to object when the last QSharedPointer that points to it goes out of scope/gets destroyed.
For QScopedPointer, use reset(T*other) method to assign a new value to the pointer. For QSharedPointer, you can only assign other shared pointers to it, like QSharedPointer a = QSharedPointer(new Class);
In either case, any previously pointed-to object will be deleted.
Thus:
class MyClass {
QScopedPointer<QMovie> movie1;
QSharedPointer<QMovie> movie2;
public:
MyClass {} // note: no need for any special initialization
void method() {
movie1.reset(new QMovie(...));
movie2 = QSharedPointer(new QMovie(...));
}
};
This is completely safe. You can call MyClass::method() as often as you wish with no memory leaks. At any point in time, MyClass will keep alive at most two QMovie objects.
QMovie * movie = new QMovie(QByteArray1,this);
QMovie * movie = new QMovie(QByteArray2,this);
If these two lines are in the same .cc file, then you will get a redefinition error. If the two lines are in separate .cc files, then when you build the executable, you will get a multiple definition error. But, your question has this wording:
I'm using Qt and need to create/replace a QMovie object in various class methods (which is ultimately set in a QLabel)
If the QMovie object resides in different classes, you don't have a memory leak, because each class's pointer is different from another's.
However, if your intention is that all the classes refer to the same QMovie instance, you will need to find a way to pass the instance to each object. Alternatively, you would have them all refer to the same one (i.e., using the singleton pattern).

Confusion about usage of 'new' for UI Widgets in QMainWindow constructor

My coding practice using Qt can best be described as follows:
If the Widget is going to be actively used (e.g. A QLineEdit which provides text), I declare it in the header file and then initialise it in MainWindow.cpp.
e.g. TextEditor.h:
class TextEditor
{
//other code
private:
QLineEdit edtFind;
};
2.. If a widget is not going to be used (e.g. QLabel, QWidget), or it's part of a signal slot system (e.g. QPushButton), I declare and inialise it inside constructor using new.
-e.g.
TextEditor::TextEditor()
{
//other code
QWidget* searchPanel = new QWidget();
edtFind = new QLineEdit("Enter Search Term");
QPushButton* findButton = new QPushButton("Find");
connect(findButton,SIGNAL(pressed()),this,SLOT(find()));
ui->statusbar->addPermanentWidget(searchPanel);
}
My question is, am I using an efficient approach in point 2? Would it be better to not allocate memory from the heap?
Thanks.
Your approach is not efficient. You should use heap allocated objects when you actually need them:
objects that have a longer lifetime
using a forward declaration in order to avoid including a header file
holding a reference to an object created elsewhere
Your approach is more complicated without any visible benefit. Heap is known to be slow, and allocating a large number of small objects is known to fragment it (this might not make a difference in your app but it's still a bad practice).
While good advise for C++ in general, answer 1 is actually wrong for a big part in Qt: QObject (and with it all widgets, since QWidget derives from QObject). Rule there is to always allocate QObjects on the heap if they have a parent, because QObject features a parent-based garbage collection (when the topmost QObject-parent gets deleted, it will ask all its children to delete themselves recursively). The application may try to delete an object on the stack, which leads to a crash.
Note that some operations in Qt implicitly add or change the parent of a QObject as a side-effect (reparenting), such as adding a widget to a layout. However, this is usually documented in the API documentation. Since reparenting is very common with QWidgets, you should never put them on the stack. Other QObject-derived classes are safer, consult the API documentation in case of doubt.