C++ Programming/Chapter Beyond the Standard Print version

From Wikibooks, the open-content textbooks collection

Jump to: navigation, search




Authors

The following people are authors to this book
Panic
The above authors release their work under the following license; this page shall be included in any copy of the C++ Programming book.
Any source code included if not bearing a different statement shall be considered under the public domain.
Images used have their own copyright status, specified in their respective repositories (en.wikibooks.org or at commons.wikimedia.org).
Acknowledgment is given for using some contents from other works like Wikipedia, the Wikibooks Java Programming, C Programming and C++ Exercises for beginners, the C/C++ Reference Web Site, and from Wikisource, as from the authors Scott Wheeler, Stephen Ferg and Ivor Horton.

There are many other contributors/editors to the book; a verifiable list of all contributions exist as History Logs at Wikibooks (http://en.wikibooks.org/).

Beyond the Standard

Resource Acquisition Is Initialization (RAII)

The RAII technique is often used for controlling thread locks in multi-threaded applications. Another typical example of RAII is file operations, e.g. the C++ standard library's file-streams. An input file stream is opened in the object's constructor, and it is closed upon destruction of the object. Since C++ allows objects to be allocated on the stack, C++'s scoping mechanism can be used to control file access.

With RAII we can use for instance Class destructors to guarantee to clean up, similarly to functioning as finally keyword on other languages, doing automates the task and so avoids errors but gives the freedom not to use it.

RAII is also used (as shown in the example below) to ensure exception safety. RAII makes it possible to avoid resource leaks without extensive use of try/catch blocks and is widely used in the software industry.

The ownership of dynamically allocated memory (memory allocated with new) can be controlled with RAII. For this purpose, the C++ Standard Library defines auto ptr. Furthermore, lifetime of shared objects can be managed by a smart pointer with shared-ownership semantics such as boost::shared_ptr defined in C++ by the Boost library or policy based Loki::SmartPtr from Loki library.

The following RAII class is a lightweight wrapper to the C standard library file system calls.

 #include <cstdio>
 
 // exceptions
 class file_error { } ;
 class open_error : public file_error { } ;
 class close_error : public file_error { } ;
 class write_error : public file_error { } ;
 
 class file
 {
 public:
     file( const char* filename )
         :
         m_file_handle(std::fopen(filename, "w+"))
     {
         if( m_file_handle == NULL )
         {
             throw open_error() ;
         }
     }
 
     ~file()
     {
         std::fclose(m_file_handle) ;
     }
 
     void write( const char* str )
     {
         if( std::fputs(str, m_file_handle) == EOF )
         {
             throw write_error() ;
         }
     }
 
     void write( const char* buffer, std::size_t num_chars )
     {
         if( num_chars != 0
             &&
             std::fwrite(buffer, num_chars, 1, m_file_handle) == 0 )
         {
             throw write_error() ;
         }
     }
 
 private:
     std::FILE* m_file_handle ;
 
     // copy and assignment not implemented; prevent their use by
     // declaring private.
     file( const file & ) ;
     file & operator=( const file & ) ;
 } ;

This RAII class can be used as follows :

void example_with_RAII()
{
  // open file (acquire resource)
  file logfile("logfile.txt") ;
 
  logfile.write("hello logfile!") ;
  // continue writing to logfile.txt ...
 
  // logfile.txt will automatically be closed because logfile's
  // destructor is always called when example_with_RAII() returns or
  // throws an exception.
}

Without using RAII, each function using an output log would have to manage the file explicitly. For example, an equivalent implementation without using RAII is this:

void example_without_RAII()
{
  // open file
  std::FILE* file_handle = std::fopen("logfile.txt", "w+") ;
 
  if( file_handle == NULL )
  {
    throw open_error() ;
  }
 
  try
  {
 
    if( std::fputs("hello logfile!", file_handle) == EOF )
    {
      throw write_error() ;
    }
 
    // continue writing to logfile.txt ... do not return
    // prematurely, as cleanup happens at the end of this function
  }
  catch(...)
  {
    // manually close logfile.txt
    std::fclose(file_handle) ;
 
    // re-throw the exception we just caught
    throw ;
  }
 
  // manually close logfile.txt 
  std::fclose(file_handle) ;
}

The implementation of file and example_without_RAII() becomes more complex if fopen() and fclose() could potentially throw exceptions; example_with_RAII() would be unaffected, however.

The essence of the RAII idiom is that the class file encapsulates the management of any finite resource, like the FILE* file handle. It guarantees that the resource will properly be disposed of at function exit. Furthermore, file instances guarantee that a valid log file is available (by throwing an exception if the file could not be opened).

There's also a big problem in the presence of exceptions: in example_without_RAII(), if more than one resource were allocated, but an exception was to be thrown between their allocations, there's no general way to know which resources need to be released in the final catch block - and releasing a not-allocated resource is usually a bad thing. RAII takes care of this problem; the automatic variables are destructed in the reverse order of their construction, and an object is only destructed if it was fully constructed (no exception was thrown inside its constructor). So example_without_RAII() can never be as safe as example_with_RAII() without special coding for each situation, such as checking for invalid default values or nesting try-catch blocks. Indeed, it should be noted that example_without_RAII() contained resource bugs in previous versions of this article.

This frees example_with_RAII() from explicitly managing the resource as would otherwise be required. When several functions use file, this simplifies and reduces overall code size and helps ensure program correctness.

example_without_RAII() resembles the idiom used for resource management in non-RAII languages such as Java. While Java's try-finally blocks allow for the correct release of resources, the burden nonetheless falls on the programmer to ensure correct behavior, as each and every function using file may explicitly demand the destruction of the log file with a try-finally block.

Garbage collection

Garbage collection is a form of automatic memory management. The garbage collector or collector attempts to reclaim garbage, or memory used by objects that will never be accessed or mutated again by the application.

Tracing garbage collectors require some implicit runtime overhead that may be beyond the control of the programmer, and can sometimes lead to performance problems. For example, commonly used Stop-The-World garbage collectors, which pause program execution at arbitrary times, may make GC languages inappropriate for some embedded systems, high-performance server software, and applications with real-time needs.

A more fundamental issue is that garbage collectors violate locality of reference, since they deliberately go out of their way to find bits of memory that haven't been accessed recently. The performance of modern computer architectures is increasingly tied to caching, which depends on the assumption of locality of reference for its effectiveness. Some garbage collection methods result in better locality of reference than others. Generational garbage collection is relatively cache-friendly, and copying collectors automatically defragment memory helping to keep related data together. Nonetheless, poorly timed garbage collection cycles could have a severe performance impact on some computations, and for this reason many runtime systems provide mechanisms that allow the program to temporarily suspend, delay or activate garbage collection cycles.

Despite these issues, for many practical purposes, allocation/deallocation-intensive algorithms implemented in modern garbage collected languages can actually be faster than their equivalents using explicit memory management (at least without heroic optimizations by an expert programmer). A major reason for this is that the garbage collector allows the runtime system to amortize allocation and deallocation operations in a potentially advantageous fashion. For example, consider the following program in C++:

#include <iostream>
 
class A {
  int x;
public:
  A() { x = 0; ++x; }
};
 
int main() {
 for (int i = 0; i < 1000000000; ++i) {
   A *a = new A();
   delete a;
 }
 std::cout << "DING!" << std::endl;
}

One of more widely used libraries that provides this function is Hans Boehm's conservative GC. C++ also supports a powerful idiom called RAII (resource acquisition is initialization) that is covered in the RAII Section of this book that states that RAII can be used to safely and automatically manage resources including memory.

TODO

TODO
Add some examples into libraries and extend a bit more this info

Programming Patterns

Software design patterns are abstractions that help structure system designs. While not new, since the concept was already described by Christopher Alexander in its architectural theories, it only gathered some traction in programming due to the publication of Design Patterns: Elements of Reusable Object-Oriented Software book in October 1994 by the Gang of Four (GoF), that identifies and describes 23 classic software design patterns.

A design pattern is not a static solution, it is not an algorithm. A pattern is a way to describe and address by name (mostly a simplistic description of its goal), a repeatable solution or approach to a common design problem, that is, a common way to solve a generic problem (how generic or complex, depends on how restricted the target goal is). Patterns can emerge on their own or by design, this is why design patterns are useful as an abstraction over the implementation and a help at design stage.

Patterns are commonly found in objected oriented programming languages like C++. They can be seen as a template for how to solve a problem that occurs in many different situations and/or applications. It is not code reuse as it usually does not specify code, but code can be easily created from a design pattern. Object-oriented design patterns typically show relationships and interactions between classes or objects, without specifying the final application classes or objects that are involved.

Each design pattern consists of the following parts:

Problem/requirement 
To use a design pattern, we need to go through a mini analysis design that may be coded to test out the solution. This section states the requirements of the problem we want to solve. This is usually a common problem that will occur in more than one application.
Forces 
This section states the technological boundaries, that helps and guides the creation of the solution.
Solution 
This section describes how to write the code to solve the above problem. This is the design part of the design pattern. It may contain class diagrams, sequence diagrams, and or whatever is needed to describe how to code the solution.

Design patterns can be considered as a standardization of commonly agreed best practices to solve specific design problems, one should at least understand them as a way to implement good design patterns within applications. Doing so will reduce the use of inefficient and obscure solutions. Using design patterns speeds up your design and helps to communicate your design to other programmers.

Creational Patterns

In software engineering, creational design patterns are design patterns that deal with object creation mechanisms, trying to create objects in a manner suitable to the situation. The basic form of object creation could result in design problems or added complexity to the design. Creational design patterns solve this problem by somehow controlling this object creation.

In this section of the book we assume that the reader has enough familiarity with functions, global variables, stack vs. heap, classes, pointers, and static member functions as introduced before.

As we will see there are several creational design patterns, and all will deal with a specific implementation task, that will create a higher level of abstraction to the code base, we will now cover each one.

Builder

The Builder Creational Pattern is used to separate the construction of a complex object from its representation so that the same construction process can create different objects representations.

Problem 
We want to construct a complex object, however we do not want to have a complex constructor member or one that would need many arguments.
Solution 
Define an intermediate object whose member functions define the desired object part by part before the object is available to the client. Build Pattern lets us defer the construction of the object until all the options for creation have been specified.

Factory Method

The Factory Design Pattern is useful in a situation where a design requires the creation of many different types of objects, all of which come from a common base type. The Factory Method will take a description of a desired object at run time, and return a new instance of that object. The upshot of the pattern is that you can take a real world description of an object, like a string read from user input, pass it into the factory, and the factory will return a base class pointer. The pattern works best when a well designed interface is used for the base class, so that the returned object may be used fully without having to cast it, using RTTI.

Problem 
We want to decide at run time what object is to be created based on some configuration or application parameter. When we write the code we do not know what class should be instantiated.
Solution 
Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

The following example uses the notion of laptop vs. desktop computer objects with a computer factory.

Let's start by defining out base class (interface) and the derived classes: Desktop and Laptop. Neither of these classes actually "do" anything, but are meant for the illustrative purpose.

 class Computer
 {
 public:
     virtual void Run() = 0;
     virtual void Stop() = 0;
 };
 class Laptop: public Computer
 {
 public:
     virtual void Run(){mHibernating = false;}
     virtual void Stop(){mHibernating = true;}
 private:
     bool mHibernating; // Whether or not the machine is hibernating
 };
 class Desktop: public Computer
 {
 public:
     virtual void Run(){mOn = true;}
     virtual void Stop(){mOn = false;}
 private:
     bool mOn; // Whether or not the machine has been turned on
 };

Now for the actual Factory, returns a Computer, given a real world description of the object

 class ComputerFactory
 {
 public:
     static Computer *NewComputer(const std::string &description)
     {
         if(description == "laptop")
             return new Laptop;
         if(description == "desktop")
             return new Desktop;
         return NULL;
     }
 };

Thanks to the magic of virtual functions, the caller of the factory method can use the returned results, without any knowledge of the true type of the object.

Let's analyze the benefits of this. First, there is a compilation benefit. If we move the interface "Computer" into a separate header file with the factory, we can then move the implementation of the NewComputer() function into a separate implementation file. By doing this, that implementation file for NewComputer() is the only one which needs knowledge of the derived classes. Thus, if a change is made to any derived class of Computer, or a new Computer type is added, the implementation file for NewComputer() is the only file which needs to be recompiled. Everyone who uses the factory will only care about the interface, which will hopefully remain consistent throughout the life of the application.

Also, if a new class needs to be added, and the user is requesting objects through a user interface of some sort, no code calling the factory may need to change to support the additional computer type. The code using the factory would simply pass on the new string to the factory, and allow the factory to handle the new types entirely.

Imagine programming a video game, where you would like to add new types of enemies in the future, each of which has different AI functions, and can update differently. By using a factory method, the controller of the program can call to the factory to create the enemies, without any dependency or knowledge of the actual types of enemies. Now, future developers can create new enemies, with new AI controls, and new drawing member functions, add it to the factory, and create a level which calls the factory, asking for the enemies by name. Combine this method with an XML description of levels, and developers could create new levels without any need to ever recompile their program. All this, thanks to the separation of creation of objects from the usage of objects.

Prototype

Specify the kinds of objects to create using a prototypical instance, and create new objects by copying that prototype.

  • A prototype pattern is used in software development when the type of objects to create is determined by a prototypical instance, which is cloned to produce new objects. This pattern is used for example when the inherent cost of creating a new object in the standard way (e.g., using the 'new' keyword) is prohibitively expensive for a given application.
  • Implementation: Declare an abstract base class that specifies a pure virtual clone() method. Any class that needs a "polymorphic constructor" capability derives itself from the abstract base class, and implements the clone() operation.
  • Here the client code first invokes the factory method. This factory method, depending on the parameter, finds out concrete class. On this concrete class call to the Clone() method is called and the object is returned by the factory method.
  • This is sample code which is a sample implementation of Prototype method. We have the detailed description of all the components here.
    • "Record" class which is a pure virtual class which is having pure virtual method "Clone()".
    • "CarRecord", "BikeRecord" and "PersonRecord" as concrete implementation of "Record" class.
    • An enum RECORD_TYPE_en as one to one mapping of each concrete implementation of "Record" class.
    • "RecordFactory" class which is having Factory method "CreateRecord(...)". This method requires an enum RECORD_TYPE_en as parameter and depending on this parameter it returns the concrete implementation of "Record" class.
  /**
   * Implementation of Prototype Method 
   **/
  #include <iostream>
  #include <map>
 
  using namespace std;
 
  enum RECORD_TYPE_en
  {
    CAR,
    BIKE,
    PERSON
  };
 
  /**
   * Record is the Prototype
   */
 
  class Record
  {
    public :
 
      Record() {}
 
      ~Record() {}
 
      Record* Clone()=0;
 
      virtual void Print()=0;
  };
 
  /**
   * CarRecord is Concrete Prototype
   */
 
  class CarRecord : public Record
  {
    private :
      string m_oStrCarName;
 
      u_int32_t m_ui32ID;
 
    public :
 
      CarRecord(string _oStrCarName,u_int32_t _ui32ID)
        : Record(), m_oStrCarName(_oStrCarName),
          m_ui32ID(_ui32ID)
      {
      }
 
      CarRecord(CarRecord& _oCarRecord)
        : Record()
      {
        m_oStrCarName = _oCarRecord.m_oStrCarName;
        m_ui32ID = _oCarRecord.m_ui32ID;
      }
 
      ~CarRecord() {}
 
      Record* Clone()
      {
        return new CarRecord(*this);
      }
 
      void Print()
      {
        cout << "Car Record" << endl
          << "Name  : " << m_oStrCarName << endl
          << "Number: " << m_ui32ID << endl << endl;
      }
  };
 
 
  /**
   * BikeRecord is the Concrete Prototype
   */
 
  class BikeRecord : public Record
  {
    private :
      string m_oStrBikeName;
 
      u_int32_t m_ui32ID;
 
    public :
      BikeRecord(string _oStrBikeName,u_int32_t _ui32ID)
        : Record(), m_oStrBikeName(_oStrBikeName),
          m_ui32ID(_ui32ID)
      {
      }
 
      BikeRecord(BikeRecord& _oBikeRecord)
        : Record()
      {
        m_oStrBikeName = _oBikeRecord.m_oStrBikeName;
        m_ui32ID = _oBikeRecord.m_ui32ID;
      }
 
      ~BikeRecord() {}
 
      Record* Clone()
      {
        return new BikeRecord(*this);
      }
 
      void Print()
      {
        cout << "Bike Record" << endl
          << "Name  : " << m_oStrBikeName << endl
          << "Number: " << m_ui32ID << endl << endl;
      }
  };
 
 
  /**
   * PersonRecord is the Concrete Prototype
   */
 
  class PersonRecord : public Record
  {
    private :
      string m_oStrPersonName;
 
      u_int32_t m_ui32Age;
 
    public :
      PersonRecord(string _oStrPersonName, u_int32_t _ui32Age)
        : Record(), m_oStrPersonName(_oStrPersonName),
          m_ui32Age(_ui32Age)
      {
      }
 
      PersonRecord(PersonRecord& _oPersonRecord)
        : Record()
      {
        m_oStrPersonName = _oPersonRecord.m_oStrPersonName;
        m_ui32Age = _oPersonRecord.m_ui32Age;
      }
 
      ~PersonRecord() {}
 
      Record* Clone()
      {
        return new PersonRecord(*this);
    }
 
    void Print()
    {
      cout << "Person Record" << endl
        << "Name : " << m_oStrPersonName << endl
        << "Age  : " << m_ui32Age << endl << endl ;
    }
  };
 
 
  /**
   * RecordFactory is the client
   */
 
  class RecordFactory
  {
    private :
      map<RECORD_TYPE_en, Record* > m_oMapRecordReference;
 
    public :
      RecordFactory()
      {
        m_oMapRecordReference[CAR]  = new CarRecord("Ferrari", 5050);
        m_oMapRecordReference[BIKE] = new BikeRecord("Yamaha", 2525);
      m_oMapRecordReference[PERSON] = new PersonRecord("Tom", 25);
      }
 
      ~RecordFactory()
      {
        delete m_oMapRecordReference[CAR];
        delete m_oMapRecordReference[BIKE];
        delete m_oMapRecordReference[PERSON];
      }
 
      Record* CreateRecord(RECORD_TYPE_en enType)
      {
        return m_oMapRecordReference[enType]->Clone();
      }
  };
 
  int main()
  {
    RecordFactory* poRecordFactory = new RecordFactory();
 
    Record* poRecord;
    poRecord = poRecordFactory->CreateRecord(CAR);
    poRecord->Print();
    delete poRecord;
 
    poRecord = poRecordFactory->CreateRecord(BIKE);
    poRecord->Print();
    delete poRecord;
 
    poRecord = poRecordFactory->CreateRecord(PERSON);
    poRecord->Print();
    delete poRecord;
 
    delete poRecordFactory;
    return 0;
  }

Another example:

To implement the pattern, declare an abstract base class that specifies a pure virtual clone() member function. Any class that needs a "polymorphic constructor" capability derives itself from the abstract base class, and implements the clone() operation.

The client, instead of writing code that invokes the "new" operator on a hard-wired class name, calls the clone() member function on the prototype, calls a factory member function with a parameter designating the particular concrete derived class desired, or invokes the clone() member function through some mechanism provided by another design pattern.

 class CPrototypeMonster
 {
 protected:            
     CString           _name;
 public:
     CPrototypeMonster();
     CPrototypeMonster( const CPrototypeMonster& copy );
     ~CPrototypeMonster();
 
     virtual CPrototypeMonster*    Clone() const=0; // This forces every derived class to provide an overload for this function.
     void        Name( CString name );
     CString    Name() const;
 };
 
 class CGreenMonster : public CPrototypeMonster
 {
 protected: 
     int         _numberOfArms;
     double      _slimeAvailable;
 public:
     CGreenMonster();
     CGreenMonster( const CGreenMonster& copy );
     ~CGreenMonster();
 
     virtual CPrototypeMonster*    Clone() const;
     void  NumberOfArms( int numberOfArms );
     void  SlimeAvailable( double slimeAvailable );
 
     int         NumberOfArms() const;
     double      SlimeAvailable() const;
 };
 
 class CPurpleMonster : public CPrototypeMonster
 {
 protected:
     int         _intensityOfBadBreath;
     double      _lengthOfWhiplikeAntenna;
 public:
     CPurpleMonster();
     CPurpleMonster( const CPurpleMonster& copy );
     ~CPurpleMonster();
 
     virtual CPrototypeMonster*    Clone() const;
 
     void  IntensityOfBadBreath( int intensityOfBadBreath );
     void  LengthOfWhiplikeAntenna( double lengthOfWhiplikeAntenna );
 
     int       IntensityOfBadBreath() const;
     double    LengthOfWhiplikeAntenna() const;
 };
 
 class CBellyMonster : public CPrototypeMonster
 {
 protected:
     double      _roomAvailableInBelly;
 public:
     CBellyMonster();
     CBellyMonster( const CBellyMonster& copy );
     ~CBellyMonster();
 
     virtual CPrototypeMonster*    Clone() const;
 
     void       RoomAvailableInBelly( double roomAvailableInBelly );
     double     RoomAvailableInBelly() const;
 };
 
 CPrototypeMonster* CGreenMonster::Clone() const
 {
     return new CGreenMonster(*this);
 }
 
 CPrototypeMonster* CPurpleMonster::Clone() const
 {
     return new CPurpleMonster(*this);
 }
 
 CPrototypeMonster* CBellyMonster::Clone() const
 {
     return new CBellyMonster(*this);
 }

A client of one of the concrete monster classes only needs a reference (pointer) to a CPrototypeMonster class object to be able to call the ‘Clone’ function and create copies of that object. The function below demonstrates this concept:

 void DoSomeStuffWithAMonster( const CPrototypeMonster* originalMonster )
 {
     CPrototypeMonster* newMonster = originalMonster->Clone();
     ASSERT( newMonster );
 
     newMonster->Name("MyOwnMoster");
     // Add code doing all sorts of cool stuff with the monster.
     delete newMonster;
 }

Now originalMonster can be passed as a pointer to CGreenMonster, CPurpleMonster or CBellyMonster.

Singleton

The term Singleton refers to an object that can only be instantiated once. This pattern is generally used where a global variable would have otherwise been used. The main advantage of the singleton is that its existence is guaranteed. Other advantages of the design pattern include the clarity, from the unique access, that the object used is not on the local stack. Some of the downfalls of the object include that, like a global variable, it can be hard to tell what chunk of code corrupted memory, when a bug is found, since everyone has access to it.

TODO

TODO
Other pros/cons of the use of singletons.

Let's take a look at how a Singleton differs from other variable types.

Like a global variable, the Singleton exists outside of the scope of any functions. Traditional implementation uses a static member function of the Singleton class, which will create a single instance of the Singleton class on the first call, and forever return that instance. The following code example illustrates the elements of a C++ singleton class, that simply stores a single string.

 class StringSingleton
 {
 public:
     // Some accessor functions for the class, itself
     std::string GetString() const 
     {return mString;}
     void SetString(const std::string &newStr)
     {mString = newStr;}
 
     // The magic function, which allows access to the class from anywhere
     // To get the value of the instance of the class, call:
     //     StringSingleton::Instance().GetString();
     static StringSingleton &Instance()
     {
         // This line only runs once, thus creating the only instance in existence
         static StringSingleton *instance = new StringSingleton;
         // dereferencing the variable here, saves the caller from having to use 
         // the arrow operator, and removes tempation to try and delete the 
         // returned instance.
         return *instance; // always returns the same instance
     }
 
 private: 
     // We need to make some given functions private to finish the definition of the singleton
     StringSingleton(){} // default constructor available only to members or friends of this class
 
     // Note that the next two functions are not given bodies, thus any attempt 
     // to call them implicitly will return as compiler errors. This prevents 
     // accidental copying of the only instance of the class.
     StringSingleton(const StringSingleton &old); // disallow copy constructor
     const StringSingleton &operator=(const StringSingleton &old); //disallow assignment operator
 
     // Note that although this should be allowed, 
     // some compilers may not implement private destructors
     // This prevents others from deleting our one single instance, which was otherwise created on the heap
     ~StringSingleton(){} 
 private: // private data for an instance of this class
     std::string mString;
 };

Variations of Singletons:

TODO

TODO
Discussion of Meyers Singleton and any other variations.

Applications of Singleton Class:

One common use of the singleton design pattern is for application configurations. Configurations may need to be accessible globally, and future expansions to the application configurations may be needed. The subset C's closest alternative would be to create a single global struct. This had the lack of clarity as to where this object was instantiated, as well as not guaranteeing the existence of the object.

Take, for example, the situation of another developer using your singleton inside the constructor of their object. Then, yet another developer decides to create an instance of the second class in the global scope. If you had simply used a global variable, the order of linking would then matter. Since your global will be accessed, possibly before main begins executing, there is no definition as to whether the global is initialized, or the constructor of the second class is called first. This behavior can then change with slight modifications to other areas of code, which would change order of global code execution. Such an error can be very hard to debug. But, with use of the singleton, the first time the object is accessed, the object will also be created. You now have an object which will always exist, in relation to being used, and will never exist if never used.

A second common use of this class is in updating old code to work in a new architecture. Since developers may have used to use globals liberally, pulling these into a single class and making it a singleton, can allow an intermediary step to bringing a structural program into an object oriented structure.

Structural Patterns

Adapter

Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.

Bridge

The Bridge Pattern is used to separate out the interface from its implementation. Doing this gives the flexibility so that both can vary independently.

Composite

Composite lets clients treat individual objects and compositions of objects uniformly. The Composite pattern can represent both the conditions. In this pattern, one can develop tree structures for representing part-whole hierarchies.

Decorator

The decorator pattern helps to attach additional behavior or responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality. This is also called “Wrapper”.

Facade

The Facade Pattern hides the complexities of the system by providing an interface to the client from where the client can access the system on an unified interface. Facade defines a higher-level interface that makes the subsystem easier to use.

Flyweight

It is the use of sharing mechanism by which you can avoid creating a large number of object instances to represent the entire system by using a smaller set fine-grained objects efficiently. A flyweight is a shared object that can be used in multiple contexts simultaneously. The flyweight will act as an independent object in each context, becoming indistinguishable from an instance of the object that’s not shared. To decide if some part of a program is a candidate for using Flyweights, consider whether it is possible to remove some data from the class and make it extrinsic.

Proxy

The Proxy Pattern will provide an object a surrogate or placeholder for another object to control access to it. It is used when you need to represent a complex object with a simpler one. If creation of an object is expensive, it can be postponed until the very need arises and meanwhile a simpler object can serve as a placeholder. This placeholder object is called the “Proxy” for the complex object.

Curiously Recurring Template

This technique is known more widely as a mixin. Mixins are described in the literature to be a powerful tool for expressing abstractions.

Behavioral Patterns

Chain of Responsibility

Chain of Responsibility pattern has the intent to avoid coupling the sender of a request to its receiver by giving more then one object a chance to handle the request. Chains the receiving objects and passes the requests along the chain until an object handles it.

Command

Command pattern is an Object behavioral pattern that decouples sender and receiver by encapsulating a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations. It can also be thought as an object oriented equivalent of call back method.

Call Back: It is a function that is registered to be called at later point of time based on user actions.

Interpreter

Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.

Iterator

The 'iterator' design pattern is used liberally within the STL for traversal of various containers. The full understanding of this will liberate a developer to create highly reusable and easily understandable data containers.

The basic idea of the iterator is that it permits the traversal of a container (like a pointer moving across an array). However, to get to the next element of a container, you need not know anything about how the container is constructed. This is the iterators job. By simply using the member functions provided by the iterator, you can move, in the intended order of the container, from the first element to the last element.

Let's start by considering a traditional single dimensional array with a pointer moving from the start to the end. This example assumes knowledge of pointer arithmetic. Note that the use of "it" or "itr," henceforth, is a short version of "iterator."

 const int ARRAY_LEN = 42;
 int *myArray = new int[ARRAY_LEN];
 // Set the iterator to point to the first memory location of the array
 int *arrayItr = myArray;
 // Move through each element of the array, setting it equal to its position in the array
 for(int i = 0; i < ARRAY_LEN; ++i)
 {
    // set the value of the current location in the array
    *arrayItr = i;
    // by incrementing the pointer, we move it to the next position in the array.
    // This is easy for a contiguous memory container, since pointer arithmetic 
    // handles the traversal.
    ++arrayItr;
 }
 // Don't be messy, clean up after yourself
 delete[] myArray;

This code works very quickly for arrays, but how would we traverse a linked list, when the memory is not contiguous? Consider the implementation of a rudimentary linked list as follows:

TODO

TODO
test compiling this, check for syntax errors.

 class IteratorCannotMoveToNext{}; // Error class
 class MyIntLList
 {
 public:
     // The Node class represents a single element in the linked list. 
     // The node has a next node and a previous node, so that the user 
     // may move from one position to the next, or step back a single 
     // position. Notice that the traversal of a linked list is O(N), 
     // as is searching, since the list is not ordered.
     class Node
     {
     public:
         Node():mNextNode(0),mPrevNode(0),mValue(0){}
         Node *mNextNode;
         Node *mPrevNode;
         int mValue;
     };
     MyIntLList():mSize(0) 
     {}
     ~MyIntLList()
     {
         while(!Empty())
             pop_front();
     } // See expansion for further implementation;
     int Size() const {return mSize;}
     // Add this value to the end of the list
     void push_back(int value)
     {
         Node *newNode = new Node;
         newNode->mValue = value;
         newNode->mPrevNode = mTail;
         mTail->mNextNode = newNode;
         mTail = newNode;
         ++mSize;
     }
     // Remove the value from the beginning of the list
     void pop_front()
     {
         if(Empty())
             return;
         Node *tmpnode = mHead;
         mHead = mHead->mNextNode
         delete tmpnode;
         --mSize;
     }
     bool Empty()
     {return mSize == 0;}
 
     // This is where the iterator definition will go, 
     // but lets finish the definition of the list, first
 
 private:
     Node *mHead;
     Node *mTail;
     int mSize;
 };

This linked list has non-contiguous memory, and is therefore not a candidate for pointer arithmetic. And we dont want to expose the internals of the list to other developers, forcing them to learn them, and keeping us from changing it.

This is where the iterator comes in. The common interface makes learning the usage of the container easier, and hides the traversal logic from other developers.

Let's examine the code for the iterator, itself.

     /*
      *  The iterator class knows the internals of the linked list, so that it 
      *  may move from one element to the next. In this implementation, I have 
      *  chosen the classic traversal method of overloading the increment 
      *  operators. More thorough implementations of a bi-directional linked 
      *  list would include decrement operators so that the iterator may move 
      *  in the opposite direction.
      */
     class Iterator
     {
     public:
         Iterator(Node *position):mCurrNode(position){}
         // Prefix increment
         const Iterator &operator++()
         {
             if(mCurrNode == 0 || mCurrNode->mNextNode == 0)
                 throw IteratorCannotMoveToNext();e
             mCurrNode = mCurrNode->mNextNode;
             return *this;
         }
         // Postfix increment
         Iterator operator++(int)
         {
             Iterator tempItr = *this;
             ++(*this);
             return tempItr;
         }
         // Dereferencing operator returns the current node, which should then 
         // be dereferenced for the int. TODO: Check syntax for overloading 
         // dereferencing operator
         Node * operator*()
         {return mCurrNode;}
         // TODO: implement arrow operator and clean up example usage following
     private:
         Node *mCurrNode;
     };
     // The following two functions make it possible to create 
     // iterators for an instance of this class.
     // First position for iterators should be the first element in the container.
     Iterator Begin(){return Iterator(mHead);}
     // Final position for iterators should be one past the last element in the container.
     Iterator End(){return Iterator(0);}

With this implementation, it is now possible, without knowledge of the size of the container or how its data is organized, to move through each element in order, manipulating or simply accessing the data. This is done through the accessors in the MyIntLList class, Begin() and End().

 // Create a list
 MyIntLList mylist;
 // Add some items to the list
 for(int i = 0; i < 10; ++i)
     myList.push_back(i);
 // Move through the list, adding 42 to each item.
 for(MyIntLList::Iterator it = myList.Begin(); it != myList.End(); ++it)
     (*it)->mValue += 42;
TODO

TODO

  • Discussion of iterators in the STL, and the usefulness of iterators within the algorithms library.
  • Iterators best practices
  • Warnings on creation of and usage of

Mediator

Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.

Memento

Without violating encapsulation the memento Pattern will capture and externalize an object’s internal state so that the object can be restored to this state later. Though the Gang of Four uses friend as a way to implement this pattern it is not the best design. It can also be implemented using PIMPL. Best Use case is 'Undo-Redo' in an editor.

Observer

The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

Problem 
In one place or many places in the application we need to be aware about a system event or an application state change. We'd like to have a standard way of subscribing to listening for system events and a standard way of notifying the interested parties. The notification should be automated after an interested party subscribed to the system event or application state change. There also should be a way to unsubscribed.
Forces 
Observers and observables probably should be represented by objects. The observer objects will be notified by the observable objects.
Solution 
After subscribing the listening objects will be notified by a way of method call.

State

The State Pattern allows an object to alter its behavior when its internal state changes. The object will appear as having changed its class.

Strategy

Defines a family of algorithms, encapsulates each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients who use it.

Template Method

By defining a skeleton of an algorithm in an operation, deferring some steps to subclasses, the Template Method lets subclasses redefine certain steps of that algorithm without changing the algorithms structure.

Visitor

The Visitor Pattern will represent an operation to be performed on the elements of an object structure by letting you define a new operation without changing the classes of the elements on which it operates.

Model-View-Controller (MVC)

pattern often used by applications that need the ability to maintain multiple views of the same data.

Further reading

Libraries

Libraries allow existing code to be reused in a program. Libraries are like programs except that instead of relying on main() to do the work you call specific functions that the library provides to do the work. Functions provide the interface between the program being written and the library being used. This interface is called Application Programming Interface or API.

What is an API?

To a programmer, an operating system is defined by its API. API stands for Application Programming Interface. An API encompasses all the function calls that an application program can communicate with the hardware or the operating system, or any other application that provides a set of interfaces to the programmer (ie: a library), as well as definitions of associated data types and structures. Most APIs are defined on the application Software Development Kit (SDK) for program development.

In simple terms the API can be considered as the interface through which the user (or user programs) will be able interact with the operating system, hardware or other programs to make them to perform a task that may also result in obtaining a result message.

Can an API be called a framework?

No, a framework may provide an API, but a framework is more than a simple API. By default a framework also defines how the code is written, it is a set of solutions, even classes, that as a group addresses the handling of a limited set of related problems and provides not only an API but a default functionality, well designed frameworks enable its interchangeability for a similar framework, striving to provides the same API.

As seen in the file organization Section, compiled libraries consists in C++ headers files that are included by the preprocessor and binary library files which are used by the linker to generate the resulting compilation. For a dynamically linked library, only the loading code is added to the resulting compilation, the actual loading of the library is done in the memory at run-time.

Programs can make use of libraries in two forms, as static or dynamic depending on how the programmer decides to distribute its code or even due to the licensing used by third party libraries, the static and dynamic libraries section of this book will cover in depth this subject.

Third party libraries

Additional functionality that goes beyond the standard libraries (like garbage collection) are available (often free) by third party libraries, but remember that third party libraries do not necessarily provide the same ubiquitous cross-platform functionality or an API style conformant with as standard libraries. The main motivation for their existence is for preventing one tho reinvent the wheel and to make efforts converge; too much energy has been spent by generations of programmers to write safe and "portable" code.

There are several libraries a the programmer is expected to know about or have at least a passing idea of what they are. Time, consistency and extended references will make a few libraries pop-out from the rest. One notable example is the highly respected collection of Boost libraries that we will examine ahead.

Licensing on third party libraries

The programmer may also be limited by the requirements of the license used on external libraries that he has no direct control, for instance the use of GNU GPL code in closed source applications isn't permitted to address this issue the FSF provides an alternative in the form of the GNU LGPL license that permits such uses but only in the dynamically linked form, this is mirrored by several other legal requirements a programmer must attend and comply to.

Static and Dynamic Libraries

Libraries come in two forms, either in source form or in compiled/binary form. Libraries in source-form must first be compiled before they can be included in another project. This will transform the libraries' cpp-files into a lib-file. If a program needs to be recompiled to run with a new version of library but doesn't require any further modifications, the library is source compatible. If a program does not need to be modified and recompiled in order to use a new version of a library, the library is binary compatible.

Advantages of using static binaries:

  • Simplification of program distribution (fewer files)
  • Code simplification (no version checks of dynamic libraries)

Disadvantages of using static binaries:

  • Waste of resources: Generates larger binaries, since the library is compiled into every executable. Wasting memory, since library cannot be shared (in memory) between processes (may depend on operating system).
  • Program will not benefit from bug fixes or extensions in the libraries without being recompiled.
Binary/Source Compatibility of libraries

A library is said to be binary compatible if the program that dynamically links to a previous version of that library, continues to work using another versions of the same library. If a recompilation of the program is needed for it to operate with each new version the library is said to be source compatible.

Producing and maintaining binary compatible libraries is beneficial for distribution but harder to be maintained by teh library creators, it is often seen as a better solution to do static linking if the library is only source compatible since it will not cause problems to the end user.

Binary compatibility saves a lot of trouble and is a signal that the library reached a status of stability. It makes it much easier to distribute software for a certain platform. Without ensuring binary compatibility between releases, people will be forced to provide statically linked binaries.

Example: Configuring MS Visual C++ to use external libraries

The Boost library is used as example library.

NOTE:
Boost.org has a install guide named Getting Started on Windows, that points to an automatic installed provided by BoostPro Computing (commonly supporting the previous and older release versions), noting also that if used with the option “Source and Documentation” deselected (selected by default), it will not show the libs/ subdirectory. This will disable the user from rebuilding part of the libraries that aren't only header files. This makes installing it yourself as shown in this section the best option.

Considering you already have decompressed and have the binary part of the Boost library built. There the steps which have to be performed:

Include directory

Set up the include directory. This is the directory that contains the header files (.h/hpp), which describes the library interface:

include directories

Library directory

Set up the library directory. This is the directory that contains the pre-compiled library files (.lib):

library directories

Library files

Enter library filenames in additional dependencies for the libraries to use:

library filenames (the Boost "REGEXP"-library in this example)

Some libraries (such as e.g. Boost) uses auto-linking to automate the process of selecting library files for linking, based on which header-files are included. Manual selection of library filenames are not required for such libraries if your compiler supports auto-linking.

Dynamic libraries

In case of dynamically loaded (.dll) libraries, one also have to place the DLL-files either in the same folder as the executable, or in the system PATH.

Run-time library

The libraries also have to be compiled with the same run-time library as the one used in your project. Many libraries therefore come in different editions, depending on whether they are compiled for single- or multithreaded runtime and debug or release runtime, as well as whether they contain debug symbols or not.

selection of run-time library



Boost Library

The Boost library (http://www.boost.org/) provides free peer-reviewed , open source libraries that extend the functionality of C++. Most of the libraries are licensed under the Boost Software License, designed to allow Boost to be used with both open and closed source projects.

Many of Boost's founders are on the C++ standard committee and several Boost libraries have been accepted for incorporation into the Technical Report 1 of C++0x. Although Boost was begun by members of the C++ Standards Committee Library Working Group, participation has expanded to include thousands of programmers from the C++ community at large.

The emphasis is on libraries which work well with the C++ Standard Library. The libraries are aimed at a wide range of C++ users and application domains, and are in regular use by thousands of programmers. They range from general-purpose libraries like SmartPtr, to OS Abstractions like FileSystem, to libraries primarily aimed at other library developers and advanced C++ users, like MPL.

A further goal is to establish "existing practice" and provide reference implementations so that Boost libraries are suitable for eventual standardization. Ten Boost libraries will be included in the C++ Standards Committee's upcoming C++ Standard Library Technical Report as a step toward becoming part of a future C++ Standard.

In order to ensure efficiency and flexibility, Boost makes extensive use of templates. Boost has been a source of extensive work and research into generic programming and metaprogramming in C++.

extension libraries

  • Algorithms
  • Concurrent programming (threads)
  • Containers
    • array - Management of fixed-size arrays with STL container semantics
    • Boost Graph Library (BGL) - Generic graph containers, components and algorithms
    • multi-array - Simplifies creation of N-dimensional arrays
    • multi-index containers - Containers with built in indexes that allow different sorting and access semantics
    • pointer containers - Containers modeled after most standard STL containers that allow for transparent management of pointers to values
    • property map - Interface specifications in the form of concepts and a general purpose interface for mapping key values to objects
    • variant - A safe and generic stack-based object container that allows for the efficient storage of and access to an object of a type that can be chosen from among a set of types that must be specified at compile time.
  • Correctness and testing
    • concept check - Allows for the enforcement of actual template parameter requirements (concepts)
    • static assert - Compile time assertion support
    • Boost Test Library - A matched set of components for writing test programs, organizing tests into test cases and test suites, and controlling their runtime execution
  • Data structures
  • Function objects and higher-order programming
    • bind and mem_fn - General binders for functions, function objects, function pointers and member functions
    • function - Function object wrappers for deferred calls. Also, provides a generalized mechanism for callbacks
    • functional - Enhancements to the function object adapters specified in the C++ Standard Library, including:
    • hash - An implementation of the hash function object specified by the C++ Technical Report 1 (TR1). Can be used as the default hash function for unordered associative containers
    • lambda - In the spirit of lambda abstractions, allows for the definition of small anonymous function objects and operations on those objects at a call site, using placeholders, especially for use with deferred callbacks from algorithms.
    • ref - Provides utility class templates for enhancing the capabilities of standard C++ references, especially for use with generic functions
    • result_of - Helps in the determination of the type of a call expression
    • signals and slots - Managed signals and slots callback implementation
  • Generic programming
  • Graphs
  • Input/output
  • Interlanguage support (for Python)
  • Iterators
    • iterators
    • operators - Class templates that help with overloaded operator definitions for user defined iterators and classes that can participate in arithmetic computation.
    • tokenizer - Provides a view of a set of tokens contained in a sequence that makes them appear as a container with iterator access
  • Math and Numerics
  • Memory
    • pool - Provides a simple segregated storage based memory management scheme
    • smart_ptr - A collection of smart pointer class templates with different pointee management semantics
      • scoped_ptr - Owns the pointee (single object)
      • scoped_array - Like scoped_ptr, but for arrays
      • shared_ptr - Potentially shares the pointer with other shared_ptrs. Pointee is destroyed when last shared_ptr to it is destroyed
      • shared_array - Like shared_ptr, but for arrays
      • weak_ptr - Provides a "weak" reference to an object that is already managed by a shared_ptr
      • intrusive_ptr - Similared to shared_ptr, but uses a reference count provided by the pointee
    • utility - Miscellaneous support classes, including:
      • base from member idiom - Provides a workaround for a class that needs to initialize a member of a base class inside its own (i.e., the derived class') constructor's initializer list
      • checked delete - Check if an attempt is made to destroy an object or array of objects using a pointer to an incomplete type
      • next and prior functions - Allow for easier motion of a forward or bidirectional iterator, especially when the results of such a motion need to be stored in a separate iterator (i.e., should not change the original iterator)
      • noncopyable - Allows for the prohibition of copy construction and copy assignment
      • addressof - Allows for the acquisition of an object's real address, bypassing any overloads of operator&(), in the process
      • result_of - Helps in the determination of the type of a call expression
  • Miscellaneous
  • Parsers
  • Preprocessor metaprogramming
  • String and text processing
    • lexical_cast - Type conversions to/from text
    • format - Type safe argument formatting according to a format string
    • iostreams - C++ streams and stream buffer assistance for new sources/sinks, filters framework
    • regex - Support for regular expressions
    • Spirit - An object-oriented recursive-descent parser generator framework
    • string algorithms - A collection of various algorithms related to strings
    • tokenizer - Allows for the partitioning of a string or other character sequence into tokens
    • wave - Standards conformant implementation of the mandated C99 / C++ pre-processor functionality packed behind an easy to use interface
  • Template metaprogramming
    • mpl - A general purpose high-level metaprogramming framework of compile-time algorithms, sequences and metafunctions
    • static assert - Compile time assertion support
    • type traits - Templates that define the fundamental properties of types
  • Workarounds for broken compilers

The current Boost release contains 87 individual libraries, including the following three:

Linear algebra – uBLAS

Boost includes the uBLAS linear algebra library, with BLAS support for vectors and matrices. uBlas supports a wide range of linear algebra operations, and has bindings to some widely used numerics libraries, such as ATLAS, BLAS and LAPACK.

  • Example showing how to multiply a vector with a matrix:
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
#include <iostream>
 
using namespace boost::numeric::ublas;
 
/* "y = Ax" example */
int main () 
{
      vector<double> x(2);
      x(0) = 1; x(1) = 2;
 
      matrix<double> A(2,2);
      A(0,0) = 0; A(0,1) = 1;
      A(1,0) = 2; A(1,1) = 3;
 
      vector<double> y = prod(A, x);
 
      std::cout << y << std::endl;
      return 0;
}

Generating random numbers – Boost.Random

Boost provides distribution-independent pseudorandom number generators and PRNG-independent probability distributions, which are combined to build a concrete generator.

#include <boost/random.hpp>
#include <ctime>
 
using namespace boost;
 
double SampleNormal (double mean, double sigma)
{
    // Create a Mersenne twister random number generator
    // that is seeded once with #seconds since 1970
    static mt19937 rng(static_cast<unsigned> (std::time(0)));
 
    // select Gaussian probability distribution
    normal_distribution<double> norm_dist(mean, sigma);
 
    // bind random number generator to distribution, forming a function
    variate_generator<mt19937&, normal_distribution<double> >  normal_sampler(rng, norm_dist);
 
    // sample from the distribution
    return normal_sampler();
}

See Boost Random Number Library for more details.

Multi-threading – Boost.Thread

Example code that demonstrates creation of threads:

#include <boost/thread/thread.hpp>
#include <iostream>
 
using namespace std; 
 
void hello_world() 
{
  cout << "Hello world, I'm a thread!" << endl;
}
 
int main(int argc, char* argv[]) 
{
  // start a new thread that calls the "hello_world" function
  boost::thread my_thread(&hello_world);
  // wait for the thread to finish
  my_thread.join();
 
  return 0;
}

Cross-Platform development

The section is to introduce programmer to programming with the aim of portability across several OSs environments. In today’s world it does not seem appropriate to constrain applications to a single operating system or computer platform, and there is an increasing need to address programming in a cross platform manner.

Darwin and Mac OS X

Both Mac OS X version 10.x.x and "pure" Darwin systems can be to as Darwin, since Mac OS X is actually a superset of Darwin.

The Windows 32 API

Win32 API is a set of functions defined in the Windows OS, in other words it is the Windows API, this is the name given by Microsoft to the core set of application programming interfaces available in the Microsoft Windows operating systems. It is designed for usage by C/C++ programs and is the most direct way to interact with a Windows system for software applications. Lower level access to a Windows system, mostly required for device drivers, is provided by the Windows Driver Model in current versions of Windows.

One can get more information about the API and support from Microsoft itself, using the MSDN Library ( http://msdn.microsoft.com/ ) essentially a resource for developers using Microsoft tools, products, and technologies. It contains a bounty of technical programming information, including sample code, documentation, technical articles, and reference guides. You can also check out Wikibooks Windows Programming book for some more detailed information that goes beyond the scope of this book.

A software development kit (SDK) is available for Windows, which provides documentation and tools to enable developers to create software using the Windows API and associated Windows technologies. ( http://www.microsoft.com/downloads/ )

History

The Windows API has always exposed a large part of the underlying structure of the various Windows systems for which it has been built to the programmer. This has had the advantage of giving Windows programmers a great deal of flexibility and power over their applications. However, it also has given Windows applications a great deal of responsibility in handling various low-level, sometimes tedious, operations that are associated with a Graphical user interface.

Charles Petzold, writer of various well read Windows API books, has said: "The original hello-world program in the Windows 1.0 SDK was a bit of a scandal. HELLO.C was about 150 lines long, and the HELLO.RC resource script had another 20 or so more lines. (...) Veteran C programmers often curled up in horror or laughter when encountering the Windows hello-world program.". A hello world program is a often used programming example, usually designed to show the easiest possible application on a system that can actually do something (i.e. print a line that says "Hello World").

Over the years, various changes and additions were made to the Windows Operating System, and the Windows API changed and grew to reflect this. The windows API for Windows 1.0 supported less then 450 function calls, where in modern versions of the Windows API there are thousands. In general, the interface has remained fairly consistent however, and a old Windows 1.0 application will still look familiar to a programmer who is used to the modern Windows API.

A large emphasis has been put by Microsoft on maintaining software backwards compatibility. To achieve this, Microsoft sometimes went as far as supporting software that was using the API in a undocumented or even (programmatically) illegal way. Raymond Chen, a Microsoft developer who works on the Windows API, has said that he "could probably write for months solely about bad things apps do and what we had to do to get them to work again (often in spite of themselves). Which is why I get particularly furious when people accuse Microsoft of maliciously breaking applications during OS upgrades. If any application failed to run on Windows 95, I took it as a personal failure."

Variables and Win32

Win32 uses an extended set of data types, using C's typedef mechanism These include:

BYTE - unsigned 8 bit integer, DWORD - 32 bit unsigned integer, LONG - 32 bit signed integer, LPDWORD - 32 bit pointer to DWORD, LPCSTR - 32 bit pointer to constant character string, LPSTR - 32 bit pointer to character string, UINT - 32 bit unsigned int, WORD - 16 bit unsigned int, HANDLE - opaque pointer to system data.

Of course standard data types are also available when programming with Win32 API.

Windows Libraries (DLLs)

In Windows, library code exists in a number of forms, and can be accessed in various ways.

Normally, the only thing that is needed is to include in the appropriate header file on the source code the information to the compiler, and linking to the .lib file will occur during the linking phase.

This .lib file either contains code which is to be statically linked into compiled object code or contains code to allow access to a dynamically link to a binary library(.DLL) on the system.

It is also possible to generate a binary library .DLL within C++ by including appropriate information such as an import/export table when compiling and linking.

DLLs stand for Dynamic Link Libraries, the basic file of functions that are used in some programs. Many newer C++ IDEs such as Dev-CPP support such libraries.

Common libraries on Windows include those provided by the Platform Software Development Kit, Microsoft Foundation Class and a C++ interface to .Net Framework assemblies.

Although not strictly use as library code, the Platform SDK and other libraries provide a set of standardized interfaces to objects accessible via the Common Object Model implemented as part of Windows.

TODO

TODO
Add Registry, IO (Input/Output), Security, Processes and Threads

API conventions and Win32 API Functions (by focus)

Time

Time measurement has to come from the OS in relation to the hardware it is run, unfortunately most computers don't have a standard high-accuracy, high-precision time clock that is also quick to access.

MSDN Time Functions ( http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/time_functions.asp )

Timer Function Performance ( http://developer.nvidia.com/object/timer_function_performance.html )

GetTickCount has a precision (dependent on your timer tick rate) of one millisecond, its accuracy typically within a 10-55ms expected error, the best thing is that it increments at a constant rate. (WaitForSingleObject uses the same timer).

GetSystemTimeAsFileTime has a precision of 100-nanoseconds, its accuracy is similar to GetTickCount.

QueryPerformanceCounter can be slower to obtain but has higher accuracy, uses the HAL (with some help from ACPI) a problem with it is that it can travel back in time on over-clocked PCs due to garbage on the LSBs, note that the functions fail unless the supplied LARGE_INTEGER is DWORD aligned.

Performance counter value may unexpectedly leap forward ( http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q274323& )

timeGetTime (via winmm.dll) has a precision of ~5ms.

File System

MakeSureDirectoryPathExists (via Image Help Library - IMAGHLP.DLL, #pragma comment( lib, "imagehlp.lib" ), #include <imagehlp.h> ) creates directories, only useful to create/force the existence of a given dir tree or multiple directories, or if the linking is already present, note that it is single threaded.

TODO

TODO
Add Basics in building "windows", Window eventhandling, Resources

Resources


Resources are perhaps one of the most useful elements of the WIN32 API, they are how we program menu's, add icons, backgrounds, music and many more aesthetically pleasing elements to our programs.

They are defined in a .rc file (resource c) and are included at the linking phase of compile. Resource files work hand in hand with a header file (usually called resource.h) which carries the definitions of each ID.

For example a simple RC file might contain a menu:

////////////// IDR_MYMENU MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&About", ID_FILE_ABOUT
MENUITEM "E&xit", ID_FILE_EXIT
END

POPUP "&Edit"
BEGIN
// Insert menu here :p
END

POPUP "&Links"
BEGIN
MENUITEM "&Visit Lukem_95's Website", ID_LINK_WEBSITE
MENUITEM "G&oogle.com", ID_LINK_GOOGLE
END
END
//////////////

And the corresponding H file:

#define IDR_MYMENU 9000
#define ID_FILE_EXIT 9001
#define ID_LINK_WEBSITE 9002
#define ID_LINK_GOOGLE 9003
#define ID_FILE_ABOUT 9004

Network

Network applications are often built in C++ on windows utilizing the WinSock API functions.

WIN32 API Wrappers

Since the win32 API is C based and also a moving target and since some alterations are done in each OS version some wrappers were created, in this section you will find some of the approaches available to facilitate the use of the API in a C++ setup and provide abstraction from the low level stuff with higher level implementations of common needed features, dealing with the GUI, complex controls even communications and database access.

Microsoft Foundation Classes (MFC); 
a C++ library for developing Windows applications and UI components. Created by Microsoft for the C++ Window's Programmer as an abstraction layer for the Win32 API, the use of the new STL enabled capabilities is scarce on the MFC. It's also compatible with Windows CE (the pocket PC version of the OS). MFC was designed to use the Document-View pattern a variant of the Model View Controller (MVC) pattern.
More info about MFC can be obtained on the Windows Programming Wikibook.
Windows Template Library (WTL); 
a C++ library for developing Windows applications and UI components. It extends ATL (Active Template Library) and provides a set of classes for controls, dialogs, frame windows, GDI objects, and more. This library is not supported by Microsoft Services (but is used internally at MS and available for download at MSDN).
Win32 Foundation Classes (WFC); 
(http://www.samblackburn.com/wfc/) a library of C++ classes that extend Microsoft Foundation Classes (MFC) to do NT specific things.
Borland Visual Component Library (VCL); 
a Delphi/C++ library for developing Windows applications, UI components and different kinds of service applications. Created by Borland as an abstraction layer for the Win32 API, but also implementing many non-visual, and non windows-specific objects, like AnsiString class for example.

Generic wrappers

Generic GUI/API wrappers are programming libraries that provide an uniform platform neutral interface (API) to the operating system regardless of underlying platform. Such libraries greatly simplify development of cross-platform software.

Cross-platform programming is more than only GUI programming. More details needed.

Here is some cross-platform GUI toolkit:

  • Gtkmm - an interface for the C GUI library GTK+. It is not cross-platform by design, but rather mutli-platform i.e. can be used on many platform.
  • Qt (http://www.qtsoftware.com/) - a cross-platform (Qt is the basis for the KDE desktop environment supports X Window System (Unix/X11), Apple Mac OS X, and Microsoft Windows NT/9x/2000/XP), it is an object-oriented application development framework, widely used for the development of GUI programs (in which case it is known as a widget toolkit), and for developing non-GUI programs such as console tools and servers. Used in numerous commercial applications such as Google Earth, Skype for Linux and Adobe Photoshop Elements. Released under the LGPL or a commercial license.
  • WxWidgets (http://www.wxwindows.org/) - a widget toolkit for creating graphical user interfaces (GUIs) for cross-platform applications on Win32, Mac OS X, GTK+, X11, Motif, WinCE, and more using one codebase. It can be used from languages such as C++, Python, Perl, and C#/.NET. Unlike other cross-platform toolkits, wxWidgets applications look and feel native. This is because wxWidgets uses the platform's own native controls rather than emulating them. It's also extensive, free, open-source, and mature. wxWidgets is more than a GUI development toolkit it provides classes for files and streams, application settings, multiple threads, interprocess communication, database access and more.
  • FLTK The "Fast, Light Toolkit"

Using a wrapper as a portability layer will offer applications some or all following benefits:

  • Independence from the hardware.
  • Independence from the Operating System.
    • Independence from changes made to specific releases.
    • Independence from API styles and error codes.

Multitasking

Multitasking is a method by which multiple tasks (also known as processes), share common processing resources such as a CPU.

A computer with a single CPU, will only run one task, where running means that in a specific point in time, the CPU is actively executing instructions for that process. A single CPU systems using scheduling can archive multitasking by which a task may be run at any given time, and then another waiting task gets a turn.

The act of reassigning a CPU from one task to another one is called a context switch. When context switches occur frequently enough the illusion of parallelism is achieved.

Even on computers with more than one CPU (called multiprocessor machines), multitasking allows many more tasks to be run than there are CPUs.

Operating systems may adopt one of many different scheduling strategies, which generally fall into the following categories:

  • In multiprogramming systems, the running task keeps running until it performs an operation that requires waiting for an external event (e.g. reading from a tape) or until the computer's scheduler forcibly swaps the running task out of the CPU. Multiprogramming systems are designed to maximize CPU usage.
  • In time-sharing systems, the running task is required to relinquish the CPU, either voluntarily or by an external event such as a hardware interrupt. Time sharing systems are designed to allow several programs to execute apparently simultaneously. The term time-sharing used to define this behavior is no longer in use, having been replaced by the term multitasking.
  • In real-time systems, some waiting tasks are guaranteed to be given the CPU when an external event occurs. Real time systems are designed to control mechanical devices such as industrial robots, which require timely processing.

Multitasking has already been successfully integrated into current Operating Systems, most computers in use today supports running several processes at a time, the recent innovation on the field are distributed computing and multi-core or chip multiprocessors (CMPs) computing, each with their specific limitations but with similar objectives and all covering the problem of concurrent programming.

Processes

Processes are independent execution units that contain their own state information, use their own address spaces, and only interact with each other via interprocess communication mechanisms (IPC).

Child Process

A child process is a computer process created by another process (the parent process), inheriting most of the parent attributes, such as opened files. Each process may create many child processes but will have at most one parent process; if a process does not have a parent this usually indicates that it was created directly by the kernel.

In UNIX, a child process is in fact created (using fork) as a copy of the parent. The child process can then overlay itself with a different program (using exec) as required. The very first process, called init, is started by the kernel at booting time and never terminates; other parentless processes may be launched to carry out various daemon tasks in userspace. Another way for a process to end up without a parent is if its parent dies, leaving an orphan process; but in this case it will shortly be adopted by init.

Inter-Process Communication (IPC)

IPC is generally managed by the operating system.

Shared Memory

Most of more recent OSs provide some sort of memory protection. In a Unix system, each process is given its own virtual address space, and the system, in turn, guarantees that no process can access the memory area of another. If an error occurs on a process only that process memory's contents can be corrupted.

With shared memory the need of enabling random-access to shared data between different processes is addressed. But declaring a given section of memory as simultaneously accessible by several processes raises the need for control and synchronization, since several processes might try to alter this memory area at the same time.

Multi-Threading

Unlike more modern languages like Java and C#, the C++ standard does not include specifications or built in support for multi-threading. Threading must therefore be implemented using special threading libraries, which are often platform dependent.

Some popular threads libraries for C++ include

  • Boost - This package includes several libraries, one of which is threads (concurrent programming). the boost threads library is not very full featured, but is complete, portable, robust and in the flavor of the C++ standard. Uses the boost license that is similar to the BSD license.
  • Intel® Threading Building Blocks (TBB) (http://www.threadingbuildingblocks.org/) offers a rich approach to expressing parallelism in a C++ program. The library helps you take advantage of multi-core processor performance without having to be a threading expert. Threading Building Blocks is not just a threads-replacement library. It represents a higher-level, task-based parallelism that abstracts platform details and threading mechanism for performance and scalability and performance. It is an open source project under the GNU General Public License version two (GPLv2) with the runtime exception.
  • Zthreads [1] - Another popular, portable thread abstraction library. This library is more feature rich, and deals only with concurrency.
  • ACE [2] - Another toolkit which includes a portable threads abstraction along with many many other facilities, all rolled into one library.

This list is not intended to be complete.

Of course, you can access the full POSIX and Windows C language threads interface from C++. So why bother with a library on top of that? The reason is that things like locks are resources that are allocated, and C++ provides abstractions to make managing these things easier. For instance, boost::scoped_lock<> uses object construction/destruction to insure that a mutex is unlocked when leaving the lexical scope of the object. Classes like this can be very helpful in preventing deadlock, race conditions, and other problems unique to threaded programs. Also, these libraries enable you to write cross-platform multi-threading code, while using platform-specific function cannot.

Threads vs. Processes

Both threads and processes are methods of parallelizing an application, its implementation may differ from one operating system to another. A process has always one thread of execution, also known as the primary thread. In general, a thread is contained inside a process (in the address space of the process) and different threads of the same process share some resources while different processes do not.

Threads

Threads are by definition a coding construct and part of a program that enable it to fork (or split) itself into two or more simultaneously (or pseudo-simultaneously) running tasks.

The thread is the basic unit (the smallest piece of code) to which the operating system can allocate a distinct processor time (schedule) for execution, this means that threads in reality don't run concurrently but in sequence on any single core system.

The thread today is not only a key concurrency model supported by most if not all modern computers, programming languages, and operating systems but is it self at the core of hardware evolution, such as symmetric multiprocessors, understanding threads is now a necessity to all programmers.

Example

The CreateThread function creates a new thread for a process. The creating thread must specify the starting address of the code that the new thread is to execute. Typically, the starting address is the name of a function defined in the program code. This function takes a single parameter and returns a DWORD value. A process can have multiple threads simultaneously executing the same function.

The following example demonstrates how to create a new thread that executes the locally defined function, ThreadFunc.

DWORD WINAPI ThreadFunc( LPVOID lpParam )  
{ 
   char szMsg[80];
   wsprintf( szMsg, "ThreadFunc: Parameter = %d\n", *lpParam ); 
   MessageBox( NULL, szMsg, "Thread created.", MB_OK );
   return 0; 
} 
VOID main( VOID ) 
{ 
   DWORD dwThreadId, dwThrdParam = 1; 
   HANDLE hThread; 
   hThread = CreateThread( 
       NULL,                        // no security attributes 
       0,                           // use default stack size  
       ThreadFunc,                  // thread function 
       &dwThrdParam,                // argument to thread function 
       0,                           // use default creation flags 
       &dwThreadId);                // returns the thread identifier 
 
  // Check the return value for success. 
  if (hThread == NULL) 
     ErrorExit( "CreateThread failed." ); 
  CloseHandle( hThread );
}

For simplicity, this example passes a pointer to a DWORD value as an argument to the thread function. This could be a pointer to any type of data or structure, or it could be omitted altogether by passing a NULL pointer and deleting the references to the parameter in ThreadFunc. It is risky to pass the address of a local variable if the creating thread exits before the new thread, because the pointer becomes invalid. Instead, either pass a pointer to dynamically allocated memory or make the creating thread wait for the new thread to terminate. Data can also be passed from the creating thread to the new thread using global variables. With global variables, it is usually necessary to synchronize access by multiple threads.

Thread quantum
Thread Local Variables
Thread Synchronization

The synchronization can be defined in several steps the first is the process lock, were a process is made to halt execution due to find a protected resource locked, there is a cost for locking especially if the lock last for too long.

Obviously there is a performance hit if any of the synchronization mechanisms is heavily used.

Critical Section
TODO

TODO
Guard or monitor sections ?

  • Mutex, a synchronization facility supplied by operating systems (not the CPU).
  • Semaphore, a yielding synchronization object, can be used to synchronize several threads. The most commonly used method for synchronization
  • Spinlock, a busy-wait synchronization object, used as a substitute for Mutexes. An implementation of inter-thread locking using machine dependent assembly instructions (such as test-and-set). Were a thread simply waits in a loop (spins) that repeatedly checks if the lock becomes available (busy wait) this is why Spinlocks perform better, if locked for a short period of time. Never used on a single-CPU machine
Suspend and Resume
Synchronizing on Objects
Cooperative vs. Preemptive Threading

Deadlock

A deadlock happens whenever there is a blocking operation that results in a never-ending waiting cycle among concurrent threads.

Worker Thread

This distinction made so to impart the idea that the referenced thread doesn't interact with the user interface directly (doesn't wait for actions or exchanges information with it).

User Interface Thread

This type of distinction is reserved to indicate that the particular thread implements a message map to respond to events and messages generated by user inputs as he interacts with the application. This is especially common when working with the Windows platform (Win32 API) because of the way it implements message pumps.

Fibers

TODO

TODO
To extend

Exploiting parallelism

As the need for concurrent programming tends to increase due to the way today's hardware evolve, we as programmers are pressed to create and introduced new programming models that ease the complicated process of dealing with the old thread model in a way to preserve development time but abstract the problem.

TODO

TODO
To extend

OpenMP

TODO

TODO
To extend

Software Internationalization

In Software, Internationalization and localization is how the adapting computer software for other locations, nations or cultures, meaning specifically those that are non-native to the programmer(s) or the primary user group

In specific, Internationalization deals with the process of designing a software application in a way that it can be configured or adapted to work with various languages and regions without heavy changes to the code base. On the other hand Localization deals with the process of enabling the configuration or auto adaptation of the software to a specific region, timezone or language by adding locale-specific components and translating text.

Text Encoding

Text, in particular the characters are used to generate readable text consists on the use of a character encoding scheme that pairs a sequence of characters from a given character set (sometimes referred to as code page) with something else, such as a sequence of natural numbers, octets or electrical pulses, in order to facilitate the use of its digital representation.

A easy to understand example would be Morse code, which encodes letters of the Latin alphabet as series of long and short depressions of a telegraph key; this is similar to how ASCII, encodes letters, numerals, and other symbols, as integers.

In earlier days of computing, the introduction of coded character sets such as ASCII (1963) and EBCDIC (1964) began the process of standardization. The limitations of such sets soon became apparent, and a number of ad-hoc methods developed to extend them. The need to support multiple writing systems (Languages), including the CJK family of East Asian scripts, required support for a far larger number of characters and demanded a systematic approach to character encoding rather than the previous ad hoc approaches.

What's this about UNICODE?

TODO

TODO
Complete this section

UTF-8

UTF-8 is a variable-length encoding of unicode. It uses 1 to 4 bytes for each character. As a UTF-8 stream doesn't contain '\0', you may use it directly in your existing c++ code without any porting. (except when counting the 'actual' number of character in it)

UTF-16

Optimizations

Optimization can be regarded as a directed effort to increase the performance of something, an important concept in engineering, in the particular in this case we will cover Software engineering. We will deal with specific computational tasks and best practices to reduce resources utilizations, not only of system resources but also of programmers and users, all based in optimal solutions evolved from the empirical validating of hypothesis and logical steps.

All optimization steps taken should have as a goal the reduction of requirements and the promotion of the program objectives, in doubt all claims can only be substantiated by doing a profiling the given problem and the applied solution.

Optimization is often a topic of discussion among programmers and not all conclusion may be consensual, since they are very closely related to the goals, the programmer experience and dependent of specific setups. The level of optimization will depend directly from actions and decisions the programmer makes. Those can be simple things, from simple coding practices to the selection of the tools one choses to use to create the program. Even selecting the compiler will have some impact.

Code

One of the safest ways of optimization is to reduce complexity, ease organization and structure and at the same time evading code bloat. This requires the capacity to plan without losing track of future needs, in fact it is a compromise the programmer makes between a multitude of factors.

Code optimization techniques, fall into the categories of:

  • High Level Optimization
    • Algorithmic Optimization (Mathematical Analysis)
    • Simplification
  • Low Level Optimization
    • Loop Unrolling
    • Strength Reduction
    • Duff's Device
    • Clean Loops

KISS

The "keep it simple, stupid" (KISS) principle, calls for giving simplicity a high priority in development. It is very similar to a maxim from Albert Einstein's that states, "everything should be made as simple as possible, but no simpler.", the difficulty for many adopters have is to determine what level of simplicity should be maintained. In any case, analysis of basic and simpler system is always easier, removing complexity will also open the door for code reutilization and a more generic approach to tasks and problems.

The right data in the right container

One should store the appropriate data structure in the appropriate container, prefer storing pointers to objects rather than the objects themselves, use "smart" pointers (see the Boost library) and don't attempt to store auto_ptr<> in STL containers, it is not allowed by the Standard, but some implementations are known to incorrectly allow it.

Avoid removing and inserting elements in the middle of a container, doing it at the end of the container has less overhead. Use STL containers when the number of objects is unknown; use static array or buffer when it is known. This requires the understanding of not only each container, but its O(x) guarantees.

Take as an example the STL containers on the issue of using (myContainer.empty()) versus (myContainer.size() == 0), it is important to understand that depending on the container type or its implementation, the size member function might have to count the number of objects before comparing it to zero. This is very common with list type containers.

While the STL attempts to provides optimal solutions to general cases, if performance doesn't match your requirements think about writing your own optimal solution for your case, maybe a custom container (probably based on vector) that doesn't call individual object destructors and uses custom allocators that avoid the delete time overhead.

Using pre-allocation of memory can provide some speed gains and be as simple remember to use the STL vector<T>::reserve() if permitted. Optimize the use system's memory and the target hardware. In todays systems, with virtual memory, threads and multiple-cores (each with its own cache) where I/O operations on the main memory and the amount of time spent moving it around, can slow things down. This can become a performance bottleneck. Instead opt for array-based data structures (cache-coherent data structures), like the STL vector, because data is stored contiguously in memory, over pointer-linked data structures as in linked lists. This will avoid "death by swapping", as the program needs to access highly fragmented data, and will even help the memory pre-fetch that most modern processors do today.

Whenever possible avoid returning containers by value, pass containers by reference.

Code reutilization

Optimization is also reflected on the effectiveness of a code. If you can use an already existing code base/framework that a considerable number of programmers have access to, you can expect it to be less buggy and optimized to solve your particular need.

Some of these code repositories are available to programmers as libraries. Be careful to consider dependencies and check how implementation is done: if used without considerations this can also lead to code bloat and increased memory footprint, as well as decrease the portability of the code. We will take a close look at them in the Libraries Section of the book.

To increase code reutilization you will probably fragment the code in smaller sections, files or code, remember to equate that more files and overall complexity also increases compile time.

ASM

If portability is not a problem and you are proficient with assembler you can use it to optimize computational bottlenecks, even looking at the output of a disassembler will often help looking for ways to improve it. Using ASM in your code brings to the table some other problems (maintainability for instance) so use it at a last resort in you optimization process, and if you use it be sure to document what you have done well.

The x86 Disassembly Wikibook provides some optimization examples using x86 ASM code.

Reduction of compile time

Some projects may take a long time to compile. To reduce the time it takes to finish compiling the first step is to check if you have the any Hardware deficiencies. You may be low in resources like memory or just have a slow CPU, even having your HD with a high level of fragmentation can increase compile time.

On the other side, problems may not be due to hardware limitations but in the tools you use, check if you are using the right tools for the job at hand, see if you have the latest version, or if do, if that is what is causing trouble, some incompatibilities may result from updates. In compilers new is always better, but you should check first what has changed and if it serves your purposes.

Experience tells that most likely if you are suffering from slow compile times, the program you are trying to compile was probably poorly designed, check the structure of object dependencies, the includes and take some the time to structure your own code to minimize re-compilation after changes if the compile time justifies it.

Use pre-compiled headers and external header guards this will reduce the work done by the compiler.

Compiler optimizations

Compiler optimization is the process of tuning the output of a compiler in an attempt to improve the operations the programmer has requested, so to minimize or maximize some attribute of an compiled program while ensuring the result is identical.

The most common optimizations available to the programmer fall into three categories:

  • Speed; improving the runtime performance of the generated object code. This is the most common optimization
  • Space; reducing the size of the generated object code
  • Safety; reducing the possibility of data structures becoming corrupted (for example, ensuring that an illegal array element is not written to)

Unfortunately, many "speed" optimizations make the code larger, and many "space" optimizations make the code slower -- this is known as the space-time tradeoff.

Run time

As we have seen before runtime is the duration of a program execution, from beginning to termination. This is were all resources needed to run the compiled code are allocated and hopefully released, this is the final objective of any program to be executed, as such it should be the target for ultimate optimizations.

Memory footprint

In the past computer memory has been expensive and technologically limited in size, and scarce resource for programmers. Large amounts of ingenuity was spent in implement complex programs and process huge amounts of data using as little as possible of this resource. Today, modern systems contain enough memory for most usages but capacity demands and expectations have increased as well; as such, techniques to minimize memory usage may still be essential.

Remember to use swap() on std::vector (or deque).

When attempting to reduce reduce (or zero) the size of a vector or deque using the swap(), on a standard container of that type, will guarantee that the memory is released and no overhead buffer for growth is used. It will also avoid the fallacy of using erase() or reserve() that will not reduce the memory footprint.

Lazy initialization

It is always needed to maintain the balance between the performance of the system and the resource consumption. Lazy instantiation is one memory conservation mechanism, by which the object initialization is deferred until it is required.

Look at the following example:

#include <iostream> 
 
class Wheel {
        int speed;
    public:
        int getSpeed(){
            return speed;
        }
        void setSpeed(int speed){
            this->speed = speed;
        }
};
 
class Car{
    private:
        Wheel wheel;
    public:
        int getCarSpeed(){
            return wheel.getSpeed();
        }
        char *getName(){
            return "My Car is a Super fast car";
        }
};
 
int main(){
    Car myCar;
    std::cout << myCar.getName();
}

Instantiation of class Car by default instantiates the class Wheel. The purpose of the whole class is to just print the name of the car. Since the instance wheel doesn't serve any purpose, initializing it is a complete resource waste.

It is better to defer the instantiation of the un-required class until it is needed. Modify the above class Car as follows:

class Car{
    private:
        Wheel *wheel;
    public:
        Car() {
            wheel=NULL; // a better place would be in the class constructor initialization list
        }
        ~Car() {
             if (wheel) {
                 delete wheel;
             }
        }
        int getCarSpeed(){
            if(wheel == NULL){
                wheel = new Wheel(); 
            }
            return wheel->getSpeed();
        }
        char *getName(){
            return "My Car is a Super fast car";
        }
};

Now the Wheel will be instantiated only when the member function getCarSpeed() is called.

I/O reads and writes

TODO

TODO
Delayed writes, read ahead, how the OS processes I/O requests...

Further reading


Modeling Tools

Long gone are the days when you had to do all software designing planing with pencil and paper, it's known that bad design can impact the quality and maintainability of products, affecting time to market and long term profitability of a project.

The solution seems to be CASE and modeling tools which improve the design quality and help to implement design patterns with ease that in turn help to improve design quality, auto documentation and the shortening the development life cycles.

UML (Unified Modeling Language)

Since the late 80s and early 90s, the software engineering industry as a whole was in need of standardization, with the emergence and proliferation of many new competing software design methodologies, concepts, notations, terminologies, processes, and cultures associated with them, the need for unification was self evident by the sheer number of parallel developments. A need for a common ground on the representation of software design was badly needed and to archive it a standardization of geometrical figures, colors, and descriptions.

The UML (Unified Modeling Language) was specifically created to serve this purpose and integrates the concepts of Booch (Grady Booch is one of the original developers of UML and is recognized for his innovative work on software architecture, modeling, and software engineering processes), OMT, OOSE, Class-Relation and OOramand by fusing them into a single, common and widely usable modeling language tried to be the unifying force, introducing a standard notation that was designed to transcend programming languages, operating systems, application domains and the needed underlying semantics with which programmers could describe and communicate. With it's adoption in November 1997 by the OMG (Object Management Group) and it's support it has become an industry standard. Since then OMG has called for information on object-oriented methodologies, that might create a rigorous software modeling language. Many industry leaders had responded in earnest to help create the standard, the last version of UML (v2.0) was released in 2004.

UML is still widely used by the software industry and engineering community. In later days a new awareness has emerged (commonly called UML fever) that UML per se has limitations and is not a good tool for all jobs. Careful study on how and why it is used is needed to make it useful.

Chapter Summary

  1. Resource Acquisition Is Initialization (RAII) Development stage: 50% (as of Oct 17, 2005)
  2. Garbage Collection Development stage: 50% (as of Jan 19, 2008)
  3. Design Patterns Development stage: 50% (as of Jan 1, 2006) - Creational, Structural and Behavioral patterns.
  4. Libraries Development stage: 25% (as of ) - APIs vs Frameworks and Static and Dynamic Libraries.
  5. Boost Library Development stage: 25% (as of Sep 20, 2005)
  6. Cross-Platform Development Development stage: 25% (as of 17 October 2007)
    1. Win32 (aka WinAPI) Development stage: 25% (as of Sep 20, 2005) - including Win32 Wrappers.
    2. Cross Platform Wrappers Development stage: 25% (as of Sep 20, 2005)
    3. Multitasking Development stage: 25% (as of Sep 20, 2005)
  7. Software Internationalization Development stage: 00% (as of )
    1. Text Encoding Development stage: 00% (as of )
  8. Optimizing Your Programs Development stage: 25% (as of May 12, 2006)
  9. Unified Modeling Language (UML) Development stage: 50% (as of Sep 20, 2005)