Menu
Home
Log in / Register

 
Home arrow Computer Science arrow Learn BlackBerry 10 App Development
< Prev   CONTENTS   Next >

C++ OOP 101

C++ has naturally evolved a great deal over the years and its current incarnation includes all the features required for modern software design. For example, memory management has been greatly simplified with smart pointers, and frameworks such as Qt drastically improve a programmer's productivity. The purpose of this section is to get you up and running with the OOP aspects of C++—namely support for classes, member functions, inheritance and polymorphism—so that you can quickly build Cascades applications without spending a couple of hours on a C++ tutorial.

C++ Class

Just like Java and Objective-C, C++ is a class-based language. A class serves as an abstraction for encapsulating functions and data (or in other words, a class is used to create new types in C++). Instances of the class are the objects that you pass around in your application and act upon by calling their methods. Usually, the class is separated between a header file providing the class definition, which includes the class's public interface, and an implementation file, which provides member function definitions (for example, in Cascades the application delegate definition is given by applicationui.hpp, and its implementation is given by applicationui.cpp). To illustrate C++ classes, let's consider the case of a financial instrument's pricing library. Pricing libraries are usually

used by investment banks on Wall Street in order to price financial products such as options, bonds, and other kinds of derivative instruments (the pricing problem can actually become quite complex and is done by “rocket scientists” called quants). Quite naturally, the very first abstraction provided by a pricing library is the Instrument class, which will be the root abstraction for managing all financial products (see Listing 3-1).

Listing 3-1. Instrument.h

#ifndef INSTRUMENT_H_

#define INSTRUMENT_H_

#include <QObject>

class Instrument : public QObject { Q_OBJECT

Q_PROPERTY(QString symbol READ symbol WRITE setSymbol NOTIFY symbolChanged) Q_PROPERTY(double price READ price NOTIFY priceChanged)

public:

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

QString symbol() const;

void setSymbol(const QString& symbol);

virtual double price() const=0; signals:

void symbolChanged(); void priceChanged();

private:

QString m_symbol;

};

Listing 3-1 is called a class definition. As mentioned previously, a class definition is provided in a header file (ending with an .h or .hpp extension) that declares the class's member functions and variables, as well as their visibility (private, protected, or public). Note that the Instrument class declares a constructor and a destructor. The Instrument(QObject* parent=0) constructor is used to initialize a class instance and the ~Instrument() destructor is where you release resources owned by the object (such as dynamically allocated objects managed by the class instance). (Note that unlike Java, where the garbage collector handles memory management, in C++ you are in charge of memory management, and you must make sure that dynamically allocated resources are released when no longer needed.)

Besides the constructor and destructor, the class's public interface also includes:

n The virtual double Instrument::price()=0 function, which is used to return the instrument's fair price. I will tell you more about this strange looking function in a moment.

n The symbol property, which is defined using the Q_PROPERTY macro. I will tell you more about the macro shortly. For the moment, simply keep in mind that it makes the corresponding property accessible from QML.

n The symbolChanged() signal, which is emitted when the corresponding symbol property is updated.

n The priceChanged() signal, which is emitted when the instrument's price changes.

Finally, the Instrument class inherits from QObject, which is part of the Qt framework (also note the presence of the Q_OBJECT macro, which tells the MOC compiler to generate additional code in order to support the signals and slots mechanism; see Chapter 1).

The Instrument class member function definition is given in a separate file, usually ending with the

.cpp extension (see Listing 3-2).

Listing 3-2. Instrument.cpp

#include "Instrument.h"

Instrument::Instrument(QObject* parent) : QObject(parent), m_symbol(""){

}

Instrument::~Instrument() {

// TODO Auto-generated destructor stub

}

voidInstrument::setSymbol(const QString& symbol){ if(m_symbol == symbol) return;

m_symbol = symbol; emit symbolChanged();

}

QString Instrument::symbol() const{ return m_symbol;

}

We first include the Instrument.h header file and then proceed by defining the member functions. The constructor first calls the QObject(QObject* parent) base class constructor and then initializes the class members using a member initialization list (in this case, there is only one class member, m_symbol, to initialize). As you can see, the file also defines the accessor functions for the m_symbol member variable. Finally, note how the symbolChanged() signal is emitted when m_symbol is updated. As you will see later in this chapter, the signal is used by the QML declarative engine to update properties bound to Instrument's symbol property.

We can now try to use the newly created instrument class by creating a simple test application with a main function, which is the entry point of all C/C++ applications (see Listing 3-3).

Listing 3-3. main.cpp

int main()

{

Instrument instrument;

}

If you try to compile the previous code, the compiler will complain with the following message:

../src/main.cpp:15:16: error: cannot declare variable 'instrument' to be of abstract type 'Instrument'

../src/Instrument.h:13:7: note: because the following virtual functions are pure within 'Instrument':

../src/Instrument.h:21:17: note: virtual double Instrument::price()

The compiler essentially tells you that it cannot instantiate the Instrument class because it contains a pure virtual function. You must be wondering what kind of a beast this is! Well, it is just a fancy way of saying that the method is abstract and that we have not provided an implementation. Also, marking a member function virtual tells the C++ compiler that a child class can override it. This

is very important. By default, methods are statically resolved in C++. If you intend polymorphic behavior, then you need to flag the function as virtual. By appending the =0 to the method declaration, you are telling the compiler that the method is abstract and you are not providing a default implementation. In effect, the class also becomes an abstract base class.

 
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