C++ Multithreading Cookbook

4.8 (4 reviews total)
By Miloš Ljumović
    Advance your knowledge in tech with a Packt subscription

  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Introduction to C++ Concepts and Features

About this book

Creating multithreaded applications is a present-day approach towards programming. With the power of C++, you can easily create various types of applications and perform parallelism and optimizations in your existing work. This book is a practical, powerful, and easy-to-understand guide to C++ multithreading. You will learn how to benefit from the multithreaded approach and enhance your development skills to build better applications. This book will not only help you avoid problems when creating parallel code, but also help you to understand synchronization techniques. The end goal of the book will be to impart various multithreading concepts that will enable you to do parallel computing and concurrent programming quickly and efficiently.

Publication date:
August 2014
Publisher
Packt
Pages
422
ISBN
9781783289790

 

Chapter 1. Introduction to C++ Concepts and Features

In this chapter, we will cover the following topics:

  • Creating a C++ project

  • Program structure, execution flow, and runtime objects

  • The structural programming approach

  • Understanding the object-oriented programming approach

  • Explaining inheritance, overloading, and overriding

  • Understanding polymorphism

  • Event handlers and Message Passing Interface

  • Linked list, queue, and stack examples

 

Introduction


The central concept in all operating systems is the process or abstraction of an executing program. Most modern operating systems can do more than one operation at a time. For example, if the user is typing in a Word document, the computer can print the document, read from the hard disc drive buffer, play music, and so on. In multitasking operating systems, the central processing unit (from now on, CPU) makes a fast switch between programs, executing each program for only a few milliseconds.

While on a single processor system, strictly speaking, only one process can be executed by the processor in one unit of time—the operating system creates an impression that more than one process is running simultaneously by switching them extremely quickly. This is called pseudoparallelism in contrast to hardware-supported native parallelism in multiprocessor systems.

Multithreading is a very important concept for today's modern operating systems. It allows more than one thread of execution, which is very important for parallel tasks as well as for user-friendly application behavior.

In traditional operating systems, every process has its own address space and one thread of execution—often called the primary thread or main thread. Usually, more than one thread in the same address space of a single process is needed, executing in a quasi-parallel context and acting like separated processes, with the exception of a common address space.

Note

Pseudoparallelism is an OS feature executed over a single-processor environment. The quasi-parallel address space concept is a Windows OS feature. When executed over a multiprocessor system, Windows provides every process with a so-called virtual address space, which is much larger than real physical address space, and hence it is a quasi-parallel context.

A very important concept in all operating systems is the thread. A thread object maintains a program counter that takes care of what instruction has to be executed the next time the thread gets the processor time. It also has registers, which save the current values of variables that the thread is manipulating, stack where data related to function calls and parameters are stored, and so on. Even though threads are executed in the context of the process, there is a big difference between processes and threads. The process is greedy, wanting all resources for itself; threads are more "friendly", they cooperate and communicate with each other and share resources such as processor time, memory, and shared variables.

 

Creating a C++ project


All our examples will require Visual Studio IDE. We will now show you how to properly set up an IDE. We'll also point out specific settings that will impact multithreaded applications.

Getting ready

Make sure Visual Studio (VS) is up and running.

How to do it...

Run Visual Studio and select a new project on the Start page. A new window with multiple options will appear. Under Templates on the left side, select C++ and expand the C++ node. You'll see the CLR, General, Test, and Win32 options. Then, perform the following steps:

  1. Select Win32. You'll see two options in the middle row: Win32 console application and Win32 project.

    The Win32 project option is used for applications that have a Graphical User Interface (GUI) other than the console. The console can still be used, but with additional option settings in project properties. For now, we will use the Win32 console application option.

  2. Select Win32 console application and enter a unique name for your project. We will name our first Win32 console application project TestProject. Under Location, select the folder where the project files will be stored. VS will create a folder for you, and it will remember the folder that you have just entered under Location as a default folder when creating future projects.

    Now, you'll see the Win32 application wizard window. You can select Finish directly and VS will create all the necessary files for you, or you can select Next and choose between options where VS creates an empty project. You will have to create the source and header files yourself, unless VS generates all the necessary files for you. For now, select Finish and you are ready to create an application.

  3. In Solution Explorer, you'll see the stdafx.h and targetver.h header files. The stdafx.cpp and Test Project.cpp source files are also created. The stdafx.h and stdafx.cpp files are a part of the precompiled header which is used for an IntelliSense engine that mimics the command-line compiler by using a Translation Unit (TU) model to service IntelliSense requests. A typical translation unit consists of a single source file and the several header files included in that source file. Other headers can be referenced so that they are included too. The IntelliSense engine exists to provide information to the users, such as what a particular type is, what the prototype of a function (and its overloads) is, or what variables are available in the current scope, beginning with a particular substring. More information is available at the MSDN reference (http://msdn.microsoft.com).

  4. The Test Project.cpp file appears in the central window, and this is where you'll write your code. Later, we will create and use more files in more complex projects, but this should do for now.

How it works...

Every program must have its main routine, which is called main. When you want to run your program, the operating system starts it by calling main. This is the starting point of execution for all C++ programs. If you write code that adheres to the Unicode programming model, you can use the wide-character version of main called wmain. You can also use _tmain, which is defined in TCHAR.h. The _tmain function will resolve to main, unless _UNICODE is defined, in which case _tmain will resolve to wmain.

Above the Test Project window, you'll see various options; among them is a combobox with the Win32 option selected, which is called Solution platform. If you want to create a 32-bit executable, leave it as is. For 64-bit executables, expand the combobox, select Configuration manager, and select New under Active solution platforms. A new x64 option will appear. Click on OK, and close the Configuration manager window.

One of the most important settings that you need to change when building 64-bit executables is under Project properties. Press Alt + F7, or select Project properties in Solution explorer after right-clicking on the TestProject project. The Test Project Property Pages window will appear. Expand Configuration Properties and C/C++, and select Preprocessor. Under Preprocessor definitions, you'll see certain values copied from the Win32 settings. You'll need to change WIN32 to _WIN64 in order to build a 64-bit executable. Leave the rest as is.

Whether you build 32-bit or 64-bit code, there is one more thing that you need to set properly, which is code generation. When creating C++ projects, you can select whether your application will depend on Dynamic Link Libraries (DLL) required for C++ runtime on the user PC. If you create an application that runs on a PC other than the PC where it is created, you'll need to think about this. On the PC where you use VS, the required C++ runtime is already installed, so this does not matter. However, on another PC, where, for example, C++ runtime isn't installed, this might cause issues. If you want to be sure that no dependency is required, you'll need to change the Runtime Library option to Multi-threaded Debug (/MTd) for the Debug mode, or change it to Multi-threaded (/MT) for the Release mode. The Debug or Release mode can be switched in the Solution Configurations combobox.

For our examples, you can leave everything as it is because 32-bit executables can be run on both 32-bit and 64-bit machines. The runtime library can also be left as default because the application will run fine on the PC where it is built as the required C++ Redistributable Package framework is already installed.

 

Program structure, execution flow, and runtime objects


A programming paradigm is a fundamental style of computer programming. There are four main paradigms: imperative, declarative, functional (or structural), and object-oriented. The C++ language is certainly the most popular object-oriented language today. It is a very powerful, flexible, and comfortable programming language. Programmers adopted it very gladly and quickly, just like its predecessor, C. The key to such success lies in the fact that it was made by a single programmer, adjusting it to his needs.

Unfortunately, C++ isn't an easy language at all. Sometimes, you can think that it is a limitless language that cannot be learned and understood entirely, but you don't need to worry about that. It is not important to know everything; it is important to use the parts that are required in specific situations correctly. Practice is the best teacher, so it's better to understand how to use as many of the features as needed.

In examples to come, we will use author Charles Simonyi's Hungarian notation. In his PhD in 1977, he used Meta-Programming – A software production method to make a standard for notation in programming, which says that the first letter of type or variable should represent the data type. For the example class that we want to call, a Test data type should be CTest, where the first letter says that Test is a class. This is good practice because a programmer who is not familiar with the Test data type will immediately know that Test is a class. The same standard stands for primitive types, such as int or double. For example, iCount stands for an integer variable Count, while dValue stands for a double variable Value. Using the given prefixes, it is easy to read code even if you are not so familiar with it.

Getting ready

Make sure Visual Studio is up and running.

How to do it...

Now, let's create our first program by performing the following steps and explaining its structure:

  1. Create a new C++ console application named TestDemo.

  2. Open TestDemo.cpp.

  3. Add the following code:

    #include "stdafx.h"
    #include <iostream>
    
    using namespace std;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
       cout << "Hello world" << endl;
       return 0;
    }

How it works...

The structure of the C++ program varies due to different programming techniques. What most programs must have is the #include or preprocessor directives.

The #include <iostream> header tells the compiler to include the iostream.h header file where the available function prototypes reside. It also means that libraries with the functions' implementations should be built into executables. So, if we want to use some API or function, we need to include an appropriate header file, and maybe we will have to add an additional input library that contains the function/API implementation. One more important difference when including files is <header> versus "header". The first (<>) targets solution-configured project paths, while the other ("") targets folders relative to the C++ project.

The using command instructs the compiler to use the std namespace. Namespaces are packages with object declarations and function implementations. Namespaces have a very important usage. They are used to minimize ambiguity while including third-party libraries when the same function name is used in two different packages.

We need to implement a program entry point—the main function. As we said before, we can use main for an ANSI signature, wmain for a Unicode signature, or _tmain where the compiler will resolve its signature depending on the preprocessor definitions in the project property pages. For a console application, the main function can have the following four different prototypes:

  • int _tmain(int argc, TCHAR* argv[])

  • void _tmain(int argc, TCHAR* argv[])

  • int _tmain(void)

  • void _tmain(void)

The first prototype has two arguments, argc and argv. The first argument, argc, or the argument count, says how many arguments are present in the second argument, argv, or the argument values. The argv parameter is an array of strings, where each string represents one command-line argument. The first string in argv is always the current program name. The second prototype is the same as the first one, except the return type. This means that the main function may or may not return a value. This value is returned to the OS. The third prototype has no arguments and returns an integer value, while the fourth prototype neither has arguments nor returns a value. It is good practice to use the first format.

The next command uses the cout object. The cout object is the name of the standard output stream in C++, and the meaning of the entire statement is to insert a sequence of characters (in this case, the Hello world sequence of characters) into the standard output stream (usually corresponds to the screen).

The cout object is declared in the iostream standard file within the std namespace. This is why we need to include the specific file and declare that we will use this specific namespace earlier in our code.

In our usual selection of the (int _tmain(int,_TCHAR**)) prototype, _tmain returns an integer. We must specify some int value after the return command, in this case 0. When returning a value to the operating system, 0 usually means success, but this is operating system dependent.

This simple program is very easy to create. We use this simple example to demonstrate the basic program structure and usage of the main routine as the entry point for every C++ program.

Programs with one thread are executed sequentially line-by-line. This is why our program is not user friendly if we place all code into one thread.

After the user gives the input, control is returned to the application. Only now can the application continue the execution. In order to overcome such an issue, we can create concurrent threads that will handle the user input. In this way, the application does not stall and is responsive all the time. After a thread handles its task, it can signal that a user has performed the requested operation to the application.

There's more...

Every time we have an operation that needs to be executed separately from the main execution flow, we have to think about a separate thread. The simplest example is when we have some calculations, and we want to have a progress bar where the calculation progress will be shown. If the same thread was responsible for calculation as well as to update the progress bar, probably it wouldn't work. This occurs because, if both work and a UI update are performed from a single thread, such threads can't interact with OS painting adequately; so almost always, the UI thread is separate from the working threads.

Let's review the following example. Assume that we have created a function where we will calculate something, for example, sines or cosines of some angle, and we want to display progress in every step of the calculation:

void CalculateSomething(int iCount)
{
    int iCounter = 0;
    while (iCounter++ < iCount)
    {
       //make calculation
       //update progress bar
    }
}

As commands are executed one after another inside each iteration of the while loop, the operating system doesn't have the required time to properly update the user interface (in this case, the progress bar), so we would see an empty progress bar. After the function returns, a fully filled progress bar appears. The solution for this is to create a progress bar on the main thread. A separate thread should execute the CalculateSomething function; in each step of iteration, it should somehow signal the main thread to update the progress bar step by step. As we said before, threads are switched extremely fast on the CPU, so we can get the impression that the progress bar is updated at the same time at the calculation is performed.

To conclude, each time we have to make a parallel task, wait for some kind of user input, or wait for an external dependency such as some response from a remote server, we will create a separate thread so that our program won't hang and be unresponsive.

In our future examples, we will discuss static and dynamic libraries, so let's say a few words about both. A static library (*.lib) is usually some code placed in separate files and already compiled for future use. We will add it to the project when we want to use some of its features. When we wrote #include <iostream> earlier, we instructed the compiler to include a static library where implementations of input-output stream functions reside. A static library is built into the executable in compile time before we actually run the program. A dynamic library (*.dll) is similar to a static library, but the difference is that it is not resolved during compilation; it is linked later when we start the program, in another words—at runtime. Dynamic libraries are very useful when we have functions that a lot of programs will use. So, we don't need to include these functions into every program; we will simply link every program at runtime with one dynamic library. A good example is User32.dll, where the Windows OS placed a majority of GUI functions. So, if we create two programs where both have a window (GUI form), we do not need to include CreateWindow in both programs. We will simply link User32.dll at runtime, and the CreateWindow API will be available.

 

The structural programming approach


As we said before, there are four programming paradigms. Both structural and object-oriented paradigms can be used when making programs in C++. Even though C++ is an object-oriented language, you can make programs with a structural approach. Usually, a program contains one or more functions because every program must have a main routine; so, we can place all our code into the main function. However, in that way, any large program will be very hard to read. Then, we will have to split the code in certain program units that we call functions. Let's give an example of a program that needs to calculate the sum of two complex numbers in the following sections.

Getting ready

Make sure Visual Studio is up and running.

How to do it...

Perform the following steps:

  1. Create a new default console application. Name it ComplexTest.

  2. Open the ComplexTest.cpp file and insert the following code:

    #include "stdafx.h"
    #include <iostream>
    
    using namespace std;
    
    void ComplexAdd( double dReal1, double dImg1, double dReal2, double dImg2, double& dReal, double& dImg )
    {
      dReal = dReal1 + dReal2;
      dImg = dImg1 + dImg2;
    }
    
    double Rand(double dMin, double dMax)
    {
      double dVal = (double)rand() / RAND_MAX;
      return dMin + dVal * (dMax - dMin);
    }
    
    int _tmain(int argc, TCHAR* argv[])
    {
        double dReal1 = Rand( -10, 10 );
        double dImg1 = Rand( -10, 10 );
        double dReal2 = Rand( -10, 10 );
        double dImg2 = Rand( -10, 10 );
        double dReal = 0;
        double dImg = 0;
        ComplexAdd(dReal1, dImg1, dReal2, dImg2, dReal, dImg);
        cout << dReal<< "+" <<dImg << "i" << endl;
        return 0;
    }

How it works...

We created the ComplexAdd function that has six parameters or three complex numbers. The first two parameters are the real and imaginary parts of the first complex number, parameters three and four are the real and imaginary parts of the second complex number, and the fifth and sixth parameters are the real and imaginary parts of the complex number that will represent the result or the sum of the first two complex numbers. Note that the fifth and sixth parameters are passed by reference. We also created a Rand function that will return a random real number from a range between dMin and dMax.

As you can see, we have achieved what we wanted; however, you'll agree that the given code is not very readable and the ComplexAdd function has many parameters. Also, we have six variables in the main function, so the conclusion is that this kind of approach is not very "friendly". Let's review a slightly different approach by using structures, as shown:

#include "stdafx.h"
#include <iostream>

using namespace std;

struct SComplex
{
    double dReal;
    double dImg;
};

SComplex ComplexAdd(SComplex c1, SComplex c2)
{
    SComplex c;
    c.dReal = c1.dReal + c2.dReal;
    c.dImg = c1.dImg + c2.dImg;
    return c;
}

double Rand(double dMin, double dMax)
{
    double dVal = (double)rand() / RAND_MAX;
    return dMin + dVal * (dMax - dMin);
}
int _tmain(int argc, TCHAR* argv[])
{
    SComplex c1;
    c1.dReal = Rand( -10, 10 );
    c1.dImg = Rand( -10, 10 );

    SComplex c2;
    c2.dReal = Rand( -10, 10 );
    c2.dImg = Rand( -10, 10 );

    SComplex c = ComplexAdd( c1, c2 );

    cout<<c.dReal<< "+" <<c.dImg << "i" << endl;
    return 0;
}

There's more…

As you can see, by creating a new type (in this case, structure), SComplex, which represents complex numbers, our code is more readable and more meaningful than the one shown in the previous example. The conclusion is that if we can somehow create objects that can represent an abstraction of tasks that we need to perform, our code, and the program itself, will make much more sense, and it will be easier for us to write and understand the code.

 

Understanding the object-oriented programming approach


Object-oriented programming (OOP) is a new approach to create software as a model for the real world. This is a particular way of designing a program. OOP includes several key concepts, such as classes, objects, inheritance, and polymorphism.

Getting ready

Make sure Visual Studio is up and running.

How to do it...

Let's review the previous example with the OOP approach by performing the following steps:

  1. Create a new console application. Name it ComplexTestOO.

  2. Open the ComplexTestOO.cpp file and insert the following code:

    #include "stdafx.h"
    #include <iostream>
    
    using namespace std;
    
    double Rand(double dMin, double dMax)
    {
       double dVal = (double)rand() / RAND_MAX;
       return dMin + dVal * (dMax - dMin);
    }
    
    class CComplex
    {
    public:
       CComplex( )
       {
          dReal = Rand( -10, 10 );
          dImg = Rand( -10, 10 );
       }
       CComplex(double dReal, double dImg)
       {
          this->dReal = dReal;
          this->dImg = dImg;
       }
       friend CComplex operator+ (const CComplex& c1, const CComplex& c2);
       friend ostream& operator<< (ostream& os, const CComplex& c);
    private:
       double dReal;
       double dImg;
    };
    
    CComplex operator+ (const CComplex& c1, const CComplex& c2)
    {
       CComplex c(c1.dReal + c2.dReal, c1.dImg + c2.dImg);
       return c;
    }
    ostream& operator<< ( ostream& os, const CComplex& c )
    {
       return os<<c.dReal<< "+" <<c.dImg << "i";
    }
    
    int _tmain(int argc, TCHAR* argv[])
    {
       CComplex c1;
       CComplex c2(-2.3, 0.9);
       CComplex c = c1 + c2;
       cout << c << endl;
    
       return 0;
    }

How it works...

If you look at the main function, you'll notice that it doesn't differ from the program where you use integers, for example. Even though an integer is a primitive type and a complex is not, a programmer's work is made easier by adding a class and properly setting its methods.

Here we have defined a new type of class—CComplex. The defined class has its own attributes and methods. It can also have friend methods that can access its private members. We have left the Rand function as it is, but we tried to make the class that represents a complex number as similar to the abstraction of a complex number as possible. We created the dReal and dImg attributes that describe the real and imaginary parts of a complex number. We created the operator+ method so that the + (plus) sign has meaning for the compiler. Now, the code is more readable and much more comfortable to use because it is easy to understand how to use it. We created two constructors: the default constructor that uses random real numbers from -10 to 10, and another constructor that enables the user to set the real and imaginary parts of a complex number directly.

