Archief - Qt en intializer list vs constructor

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

rubenvb

Legacy Member
Hi 9livers,

Ik ben Qt aan het leren uit "THe Book of Qt 4...".

Nu ben ik aan hfdstk 2, en daar wordt een enorm lange constructor gebruikt om verschillende Qdingen te "new"-en. Nu dacht ik altijd dat dit beter in de intializer list staat, maar dan moeten al die ge-"new"-de objecten wel een class member zijn. Concreet komt het dus op dit neer:
Zoals in het boek:

Code:
// header
class QKlasse : public QWidget
{
      Q_OBJECT
public:
      QKlasse();
}
// implementatie van de klasse
QKlasse::QKlasse()
{
      // eerst wordt alles ge-"new"-d
      label = new QLabel();
      button = new QPushButton();
      layout = new QVBoxLayout();

     //hieronder worden dan alle layouts samengesteld en connecties gemaakt
}
Zoals ik het zou doen:

Code:
// header
class QKlasse : public QWidget
{
      Q_OBJECT
public:
      QKlasse();
private:
      QLabel *label;
      QPushButton *button;
      QVBoxLayout *layout;
      // enz.
}
// implementatie van de klasse
QKlasse::QKlasse()
:     label( new QLabel() ),
      button( new QPushButton() ),
      layout( new QVBoxLayout() )
      //enz.
{
     //hier worden dan alle layouts samengesteld en connecties gemaakt
}

Ondanks het zijn van Qt code, kan een mens die in C++ thuis is normaal op mijn vraagje antwoorden: wat is het verschil (behalve dat je klasse groter is in mijn voorbeeld)? Over de destructor hoef je je in Qt geen zorgen te maken, alle ge-"new"-de toestanden worden samen met je klasse mooi uit het geheugen gehaald (vraag mij niet hoe of waar, het is gewoon zo, and I like it :) ).

Merci!

MAXXUR

Legacy Member
Hela hola, wa ge daar als laatste zegt: Wanneer in Qt een object vernietigd wordt, zullen de kindobjecten ook vernietigd worden. Der is echter nerges in uw code waar gij zegt dat bijvoorbeeld uw label een (Qt-)kind is van uw klasse, die wordt dus helemaal niet vernietigd wanneer een instantie van uw klasse vernietigd wordt. Om dat automatisme te bereiken moet ge dus label = new QLabel(this); invoeren, waardoor ge laat weten dat het een kind is vd instantie.

(zie ook de functie header: QLabel::QLabel ( QWidget * parent = 0, Qt::WindowFlags f = 0 ) )

Over da verschil tss init. list en gewoon ben ik niet zeker; ik denk dat er gewoon geen verschil is :) iets met oude vs. nieuwe syntax misschien.

Tyfius

Legacy Member
In de jaren stillekes, toen de megaherz processor nog moest worden uitgevonden was dat iets performanter. Tegenwoordig maakt dat amper nog een zak uit. Da's hetzelfde als i++ of ++i in een for loop schrijven. Een deftige compiler zet dat allemaal om naar dezelfde performante code.

rubenvb

Legacy Member
MAXXUR zei:
Hela hola, wa ge daar als laatste zegt: Wanneer in Qt een object vernietigd wordt, zullen de kindobjecten ook vernietigd worden. Der is echter nerges in uw code waar gij zegt dat bijvoorbeeld uw label een (Qt-)kind is van uw klasse, die wordt dus helemaal niet vernietigd wanneer een instantie van uw klasse vernietigd wordt. Om dat automatisme te bereiken moet ge dus label = new QLabel(this); invoeren, waardoor ge laat weten dat het een kind is vd instantie.

Ik nam eventjes aan dat in de niet vermelde sectie van mijn code er een layout gemaakt wordt waardoor via de layout van de dialog/mainwindow/qwidget dat in de main functie gemaakt wordt alles aan elkaar hangt.

Zoiets dus:

mainwindow->QKlasse->topLayout->subLayout->label

een quote uit het boek dat hetzelfde zegt als hierboven vermeld:
The Book of Qt 4 zei:
Also, this declaration not only creates the QVBoxLayout object but also makes it a child of the QWidget object window, by means of the constructor provided by the QVBoxLayout class. In contrast, when they are created, the two labels initially have no parent object; the QLabel constructor initializes only the label’s text:
Code:
QLabel* label1 = new QLabel("One");
We use the subsequent QVBoxLayout::addWidget() calls to ensure that the QWidget object assumes parentage of each of the new labels. (In fact, the GUI elements contained in a widget must be the children of the overlying widget. For this reason, the QWidget object becomes the parent of the QLabel object, and not theQVBoxLayout object, as might be assumed.) Both the layout object and the two labels, which are subobjects of the window
object, must be generated on the heap using new. On the other hand, we generate the window on the stack using QWidget window;, so that we don’t have to delete it by hand when the application is terminated. (You can do this only with objects that have no parent object.) Therefore, in most cases you should create objects of classes derived from QObject on the heap using new.

Dat zegt mij dus dat het niet uitmaakt waar al die dingen ge-"new"-d worden, ze worden sowieso juist gedeletete indien alles gelayout wordt.
Is er nog een functioneel verschil tussen alle pointers in de klasse definitie steken vs die enkel in de constructor te gebruiken? (behalve natuurlijk als je die binnen of buiten de klasse nog gaat gebruiken)

MAXXUR

Legacy Member
Hou er dus inderdaad rekening mee dat door het "layouten" vb "addWidget" er impliciet een "setParent" gecalled wordt, waardoor uw toegevoegd itemtje zal deleted worden bij het vernietigen van uw parentobject omdat die vanaf dan in de kinderlijst van de parent zit. Pas ook op, dat is niet bij álle layoutelementen zo.

Ik kan er niet aan uit wa ge met da laatste bedoelt? Geef es een vb

rubenvb

Legacy Member
Merci voor het antwoord!

Met dat laatste bedoel ik het verschil tussen (zie mijn twee QKlasses van hierboven) de private members label, button en layout vs de afwezigheid van deze dingen in de andere manier.
Als deze pointers data members van QKlasse zijn, neemt een object meer geheugen in, maar kan ik wel via de member initialization list "sneller" een object aanmaken door alle pointers daar te "new"-en.
Als deze pointers enkel bestaan in de constructor, is een object van die klasse formeel kleiner in het geheugen*, kan ik niet aan die pointers binnen mijn klasse, en kan ik ook niet de member initialization list gebruiken om de GUI componenten aan te maken.
*hoewel ik mijn twijfels heb, aangezien als een object van de klasse wordt aangemaakt, de constructor aangeroepen is en dus alles toch in het geheugen steekt, of niet?

Ik begrijp dat dit echt wel muggezifterij is, maar toch zie ik niet in waarom iemand het eerste codefragment zou gebruiken ipv het tweede (met pointer data members).

MAXXUR

Legacy Member
Goh, hangt ervanaf of ge wel of niet vaak aan uw members wilt kunnen. Zo'n afweging gaat ge op heel veel momenten maken binnen programmatie: meer opslaggeheugen versus tragere toegang (via functies ed.). Stel da ge maar 1 keer aan uwe label komt, dan gaat ge die ni als member opslaan, stel da ge de inhoud van uw label om de 5 botten verandert, hebt ge die liefst wel als membervariabele staan zoda ge die ni telkens moet terug gaan opvragen via de parent.
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan