Object Oriented Programming with C++

Object Oriented Programming (OOP) is something that is taught in many schools, probably not so useful for fresh starters. It's a method of programming that main purpose is to make code better to work with for maintenance programmers.

In OOP code is organized into classes or structures which associate data attributes with functions to be used with them. Object is an instance of class or structure and each instance can have unique attribute values.

There are several important topics related with OOP:

  • inheritance: mechanism for code reuse between classes
  • polymorphism: allows to access derived class using base class pointer, useful for functions that work on whole inheritance tree
  • encapsulation: hide class attribute & methods unless they are required by outside world
  • composition: store one or more object(s) inside another
  • virtual inheritance: C++ specific topic related to multiple inheritance
  • pure virtual (abstract) functions: functions that must be implemented in derived classes
  • abstract class: class with pure virtual methods
  • friend functions: functions which can access private class attributes
  • final classes: do not allow class to be derived from
  • class attributes: attributes which have the same value for each object

Simple class can be defined as follows:

#include <iostream>
#include <string>
using namespace std;

class scBaseTask
{
  // object attribute: each object have a copy of this variable with unique memory address
  bool running;

  public:
  // constructor: executed when new object is created (allocated in memory)
    scBaseTask():running(false) {}

  // destructor: executed when object is being destroyed (removed from memory)  
    virtual ~scBaseTask() {}

  // --- methods ---

  // virtual method can be replaced in derived class
    virtual std::string getName() { return "BaseTask"; }

  // non-virtual methods are not "replaced" in derived class, but still available  
    bool isRunning() { 
      return running; 
    }

    void start() { 
      if (!running) {
        cout << "Task [" << getName() << "] started\n";
        running = true; 
      }
    }

    void stop() { 
      if (running) {
        cout << "Task [" << getName() << "] stopped\n";
        running = false; 
      }
    }
};

// derived class, implements new version of "getName" method 
class scSortTask: public scBaseTask {
  public:
    virtual std::string getName() { return "SortTask"; }
};

int main() {
    scBaseTask baseTask;
    baseTask.start();
    if (baseTask.isRunning())
      cout << "baseTask is running\n";
    baseTask.stop();
    scSortTask sortTask;
    scBaseTask *baseTaskPtr = &sortTask;
    // test polymorphism: calls derived class' method on base class pointer
    cout << "Sort task returns name: " << baseTaskPtr->getName() << "\n";
    return 0;
}

Output:
Task [BaseTask] started
baseTask is running
Task [BaseTask] stopped
Sort task returns name: SortTask

Final classes

Classes for which you cannot implement derived classes. Useful for API classes.

version 1

class Temp
{
private:
  ~Temp() { };
  friend class FinalClass;
};

class FinalClass : virtual public Temp
{
. . .
};

version 2

// based on: API Design for C++, Martin Reddy
class NoBase 
{
    public:
      static NoBase* Create() { return new NoBase(); }
    private:
      NoBase();  
};

version 3 - with help of templates

template <typename T>
class MakeFinal
{
private:
  ~MakeFinal() { };
  friend T;
};

class FinalClass : virtual public MakeFinal<FinalClass>
{
};

Interfaces

See C++ interfaces.

Resources

See also

Share

follow