When you want to overload (this will be explained later in detail) a certain method, you can choose between two approaches. The first approach is to set the method inside a class, and this method will change the state (or values) of the calling object. The second approach is to make the method independent of the class, the so-called outer, but it has to be declared as friend so that it can access the private and protected members of the objects.

There's more...

The following code tells the compiler that the operator+ function which expects two complex numbers will be defined somewhere in the code, and it has to be able to access the private and protected members of the CComplex class:

friend CComplex operator+ (const CComplex& c1, const
CComplex& c2);

This makes the main function the simplest possible. Again, we use user-defined types such as primitive types, which is very good practice because even programmers not so familiar with the code will quickly understand what the code means.

 

Explaining inheritance, overloading, and overriding


Inheritance is a very important characteristic of OOP. It is the relation between two (or more) classes: if class B is some kind of class A, then the objects of class B have the same properties as the objects of class A. In addition to that, class B can implement new methods and properties, and thus supersede the base class A.

Getting ready

Make sure Visual Studio is up and running.

How to do it...

Let's review this example by performing the following steps:

  1. Create a new default console application. Name it InheritanceTest.

  2. Open the InheritanceTest.cpp file and insert the following code:

    #include "stdafx.h"
    #include <iostream>
    
    using namespace std;
    
    class CPerson
    {
    public:
      CPerson(int iAge, char* sName)
      {
        this->iAge = iAge;
        strcpy_s(this->sName, 32, sName);
      }
      virtual char* WhoAmI()
      {
        return "I am a person";
      }
    private:
      int iAge;
      char sName[32];
    };
    
    class CWorker : public CPerson
    {
    public:
      CWorker(int iAge, char* sName, char* sEmploymentStatus)
        : CPerson(iAge, sName)
      {
        strcpy_s(this->sEmploymentStatus, 32, sEmploymentStatus);
      }
      virtual char* WhoAmI()
      {
        return "I am a worker";
      }
    private:
      char sEmploymentStatus[32];
    };
    
    class CStudent : public CPerson
    {
    public:
      CStudent(int iAge, char* sName, char* sStudentIdentityCard)
        : CPerson(iAge, sName)
      {
        strcpy_s(this->sStudentIdentityCard, 32, sStudentIdentityCard);
      }
      virtual char* WhoAmI()
      {
        return "I am a student";
      }
    private:
      char sStudentIdentityCard[32];
    };
    
    int _tmain(int argc, TCHAR* argv[])
    {
      CPerson cPerson(10, "John");
      cout << cPerson.WhoAmI() << endl;
    
      CWorker cWorker(35, "Mary", "On wacation");
      cout << cWorker.WhoAmI() << endl;
    
      CStudent cStudent(22, "Sandra", "Phisician");
      cout << cStudent.WhoAmI() << endl;
    
      return 0;
    }

How it works...

We created a new CPerson data type that represents one human. It has iAge and sName as attributes that describe some person. Let's assume that we need some worker or student as another data type. OOP provides a great mechanism, inheritance, which can be used to achieve this. As a worker is still a person, but with some additional attributes, we will extend CPerson with CWorker using the following line of code:

class CWorker : public CPerson

So, CWorker is a derived class of CPerson. It has all the attributes and methods from the base class, CPerson, and an additional sEmploymentStatus attribute that is important to a worker only. Further, let's say we need a Student data type. Since a student is a person who has some additional attributes besides age and name, we will extend a person again by using the following line of code:

class CStudent : public CPerson

What is important for us to know is that when you declare an object, its constructor is being called. When you declare an object of a derived class, the constructor from the base class is called first, and the constructor from the derived class is called later. The following is the code sample:

CWorker( int iAge, char* sName, char* sEmploymentStatus )
: CPerson( iAge, sName )
{
   strcpy_s( this->sEmploymentStatus, 32, sEmploymentStatus );
}

Take a look at the CWorker constructor prototype; after the parameter list, you'll notice a : (colon) sign after which the base class constructor is called, as shown in the following code, with the needed parameters iAge and sName, for CPerson to be created:

CPerson(iAge, sName)

The situation with destructors is the opposite. The destructor from the derived class is called before, from the base class.

Graphically, the CPerson, CWorker, and CStudent objects look like the following diagrams, respectively:

The meaning of the operators can be defined even for user-defined types, such as CComplex in the previous example. It is very handy, as you saw, because it is more meaningful to write c = c1 + c2, where c, c1, and c2 are complex numbers, than to write c = ComplexAdd( c1, c2 ).

The user must implement the operator functions or overload them in order for the compiler to know how to deal with user-specific types. The compiler knows what to do with primitive types, such as adding two integers, but imagine two matrices m1 and m2 and the expression matrix m = m1 + m2. Well, if we do not define the CMatrix operator + (const CMatrix& m1, const CMatrix& m2) function, the compiler won't know what to do because it doesn't know how to add matrices.

Overriding a method is a feature that allows a derived class to provide a specific implementation of a method that is already provided in the base class. Take a look at the WhoAmI method from the previous example. Its output will be as follows:

I am a person
I am a worker
I am a student

Even though a method from each class has the same name, it is a different method and has a different functionality. We can say that the WhoAmI method is overridden in the CPerson derived class.

There's more...

Overriding is an excellent feature in OOP and C++, but polymorphism is even better. Let's review the following example.

 

Understanding polymorphism


Polymorphism is a feature where an object executes an operation in the way that it is implemented in the derived class that it belongs to, even if we access it through a pointer or a reference of the base class. Polymorphism is a feature that allows an object to take many forms.

Getting ready

Make sure Visual Studio is up and running.

How to do it...

