Core Principles

Object-Oriented Programming (OOP) is a programming paradigm based on the concept of “objects”, which can contain data, in the form of fields (often known as attributes or properties), and code, in the form of procedures (often known as methods). A key feature of OOP is the concept of class and instance. Here’s a breakdown of its core principles:

Classes and Objects

  • Class: A blueprint for creating objects (a particular data structure), providing initial values for state (member variables or attributes), and implementations of behavior (member functions or methods).
  • Object: An instance of a class. Each object can have unique attributes and behaviors as defined by its class.

Encapsulation

POO – Encapsulamiento
  • This principle is about bundling the data (attributes) and the methods that operate on the data into a single unit or class. It also involves restricting direct access to some of an object’s components, which is a means of preventing accidental interference and misuse of the methods and data.
  • In C++, encapsulation helps us keep related data and functions together, which makes our code cleaner and easy to read.
  • Data hiding is a way of restricting the access of our data members by hiding the implementation details.

Access Modifiers

  • public members (including base classes) can be accessed by
    • The current class
    • Derived classes
    • Free functions
    • Unrelated classes
  • protected members (including base classes) can be accessed by
    • The current class
    • Derived classes
  • private members (including base classes)
    • The current class

Specifiers apply to all following members

C++
class MyClass {
    public:
        MyClass() = default;
        int number = 2;
    private:
        double doubleNumber = 3.2;
};

Friend

  • Functions, classes, and templates can be declared as friends
  • friends can access anything of the related class
  • Friendship is the closest relationship a class can have and bleaks all encapsulations
  • Friendship is probably best avoided because of this.

Run in Repl.it https://repl.it/join/zovqdpto-maikolguzman

C++
#include <iostream>
using namespace std;

class Distance {
    private:
        int meter;
        
        // friend function
        friend int addFive(Distance distance) {
          //accessing private members from the friend function
          distance.meter += 5;
          return distance.meter;
        }

    public:
        Distance() : meter(0) {}
        
};

int main() {
    cout << "Welcome to the UNA!" << std::endl;  // display message
    Distance distance;
    cout << "Distance: " << addFive(distance) << std::endl;
    return 0;
}

Example

Inheritance

POO – Herencia
  • Inheritance allows a new class to adopt the properties and methods of an existing class. The new class (derived or child class) inherits attributes and behaviors from the old class (base or parent class) and can introduce its own.
  • The derived class inherits the properties and characteristics from the base class and can have additional features of its own
  • Inheritance is one of the most important feature of Object Oriented Programming.
C++
class Animal {
    // eat() function
    // sleep() function
};

class Dog : public Animal {
    // bark() function
};

Multiple Inheritance

  • Be aware of ambiguous access
  • Use explicit namespaces to resolve ambiguities
  • You cannot inherit from the same class twice
  • You can override the same virtual member from multiple base classes.

Run in Repl.it: https://repl.it/@MaikolGuzman/multi-inheritance-01-basic

C++
#include <iostream>  // allows program to output data to the screen
struct Base1 {
  void doSomething(int num) {
    std::cout << "INT - Base 1 ::doSomething(" << num << ")\n" << std::endl;
  }
};
struct Base2 {
  void doSomething(int num) {
    std::cout << "INT - Base 2 ::doSomething(" << num << ")\n" << std::endl;
  }
};
struct Derived : Base1, Base2 {
};
// function main begins program execution
int main(int argc, const char *argv[]) {
  std::cout << "Welcome to the UNA!" << std::endl;
  Derived derived;
  derived.Base1::doSomething(1);
  derived.Base2::doSomething(2);
  
}  // end function main

Polymorphism

POO – Polimorfismo
  • Polymorphism permits objects to be treated as instances of their parent class rather than their actual class. This allows for flexibility – methods or functions can be written that don’t need to know the exact type of their arguments, making it possible to use objects of different classes interchangeably as long as they follow a certain interface.
  • Polymorphism in C++ means the same entity (function or object) behaves differently in different scenarios.
  • Polymorphism means having many forms. A person can have different characteristics. As a Mom, at the same time am a mother, wife, and employee.
  • Types:
    • Compile Time
    • Runtime

Compile-time

  • In compile-time polymorphism, a function is called at the time of program compilation. We call this type of polymorphism as early binding or Static binding.
  • Function overloading and operator overloading is the type of Compile time polymorphism.
  • An example in C++ this can be represented by templates
  • Templates allow you to specify at compile time what types you want to work on
  • The standard library is full of example:
    • std::vector<T>;
    • std::list<T>;
    • std::map<T, U>;

Polymorphism is a core concept in object-oriented programming that allows objects of different classes to be treated as objects of a common superclass. It’s typically divided into two types in C++: overloading and overriding.

Overloading (Compile-time Polymorphism)

  • Definition: Overloading occurs when two or more functions in the same scope have the same name but different parameters. This can apply to both function overloading and operator overloading.
  • Characteristics: It’s resolved at compile time and it’s a way of implementing polymorphism that gives multiple meanings or functions to a single function or an operator.
  • Function overloading means one function can perform many tasks.
  • In C++, a single function is used to perform many tasks with the same name and different types of arguments.
  • In the function overloading function will call at the time of program compilation. It is an example of compile-time polymorphism.

Example of Overloading:

C++
class Print {
public:
    void show(int i) {
        cout << "Integer: " << i << endl;
    }
    void show(string s) {
        cout << "String: " << s << endl;
    }
};

int main() {
    Print p;
    p.show(5);         // Calls show(int)
    p.show("Hello");   // Calls show(string)
    return 0;
}

Operator Overloading

  • Operator overloading means defining additional tasks to operators without changing its actual meaning. We do this by using operator function.
  • The purpose of operator overloading is to provide a special meaning to the user-defined data types.
  • The advantage of Operators overloading is to perform different operations on the same operand.

Runtime

  • In a Runtime polymorphism, functions are called at the time the program execution. Hence, it is known as late binding or dynamic binding
  • Function overriding is a part of runtime polymorphism. In function overriding, more than one method has the same name with different types of the parameter list.
  • The standard library uses this in the exception library

Overriding (Run-time Polymorphism)

  • Definition: Overriding involves redefining a method of a base class in a derived class. This is used in situations where a subclass needs to modify or extend the behavior of that method.
  • Characteristics: It’s a feature that allows a subclass or child class to provide a specific implementation of a method that is already provided by one of its super-classes or parent classes.
  • New definition to base class function in the derived class.
  • It can be only possible in the derived class. In function overriding, we have two definitions of the same function, one in the superclass and one in the derived class.
  • Generally, this means virtual function and inheritance in C++
  • The decision about which function definition requires calling happens at runtime.

Example of Overriding:

C++
class Animal {
public:
    virtual void speak() {
        cout << "Some sound" << endl;
    }
};

class Dog : public Animal {
public:
    void speak() override {
        cout << "Bark" << endl;
    }
};

int main() {
    Animal* animal = new Dog();
    animal->speak();  // Calls Dog's speak method
    delete animal;
    return 0;
}

In this example, the speak method in the Dog class overrides the speak method in the Animal class. The virtual keyword in the base class (Animal) and override keyword in the derived class (Dog) are used to make the overriding explicit and more readable.

Abstraction

  • Abstraction involves hiding the complex reality while exposing only the necessary parts. It is a way of creating a simple model of a more complex entity, by only showing its essential features and hiding the details.

Object-oriented programming aims to implement real-world entities like inheritance, hiding, polymorphism, etc. in programming. It is a paradigm widely used for structuring complex software programs into manageable and reusable code.