Menu
Home
Log in / Register
 
Home arrow Computer Science arrow Learn BlackBerry 10 App Development
< Prev   CONTENTS   Next >

QObject::deleteLater( )

The QObject::deleteLater() method queues up your object for deletion in the Qt event thread. As a general rule of thumb, you should never delete heap-based objects in a slot if it has been passed as a parameter to the slot by the emitting signal (otherwise your application might crash because the object might still be required by other slots, for example). You might, however, face the situation where it is the slot's responsibility to discard the passed object when it is no longer needed. In that case, you can use QObject::deleteLater() to make sure that the object will be eventually deleted once control returns to the event loop (I will not get into the details of the Qt event loop, but if you apply the above-mentioned rule by not deleting heap-based objects in slots, you will always be on the safe side of the fence).

You will see examples of how to use QObject::deleteLater() in the section discussing QThread and you will also have ample opportunity to use the method in Chapter 7 when discarding QNetworkReply objects.

QObject::objectName()

The objectName property identifies an object by name. In practice, you can set a Cascades control's objectName in QML and then retrieve the object from the scene graph in C++ using the

QObject::findChild<T>() method. For example, this is how the C++ code in Chapter 1 updated the TextView in Listing 1-3.

QObject Memory Management

QObjects organize themselves in parent-child relationships. You can always set a QObject's parent either during construction or by explicitly calling the QObject::setParent(QObject* parent). The parent then takes ownership of the QObject and adds it to its list of children. Whenever the parent is deleted, so are its children. This technique works particularly well for GUI objects, which tend to naturally organize themselves as object trees. Here are a few things to keep in mind when using the parent-child memory management technique:

n If you delete a QObject, its destructor will automatically remove itself from its parent's list of children.

n Signal and slots are also disconnected so that a deleted object cannot receive signals previously handled by the object.

n You should never mix memory management techniques when managing an object. For example, you should not manage the same object using parentchild relationships and a smart pointer (both techniques use separate reference counts and will conflict if used with the same object). You can, however, use smart pointers and parent-child relationships in the same application as long as they manage different objects (you can even use a smart pointer as a member variable of a QObject instance).

To further illustrate parent-child memory management, let's extend the Instrument class hierarchy by adding composite instruments. In finance, we usually use aggregates of instruments in order to represent things such as indices, portfolios, and funds. Let's therefore introduce a new type called CompositeInstrument (see Listing 3-14).

Listing 3-14. CompositeInstrument.h

#ifndef COMPOSITEINSTRUMENT_H_

#define COMPOSITEINSTRUMENT_H_

#include "Instrument.h"

class CompositeInstrument : public Instrument {

Q_OBJECT

public:

CompositeInstrument(QObject* parent=0); virtual ~CompositeInstrument();

void addInstrument(Instrument* instrument); bool removeInstrument(Instrument* instrument); const QList<Instrument*>& instruments(); double price() const;

signals:

void instrumentAdded(); void instrumentRemoved();

private:

QList<Instrument*> m_instruments;

};

#endif /* COMPOSITEINSTRUMENT_H_ */

If you are into design patterns, you must have recognized an implementation of the Composite pattern, which lets you manage an aggregation of objects as a single object. Quite interestingly, these aggregate instruments are also called composites in finance. (Note that another good example of a composite class is the Cascades Container. Also in the example given in Listing 3-14, I am supposing that each instrument part of the composite is equally weighted. In practice, you could have different weights attributed to the instruments. For example, the Dow Jones Industrial Average is price weighted.)

Listing 3-15 gives you the CompositeInstrument member function definitions.

Listing 3-15. CompositeInstrument.cpp

#include "CompositeInstrument.h"

#include <iostream> using namespace std;

CompositeInstrument::CompositeInstrument(QObject* parent) : Instrument(parent) {

}

CompositeInstrument::~CompositeInstrument() {

// for illustration purposes only to show that the destructor is called cout << "~CompositeInstrument()" << endl;

}

voidCompositeInstrument::addInstrument(Instrument* instrument){ if(!m_instruments.contains(instrument)){

m_instruments.append(instrument); instrument->setParent(this);

emit instrumentAdded();

}

}

boolCompositeInstrument::removeInstrument(Instrument* instrument){ if(m_instruments.contains(instrument)){

m_instruments.removeOne(instrument); instrument->setParent(0);

emit instrumentRemoved(); return true;

}

return false;

}

const QList<Instrument*>& CompositeInstrument::instruments(){ return m_instruments;

}

double CompositeInstrument::price() const { double totalPrice = 0;

for(int i = 0; i < m_instruments.length(); i++){ totalPrice += m_instruments[i]->price();

}

return totolPrice;

}

The CompositeInstrument class uses a QList<Instrument*> instance in order to keep track of its instruments (a QList<T> is one of Qt's generic container classes; see the “Qt Container Classes” section).

Turning our attention to memory management, when a new Instrument is added to the composite, the composite takes ownership of the instrument using the instrument->setParent(this) method. Similarly, when an instrument is removed from the composite, the composite removes it from its list of children using instrument->setParent(0). In practice, you should always document this kind of behavior so that it is clear to your clients who owns an object at any given time (for example,

the Cascades documentation will always explicitly tell you who owns a control after it is added to or removed from another control).

Finally, Listing 3-16 shows you how to use the CompositeClass in a small test application.

Listing 3-16. main.cpp

int main(){

Stock* stock = new Stock; stock->setSymbol("myStock"); stock->setSpot(50);

Option* option = new Option; option->setSymbol("myOption"); option->setSpot(50);

option->setStrike(55);

option->setTimeToMaturity(0.5); option->setVolatility(.2); option->setRiskfreeRate(.05);

CompositeInstrument* composite = new CompositeInstrument(); composite->addInstrument(stock);

composite->addInstrument(option);

std::cout << "Composite price is: " << composite->price() << std::endl; delete composite;

// more code goes here

}

The application's output is given as follows:

Composite price is: 51.4532

~CompositeInstrument() Stock was deleted Option was deleted

As you can see, the Stock instance and the Option instance are also deleted when the Composite instance is deleted, which illustrates how parent-child relationships work in practice.

Finally, note that parent-child relationships are distinct from the actual class hierarchy. You can set a QObject's parent to any other QObject without having the objects sharing a direct inheritance relationship.

 
Found a mistake? Please highlight the word and press Shift + Enter  
< Prev   CONTENTS   Next >
 
Subjects
Accounting
Business & Finance
Communication
Computer Science
Economics
Education
Engineering
Environment
Geography
Health
History
Language & Literature
Law
Management
Marketing
Philosophy
Political science
Psychology
Religion
Sociology
Travel