Perform the following steps:

  1. Create a new default console application. Name it PolymorphismTest.

  2. Open the PolymorphismTest.cpp file and insert the following code:

    #include "stdafx.h"
    #include <iostream>
    
    #define M_PI 3.14159265358979323846
    
    using namespace std;
    
    class CFigure
    {
    public:
      virtual char* FigureType() = 0;
      virtual double Circumference() = 0;
      virtual double Area() = 0;
      virtual ~CFigure(){ }
    };
    
    class CTriangle : public CFigure
    {
    public:
      CTriangle()
      {
        a = b = c = 0;
      }
      CTriangle(double a, double b, double c) : a(a), b(b), c(c){ }
      virtual char* FigureType()
      {
        return "Triangle";
      }
      virtual double Circumference()
      {
        return a + b + c;
      }
      virtual double Area()
      {
        double S = Circumference() / 2;
        return sqrt(S * (S - a) * (S - b) * (S - c));
      }
    private:
      double a, b, c;
    };
    class CSquare : public CFigure
    {
    public:
      CSquare()
      {
        a = b = 0;
      }
      CSquare(double a, double b) : a(a), b(b) { }
      virtual char* FigureType()
    
      {
        return "Square";
      }
      virtual double Circumference()
      {
        return 2 * a + 2 * b;
      }
      virtual double Area()
      {
        return a * b;
      }
    private:
      double a, b;
    };
    
    class CCircle : public CFigure
    {
    public:
      CCircle()
      {
        r = 0;
      }
      CCircle(double r) : r(r) { }
      virtual char* FigureType()
      {
        return "Circle";
      }
      virtual double Circumference()
      {
        return 2 * r * M_PI;
      }
      virtual double Area()
      {
        return r * r * M_PI;
      }
    private:
      double r;
    };
    
    int _tmain(int argc, _TCHAR* argv[])
    {
      CFigure* figures[3];
    
      figures[0] = new CTriangle(2.1, 3.2, 4.3);
  
      figures[1] = new CSquare(5.4, 6.5);
      figures[2] = new CCircle(8.8);
    
      for (int i = 0; i < 3; i++)
      {
        cout << "Figure type:\t" << figures[i]->FigureType()
          << "\nCircumference:\t" <<
          figures[i]->Circumference()
          << "\nArea:\t\t" << figures[i]->Area()
          << endl << endl;
      }
    
      return 0;
    }

How it works...

First, we created a new type, CFigure. We would like to create some real figures, such as triangles, squares, or circles, and methods that will calculate their circumference and area. You'll agree that we can't calculate these features for the figure itself because we don't know what type of real figure it is. This is why we created CFigure as an abstract class. An abstract class is a class where at least one of its virtual methods is declared with no implementation and has = 0 after its prototype. Functions declared in such a manner are called pure virtual functions. An abstract class can't have objects, but inherited classes can. You can instantiate pointers and references of abstract classes. We extend the CTriangle, CSquare, and CCircle classes that represent triangles, squares, and circles, respectively. In these derived classes, we implement the FigureType, Circumference, and Area methods because we want to have the ability to instantiate such types of objects.

Each of these three classes has the same method names but different implementations, similar to overriding but different in meaning. How? Well, if you look at the main function, you'll notice that we declared an array of three pointers of the CFigure type. As a pointer or reference to a base class can always point to any of its derived classes, it is possible to create an object of type CTriangle and set the CFigure pointer to point at it, using the following code:

figures[ 0 ] = new CTriangle( 2.1, 3.2, 4.3 );

In the same way, we set other figures using the following code:

figures[ 1 ] = new CSquare( 5.4, 6.5 );
figures[ 2 ] = new CCircle( 8.8 );

Now, refer to the following code:

for ( int i = 0; i < 3; i++ )
{
   cout << "Figure type:\t" << figures[ i ]->FigureType( ) << "\nCircumference:\t" << figures[ i ]->Circumference( ) << "\nArea:\t\t" << figures[ i ]->Area( ) << endl<<endl;
}

The compiler will use a C++ feature called dynamic binding to resolve the type of object to which the figure points. It'll then call an appropriate virtual method. Dynamic binding is possible only if the method is declared virtually and if you access it via a pointer or reference.

Let's go back to the example with persons. We had to declare objects of type CPerson, CWorker, and CStudent. All three are of different types, and you can call the WhoAmI method, for example, by using the following code:

cPerson.WhoAmI( )

The compiler knows that you are referring to the cPerson object, which is of a CPerson type, and its method is WhoAmI. On the other hand, in the example with figures, the compiler doesn't know what type of object the figure pointer will point to during compilation. This will be resolved during the runtime. This is why it is called dynamic binding.

 

Event handlers and Message Passing Interface


Many programs respond to some events, such as when a user presses a button or inputs some text. A very important mechanism is event handling or the ability of a program to react to user action. If we want to handle when a user presses a button, we need to create some kind of a listener that will listen to button events, in this case a press action.

An event handler is a function that the operating system calls each time the control sends some kind of message, such as I have been pressed in the case of buttons or I received a character in the case of a textbox.

Event handlers are very important. Timers are events that trigger after a certain portion of time has elapsed. When you press a key on the keyboard, the operating system raises a "key is pressed" event, and so on.

Event handlers for windows are very important for us. The majority of applications have windows or forms. Every window needs its event handler, which will be called each time some event occurs in its space. For example, if you create a window with a few buttons and textboxes, you must have a window procedure associated with that window in order to handle such events.

The Windows operating system provides such a mechanism in the form of a window procedure, usually called WndProc (but you can name it as you like). This procedure is called by the operating system each time some event specific to that window occurs. In the following example, we will create our first Windows application, where we will have a window and explain the usage of a window procedure.

Getting ready

Make sure Visual Studio is up and running.

How to do it...

Perform the following steps:

  1. Create a new empty Win32 C++ project. Name it GUIProject, and then click on OK. Now, right-click on the source files and navigate to Add | New item in Solution Explorer. Name it main, and then click on Add.

  2. Now, let's create the code. First, we will add a header that we need, as shown:

    #include <windows.h>

The windows.h header is needed for the majority of APIs that are responsible for visual features such as windows, controls, enumerations, and styles. Before we create an application entry point, we have to declare a window procedure prototype so that we can use it in the window structure, as shown in the following code:

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
lParam);

We will implement WndProc later but for now the declaration is enough. Now, we need an application entry point. Unlike a console application, the main function in Win32 applications has a slightly different prototype, as shown in the following code:

int WINAPI WinMain(HINSTANCE hThis, HINSTANCE hPrev, LPSTR szCmdLine, int iCmdShow)

After the return type (int), you will notice the WINAPI macro. It represents a calling convention.

WINAPI or stdcall means that a call stack will clean the callee. WinMain is the name and it must have four parameters in a given order. The first parameter, hThis, is a handle to the current instance of the application. The second parameter, hPrev, is a handle to the previous instance of the application. If you refer to the MSDN documentation (http://msdn. microsoft.com/en-us/library/windows/desktop/ms633559%28v=vs.85%29.aspx), you'll notice that the hPrev parameter is always NULL, so I guess that this has been left for compatibility with previous versions of Windows operating systems, as it can't have values in current versions. The third parameter is szCmdLine or the command line for the application, excluding the program name. The final parameter controls how the window is to be shown.

It can have one or more values combining bit values with the OR (|) operator (more information available on MSDN).

We will then use the UNREFERENCED_PARAMETER macro to tell the compiler that we will not use certain parameters so that it can do some additional optimization. Use the following code:

UNREFERENCED_PARAMETER( hPrev );
UNREFERENCED_PARAMETER( szCmdLine );

Next, we need to instantiate the WNDCLASSEX window structure. This is an object where details of future windows, such as stack size, handle to current application instance, window style, window color, icon, and mouse pointer, will be stored. The code to instantiate the WNDCLASSEX window structure is as follows:

WNDCLASSEX wndEx = { 0 };

The number of extra bytes to allocate after instantiating the window class structure can be defined by using the following code:

wndEx.cbClsExtra = 0;

The size, in bytes, of this structure can be defined by using the following code:

wndEx.cbSize = sizeof( wndEx );

The number of extra bytes to allocate after instantiating the window instance can be defined by using the following code:

wndEx.cbWndExtra = 0;

A handle to the class background brush can be defined by using the following code:

wndEx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);

A handle to the class cursor can be defined by using the following code:

wndEx.hCursor = LoadCursor( NULL, IDC_ARROW );

Handles to the class icon can be defined by using the following code:

wndEx.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wndEx.hIconSm = LoadIcon( NULL, IDI_APPLICATION );

A handle to the instance that contains the window procedure for the class can be defined by using the following code:

wndEx.hInstance = hThis;

A pointer to the window procedure can be defined by using the following code:

wndEx.lpfnWndProc = WndProc;

A pointer to a null-terminated string or an atom can be defined by using the following code:

wndEx.lpszClassName = TEXT("GUIProject");

A pointer to a null-terminated character string that specifies the resource name of the class menu, as the name appears in the resource file, can be defined using the following code:

wndEx.lpszMenuName = NULL;

The class style(s) can be defined using the following code:

wndEx.style = CS_HREDRAW | CS_VREDRAW;

The following code registers a window class for subsequent use in calls to the CreateWindow or CreateWindowEx function:

if ( !RegisterClassEx( &wndEx ) )
{
  return -1;
}

The CreateWindow API creates an overlapped, pop-up, or child window. It specifies the window class, window title, window style, and (optionally) the initial position and size of the window. The function also specifies the window's parent or owner, if any, and the window's menu, as shown in the following code:

HWND hWnd = CreateWindow( wndEx.lpszClassName, TEXT("GUI Project"), WS_OVERLAPPEDWINDOW, 200, 200, 400, 300, HWND_DESKTOP,NULL, hThis, 0 );

if ( !hWnd )
{
   return -1;
}

The UpdateWindow function updates the client area of the specified window by sending a WM_PAINT message to the window if the window's update region is not empty. The function sends a WM_PAINT message directly to the window procedure of the specified window bypassing the application queue. The usage is shown in the following code:

UpdateWindow( hWnd );

The following code sets the specified window's show state:

ShowWindow( hWnd, iCmdShow );

Now, we need the instance of the MSG structure that represents the window message.

MSG msg = { 0 };

Here, we enter the message loop. Windows-based applications are event driven. They do not make explicit function calls (such as C runtime library calls) to obtain input. Instead, they wait for the system to pass input to them. The system passes all input for an application to the various windows in the application. Each window has a function, called a window procedure, which the system calls whenever it has input for the window. The window procedure processes the input and returns control to the system. The GetMessage API retrieves a message from the calling thread's message queue, as shown in the following code:

while ( GetMessage( &msg, NULL, NULL, NULL ) )
{
   // Translates virtual-key messages into character messages.
   TranslateMessage(&msg );
   // Dispatches a message to a window procedure.
   DispatchMessage(&msg );
}

When we close the application or send some command that signals it to exit, the system releases an application message queue. This means that our application will have no more messages, and it will end the while loop. The DestroyWindow API destroys the specified window. The function sends the WM_DESTROY and WM_NCDESTROY messages to the window to deactivate it and removes the keyboard focus from it. The function also destroys the window's menu, flushes the thread message queue, destroys timers, removes clipboard ownership, and breaks the clipboard viewer chain (if the window is at the top of the viewer chain).

DestroyWindow( hWnd );

The function also unregisters a window class, freeing the memory required for the class.

UnregisterClass( wndEx.lpszClassName, hThis );

The function returns a success exit code or a last message code from the application message queue, as shown in the following code:

return (int) msg.wParam;

Now, we need to implement a window procedure or an application main event handler. For our first example, we will create a simple WndProc with only the functionality of handling mandatory events. The window procedure returns 64-bit long signed integer values. It has four parameters: the hWnd structure that represents the window identifier, the uMsg unsigned integer that represents a window message code, the wParam unsigned 64-bit long integer to pass application-defined data, and the lParam signed 64-bit long integer to pass application-defined data too.

LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{

Messages are handled by their message code. For example, we need to handle default messages (in this case, WM_CLOSE), which the system sends when the application is closing. Then, we will call the PostQuitMessage API to free system resources and to safely close the application, using the following code:

switch ( uMsg )
{
   case WM_CLOSE:
   {
       PostQuitMessage( 0 );
       break;
   }

   default:
   {

Call the default window procedure to provide default processing for any window message that an application does not process. This function ensures that every message is processed. The default window procedure can be used in the following manner:

           return DefWindowProc(hWnd, uMsg, wParam, lParam);
        }
    }
    return 0;
}

Though this was a very simple example of a window application, it completely reflects the event-driven system features and the event-handling mechanism. In chapters to come, we will use event handling all the time, so it is very important for you to understand the basic process.

 

Linked list, queue, and stack examples


The following example demonstrates the OOP usage of a linear linked list that can contain any generic type T. The idea behind this example is to show inheritance usage as a model for the relation that "B is a kind of A".

A linear list is a structure of linearly arranged elements in which we know that the first element links to the second, the second element links to the third, and so on. Basic operations with a linked list are insert element (PUT) and obtain element (GET). A queue is a linear list where the elements are arranged in order so that what enters a queue first gets out first, in other words, FIFO—First In First Out. Therefore, when you get an element, it is obtained from the top of the list, and you put a new element at the bottom of the list. A stack is a linear list where elements are arranged such that they are obtained in the reverse order of how they were inserted. The element is placed at the top of the list, and it is obtained from the top of the list, or LIFO—Last In First Out.

A linear list is an arranged collection of elements. Each list has methods that can set element value, obtain an element from the list, or simply peek an element. A list can be used to store any type of objects. Yet, for specializations of list class, queue, and stack, it is defined exactly where elements must be inserted or obtained from. So, a list as a general object will be a base class.

You should be aware that a list designed in such a manner can be implemented as a static or dynamic structure. In other words, it can be implemented as an array of elements or as a structure of elements linked by pointers to the next (or previous or both) element. Implementation using pointers is mostly used in practice and will be shown here.

The list, in the following example, will be implemented as a collection of pointers that point to the original objects that are placed in the list using its methods. So, the original objects won't be copied to the list, which enables polymorphism for list elements. Semantics, as such, requires additional attention and careful design.

Getting ready

Make sure Visual Studio is up and running.

How to do it...

Perform the following steps:

  1. Create a new empty C++ console application project. Name it LinkedList.

  2. Add a new header file named CList.h. Copy and paste the following code into it:

    #ifndef _LIST_
    #define _LIST_
    
    #include <Windows.h>
    
    template <class T>
    class CNode
    {
    public:
      CNode(T* tElement) : tElement(tElement), next(0) { }
      T* Element() const { return tElement; }
      CNode*& Next(){ return next; }
    private:
      T* tElement;
      CNode* next;
    };
    
    template <class T>
    class CList
    {
    public:
      CList() : dwCount(0), head(0){ }
      CList(T* tElement) : dwCount(1), head(new CNode<T>(tElement)){ }
      virtual ~CList(){ }
      void Append(CNode<T>*& node, T* tElement);
      void Insert(T* tElement);
      bool Remove(T* tElement);
      DWORD Count() const { return dwCount; }
      CNode<T>*& Head() { return head; }
      T* GetFirst(){ return head != NULL ? head->Element() : NULL; }
      T* GetLast();
      T* GetNext(T* tElement);
      T* Find(DWORD(*Function)(T* tParameter), DWORD dwValue);
    protected:
      CList(const CList& list);
      CList& operator = (const CList& list);
    private:
      CNode<T>* head;
      DWORD dwCount;
    };
    
    template <class T>
    void CList<T>::Append(CNode<T>*& node, T* tElement)
    {
        if (node == NULL)
        {
           dwCount++;
           node = new CNode<T>(tElement);
    
           return;
        }
    
        Append(node->Next(), tElement);
    }
    
    template <class T>
    void CList<T>::Insert(T* tElement)
    {
        dwCount++;
        if (head == NULL)
        {
           head = new CNode<T>(tElement);
           return;
        }
    
        CNode<T>* tmp = head;
        head = new CNode<T>(tElement);
        head->Next() = tmp;
    }
    
    template <class T>
    bool CList<T>::Remove(T* tElement)
    {
        if (head == NULL)
        {
           return NULL;
        }
    
        if (head->Element() == tElement)
        {
           CNode<T>* tmp = head;
           head = head->Next();
    
           delete tmp;
           dwCount--;
    
           return true;
        }
    
        CNode<T>* tmp = head;
        CNode<T>* lst = head->Next();
    
        while (lst != NULL)
        {
            if (lst->Element() == tElement)
            {
               tmp->Next() = lst->Next();
    
               delete lst;
               dwCount--;
    
               return true;
           }
    
           lst = lst->Next();
           tmp = tmp->Next();
        }
    
        return false;
    }
    
    template <class T>
    T* CList<T>::GetLast()
    {
        if (head)
        {
           CNode<T>* tmp = head;
           while (tmp->Next())
           {
              tmp = tmp->Next();
           }
           return tmp->Element();
        }
    
        return NULL;
    }
    
    template <class T>
    T* CList<T>::GetNext(T* tElement)
    {
        if (head == NULL)
        {
           return NULL;
        }
    
        if (tElement == NULL)
        {
           return GetFirst();
        }
    
        if (head->Element() == tElement)
        {
           return head->Next() != NULL ? head->Next()->Element() : NULL;
        }
    
        CNode<T>* lst = head->Next();
        while (lst != NULL)
        {
           if (lst->Element() == tElement)
           {
              return lst->Next() != NULL ? lst->Next()->Element() : NULL;
           }
    
           lst = lst->Next();
        }
    
        return NULL;
    }
    
    template <class T>
    T* CList<T>::Find(DWORD(*Function)(T* tParameter), DWORD dwValue)
    {
        try
        {
           T* tElement = NULL;
           while (tElement = GetNext(tElement))
           {
               if (Function(tElement) == dwValue)
               {
                  return tElement;
               }
           }
        }
        catch (...) { }
    
        return NULL;
    }
    
    #endif
  3. The provided files contain definitions and implementations of the CList class. Now, we can create CQueue and CStack very easily. Under the header files, create a new header file named CQueue.h and insert the following code:

    #ifndef __QUEUE__
    #define __QUEUE__
    
    #include "CList.h"
    
    template<class T>
    class CQueue : CList<T>
    {
    public:
      CQueue() : CList<T>(){ }
      CQueue(T* tElement) : CList<T>(tElement){ }
      virtual ~CQueue(){ }
      virtual void Enqueue(T* tElement)
      {
        Append(Head(), tElement);
      }
      virtual T* Dequeue()
      {
        T* tElement = GetFirst();
        Remove(tElement);
        return tElement;
      }
      virtual T* Peek()
      {
        return GetFirst();
      }
      CList<T>::Count;
    protected:
      CQueue(const CQueue<T>& cQueue);
      CQueue<T>& operator = (const CQueue<T>& cQueue);
    };
    
    #endif
  4. For CStack, we will do something similar. Under the header files, create a new header file named CStack.h and insert the following code:

    #ifndef __STACK__
    #define __STACK__
    #include "CList.h"
    
    template<class T>
    class CStack : CList<T>
    {
    public:
      CStack() : CList<T>(){ }
      CStack(T* tElement) : CList<T>(tElement){ }
      virtual ~CStack(){ }
      virtual void Push(T* tElement)
      {
        Insert(tElement);
      }
      virtual T* Pop()
      {
        T* tElement = GetFirst();
        Remove(tElement);
        return tElement;
      }
      virtual T* Peek()
      {
        return GetFirst();
      }
      CList<T>::Count;
    protected:
      CStack(const CStack<T>& cStack);
      CStack<T>& operator = (const CStack<T>& cStack);
    };
    
    #endif
  5. Finally, let's implement the following code in LinkedList.cpp, our placeholder for the main routine:

    #include <iostream>
    
    using namespace std;
    
    #include "CQueue.h"
    #include "CStack.h"
    
    int main()
    {
      CQueue<int>* cQueue = new CQueue<int>();
      CStack<double>* cStack = new CStack<double>();
    
      for (int i = 0; i < 10; i++)
      {
        cQueue->Enqueue(new int(i));
        cStack->Push(new double(i / 10.0));
      }
    
      cout << "Queue - integer collection:" << endl;
      for (; cQueue->Count();)
      {
        cout << *cQueue->Dequeue() << " ";
      }
    
      cout << endl << endl << "Stack - double collection:" << endl;
      for (; cStack->Count();)
      {
        cout << *cStack->Pop() << " ";
      }
    
      delete cQueue;
      delete cStack;
    
      cout << endl << endl;
      return system("pause");
    }

How it works...

Let's explain all the parts of the CList class first. The list consists of elements of type CNode for easier handling. The CNode class has two attributes: the tElement pointer to the user-defined element and the next pointer to the next list item. It implements two methods: Element and Next; the former returns a reference to the element address while the latter returns a reference to the next item address.

In literature constructor is referred as ctor and destructor as dtor. The CList default constructor is the public method that creates an empty list. The second constructor creates a list with a single starting element with a supplied pointer. As a list is a dynamic structure, the destructor is required. The Append method inserts an element as the last element in a collection. The Insert method inserts an element as the first element in a collection. The Count method returns the number of elements currently in the list. The Head method returns a reference to the list starting node.

The GetFirst method returns the first element from the list, or NULL if the list is empty. The GetLast method returns the last element from the list, or NULL if it's empty. The GetNext method returns the next list item, relative from the item for which the address is provided as the T* tElement parameter. If such an item is not found, the method returns NULL.

The Find method is most certainly an advanced feature. It is designed to use the undefined type T, and use its undefined Function method with the tParameter parameter. If we wanted to use a list of some objects, for example students, we would like to iterate them (using the GetNext method, for example) or find a specific student. What if it's possible for a future defined type to implement some method that will return unsigned long (DWORD) and can compare it with the dwValue parameter? For example, if we want to find a student based on their ID, we can use the following code:

#include <windows.h>
#include "CList.h"

class CStudent
{
public:
  CStudent(DWORD dwStudentId) : dwStudentId(dwStudentId){ }
  static DWORD GetStudentId(CStudent* student)
  {
    DWORD dwValue = student->GetId();
    return dwValue;
  }
  DWORD GetId() const
  {
    return dwStudentId;
  }
private:
  DWORD dwStudentId;
};

int main()
{
  CList<CStudent>* list = new CList<CStudent>();
  list->Insert(new CStudent(1));
  list->Insert(new CStudent(2));
  list->Insert(new CStudent(3));

  CStudent* s = list->Find(&CStudent::GetStudentId, 2);
  if (s != NULL)
  {
    // s FOUND
  }

  return 0;
}

If a list is used for primitive types, such as int, we can use the list as shown in the following code:

#include <windows.h>
#include "CList.h"

DWORD Predicate(int* iElement)
{
  return (DWORD)(*iElement);
}

int main()
{
  CList<int>* list = new CList<int>();
  list->Insert(new int(1));
  list->Insert(new int(2));
  list->Insert(new int(3));

  int* iElement = list->Find(Predicate, 2);
  if (iElement != NULL)
  {
    // iElement FOUND
  }

  return 0;
}

The protected methods are copy constructor (copy constructor) and operator= (operator equal). Why do we set these two methods as protected? The list implemented here, as we said, saves only pointers to objects that "live" outside the list itself. It would be dangerous to allow the user to copy the list intentionally or unintentionally and without caution, either using copy constructor or equal op for this reason. This is why we decided to protect copy constructor and disable the user from using it. In order to achieve this behavior, we need to declare, and later implement, both methods; else the compiler will generate them as public, by default, implementing them with copying pointers one by one, which is wrong. It is not enough to declare them as private either; in such a case, the same problem will occur for classes derived from the CList base class. They too need to declare copy constructor and equal op, else these methods will be public, generated from the compiler by default. When copy constructor exists in base class, the derived copy constructor will call it by default, except if the derived class calls it explicitly in another way. As we want to enable the CList copy constructor to be made available to the derived classes, it is declared as protected.

The private section of the CList class contains objects needed for the implementation of the linked list as a linear linked list. This means that every element points to the next, while the head node points to the first element.

The CQueue and CStack classes implement queue and stack, respectively. Notice how easy their implementation was after properly designing the CList base class (especially the Enqueue, Dequeue, Push, Pop, and Peek methods). Once the CList class is carefully designed, it is very simple to design and implement CQueue and CStack, or even some other classes later.

About the Author

  • Miloš Ljumović

    Miloš Ljumović was born on July 26 in Podgorica, the capital of Montenegro in Europe, where he attended elementary and high school. He also went to music school to play the guitar. He studied Computer Science in the Faculty of Natural Science and Mathematics, Montenegro University. The following year, he picked up interest in operating systems, which he majored in, in his Master's degree. In December 2009, along with his friend Danijel, he started his company, Programmer, along with a highly qualified team to provide high-tech IT solutions. Soon, many skilled developers joined them, and from this collaboration, many applications and system software, web applications, and database systems have arisen. His clients were not only the Government of Montenegro, but also some major domestic companies. To see what his interests are and what he is doing, visit his company's website http://expert.its.me or his website http://milos.expert.its.me, or contact him at [email protected]

    After working only for a few months as an international consultant, he worked with an American company in a project involving large e-commerce businesses and data scraping from the Internet. All this was the spark to open his new company, EXPERT.ITS.ME, in the beginning of July 2014. Besides development, he provides consulting services and helps small businesses in the IT sector to manage problems while inspiring them to be and think big. He is also a member of the Committee of National Chamber (ICT) of Montenegro and MENSA. He likes programming in C/C++/C# even though he is skilled in HTML, PHP, TSQL, and more while going toward his dream of developing his own operating system.

    In his spare time, he plays tennis, dives, hunts, or plays chess. He favors brainstorming with his team and fresh, modern ideas in the area of IT and computer science. He is continuously going towards new beginnings and next-generation software solutions. He specially likes teaching computer science and math students through private classes and courses and shaping them to be qualified programmers and helping them find all the beauty of science. He developed a new age financial system for the national domain company, MeNet; he also developed video recognition software, along with pictures and other digital media types. He also developed many fascinating websites and other web applications. The list of customers is too long to be incorporated here.

    Browse publications by this author

Latest Reviews

(4 reviews total)
Pitched at right level. Topical.
Très progressif et bien commenté avec des explications claires.
I really wanted to review this neutral but it was not an option. The book seemed misleading a bit just based off the description. I paid $5 I think, so I am not that upset. But there are a few things I saw which programming side were horribly incorrect just skimming througb, but sadly I could tell I knew everything in the book as well. I got this one on sale as well so I am not upset.
C++ Multithreading Cookbook
Unlock this book and the full library for $5 a month*
Start now