Object Oriented Programming (Oops) for Beginners || Detail Explained 🔥🔥

Class and Object

Object-oriented programming (OOP) is a computer programming model that organizes 
software design with classes and objects, rather than functions and logic.
Class :
-> A class is the building block that leads to Object-Oriented programming. It is a user-defined data
type, which holds its own data members and member functions, which can be accessed and used by
creating an instance of that class.

Object :
-> An Object is an instance of a Class. When a class is defined, no memory is allocated but when it is 
instantiated (i.e. an object is created) memory is allocated.

Code :

#include <bits/stdc++.h>
using namespace std;
class Person{
	// Access specifier
	public:

	// Data Members
	string name;

	// Member Functions()
	void printname(){
	   cout << "Person name is: " << name;
	}
};

int main() {

	// Declare an object of class Person
	Person obj1;

	// accessing data member
	obj1.name = "Thanos";

	// accessing member function
	obj1.printname();
	return 0;
}

Constructor & Destructor

Constructor :

-> Constructors are special class members which are called by the compiler every time an object of that 
class is instantiated. 
-> Constructors have the same name as the class and may be defined inside or outside the class 
definition.

There are 3 types of constructors:
1. Default constructors
2. Parameterized constructors
3. Copy constructors

1. Default Constructor: Default constructor is the constructor which doesn’t take any argument. It has
no parameters.

2. Parameterized Constructor: A constructor is called Parameterized Constructor when it accepts a
 specific number of parameters.
 
3.Copy Constructor: A copy constructor is a member function which initializes an object using another
object of the same class. 
Characteristics of the constructor:
1. Constructor has same name as the class itself.
2. Constructors don’t have return type.
3. A constructor is automatically called when an object is created.
4. It must be placed in public section of class.
5. If we do not specify a constructor, C++ compiler generates a default constructor for object (expects
   no parameters and has an empty body).
6. Constructors can be overloaded.
7. Constructor can not be declared virtual.

Code:

#include <bits/stdc++.h>
using namespace std;

class student
{
     string name;
     public:
       int age;
       bool gender;

    student()                        // Default Constructor
    {
      cout<<"Default Constructor"<<endl;
    }

    student(string s, int a, int b)  // parameterised constructor
    {
       name = s;
       age = a;
       gender = b;
       cout <<"parameterised constructor"<<endl;
    }

 student (student &p){               // copy constructer
    name = p.name;
    age = p.age;
    gender = p.gender;
    cout<<"copy constructer"<<endl;
 }

    void printinfo()
    {
        cout << "Name = ";
        cout << name << endl;
        cout << "Age = ";
        cout << age << endl;
        cout << "Gender = ";
        cout << gender << endl;
    }
};

int main()
{
    student w("sumeet", 20, 1);
    student c;
    c = w;
    c.printinfo();
    return 0;
}

Destructor :

-> A destructor is also a special member function as a constructor. Destructor destroys the class objects
created by the constructor. 
Destructor has the same name as their class name preceded by a tiled (~) symbol.

Characteristics of a destructor:-
1. Destructor is invoked automatically by the compiler when its corresponding constructor goes out of
   scope and releases the memory space that is no longer required by the program.
2. Destructor neither requires any argument nor returns any value therefore it cannot be overloaded.
3. Destructor  cannot be declared as static and const.
4. Destructor should be declared in the public section of the program.

Code:

#include <iostream>
using namespace std;

int count = 0;

class num{
public:
    num(){                        // Constructor
        count++;
        cout << "This is the time when constructor is called for object number" << count << endl;
    }

    ~num(){                       // Destructor
        cout << "This is the time when my destructor is called for object number" << count << endl;
        count--;
    }
};

Inheritance

-> Inheritance is one of the most important features of Object-Oriented Programming.
The capability of a class to derive properties and characteristics from another class is called Inheritance.

-> derived class (child) - the class that inherits from another class
-> base class (parent) - the class being inherited from

Example:
For instance, we are humans. We inherit certain properties from the class 'Human' such as the ability to
speak, breathe, eat, drink, etc

There are 5 Types of Inheritance in C++ :
1. Single Inheritance.
2. Multiple Inheritance.
3. Multilevel Inheritance.
4. Hierarchical Inheritance.
5. Hybrid Inheritance.

1. Single Inheritance

When a subclass(child) is inherited from a base class is called single inheritance.

Code :

#include<bits/stdc++.h>
using namespace std;

class A{
    public:
    void funcA(){
     cout<<"Inherited form class A"<<endl;
    }
};

class B : public A{
 public:
 void funcB(){
    cout<<"Inherited from class B"<<endl;
 }
};

int main(){
    B obj;
    obj.funcA();
    return 0;
}

2. Multipile Inheritance

when one subclass is inherited from more than one base class is called multiple inheritance.

Code :

#include<bits/stdc++.h>
using namespace std;

class A{
 public:
 void func(){
    cout<<"Inherited form class A"<<endl;
 }
};

class B{
 public:
 void func(){
    cout<<"Inherited from class B"<<endl;
 }
};

class C : public A, public B{

    public:
    void func(){
        cout<<"Inherited from class C"<<endl;
    }
};

int main()
{
    C obj;
    obj.A :: func();  // resolving ambiguity
    obj.B :: func();
    obj.func();
    return 0;
}

3. Multilevel Inheritance

In this type of inheriatance, a derived class is created from another derived class.

Code :

#include<bits/stdc++.h>
using namespace std;

class A{
  public:
  void funcA(){
    cout<<"Inhrited from class A"<<endl;
  }
};

class B : public A{
    public:
    void funcB() {
        cout<<"Inherted from class B"<<endl;
    }
};

class C : public B{
    public:
    void func() {
        cout<<"Inherited from class C"<<endl;
    }
};

int main()
{
    C obj;
    obj.funcB();
    return 0;
}

4. Hierarchical Inheritance

In this type of inheritance, more than one subclass is inherited from a single base class.

Code :

#include<bits/stdc++.h>
using namespace std;

class A{
    public:
    void func(){
        cout<<"Inherited from class A"<<endl;
    }
};

class B : public A{
    public:
    void funcB(){
        cout<<"Inherited from class B"<<endl;
    }
};

class C : public A{
    public:
    void funcC(){
        cout<<"Inherited from class C"<<endl;
    }
};

int main()
{
    C obj;
    obj.func();
    B obj2;
    obj2.funcB();
    obj2.func();
    return 0;
}

5. Hybrid Inheritance

Hybrid inheritance is a combination of multiple inheritance and multilevel inheritance.

There are 2 Ways to Avoid Ambiguity :

1. Avoiding ambiguity using the scope resolution operator: Using the scope resolution operator we can
   manually specify the path from which data member will be accessed.
2. Avoiding ambiguity using the virtual base class: Virtual classes are primarily used during multiple
   inheritance. To avoid, multiple instances of the same class being taken to the same class which later
   causes ambiguity.

Using scope resolution operator :

Code :

#include <iostream>
using namespace std;

class A{
public:
    void func(){
        cout << " I am in class A" << endl;
    }
};

class B{
public:
    void func(){
        cout << " I am in class B" << endl;
    }
};

// Derived class C
class C : public A, public B
{
};

int main(){

    // Created an object of class C
    C obj;

    // Calling function func() in class A
    obj.A::func();

    // Calling function func() in class B
    obj.B::func();

    return 0;
}

Using Virtual class

Code :

#include <iostream>
using namespace std;
class A
{
public:
    int a;
    A()
    {
        a = 10;
    }
};
class B : public virtual A
{
};
class C : public virtual A
{
};
class D : public B, public C
{
};
int main()
{
    // creating class D object
    D object;
    cout << "a = " << object.a << endl;
    return 0;
}

Polymorphism

-> The word polymorphism means having many forms. Polymorphism occurs when there is a hierarchical mode inheritance.
-> C++ polymorphism means that a call to a member function will cause a different function to be
   executed depending  on the type of object that invokes the function.

Polymorphism is divided into two types :
1. Compile time Polymorphism
2. Runtime Polymorphism - virtual function

Example:
Another excellent real time example of polymorphism is your smartphone. The smartphone can act as
phone, camera, music player and what not, taking different forms and hence polymorphism.

Compile-time polymorphism :

-> Compile-time polymorphism is a polymorphism that is, the function call is resolved during the
   compilation process
compile-time polymorphism is divide into two type:
-> Function overloading
-> Operator overloading

1. Function overloading :

-> when there are multiple functions with the same name but take different parameters as an
   arguments then these function are said to be overloaded.
-> Functions can be overloaded by changing the number of arguments or and changing the type of
   arguments.

Code :

#include<bits/stdc++.h>
using namespace std;

class Simple
{
  public :
  void fun()
  {
      cout<<"function with no argument"<<endl;
  }

  void fun(int x)
  {
      cout <<"function with int argument"<<endl;
  }
  void fun(double x)
  {
      cout<<"function with double argument"<<endl;
  }
};

int main()
{
    Simple obj;
    obj.fun();
    obj.fun(4);
    obj.fun(4.5);
    return 0;
}

2. Operator Overloading :

-> C++ also provides the option to overload operators So a single operator ‘+, when placed between
   integer operands, adds them and when placed between string operands, concatenates them.

Runtime Polymorphism :

-> Runtime polymorphism is also known as dynamic polymorphism or late binding. In runtime
   polymorphism, the function call is resolved at run time.
-> This type of polymorphism is achieved by Function Overriding or Virtual function.

-> A virtual function is a member function in the base class that we expect to redefine in derived
   classes.

Code :

#include <iostream>
using namespace std;

class Base {
   public:
    virtual void print() {
        cout << "Base Function" << endl;
    }
};

class Derived : public Base {
   public:
    void print() {
        cout << "Derived Function" << endl;
    }
};

int main() {
    Derived derived1;

    // pointer of Base type that points to derived1
    Base* base1 = &derived1;

    // calls member function of Derived class
    base1->print();

    return 0;
}
Advantages of virtual function 
-> It helps the programmer to reuse the code.
-> It also save lot of time.
-> Easy to debug the code.

Encapsulation

-> In normal term encapsulation is defined as wrapping up of data and information under a single unit.
-> Encapsulation define as binding together the data and function that  manipulates them.

Example:
School bag is one of the most real examples of Encapsulation. School bag can keep our books, pens,
etc. so, the same bag contain many things so, it's an example of encapsulation.

Advantages
1. Increased security of data
2. Encapsulation allows access to a level without revealing the complex details below that level.
3. It reduces human errors.
4. Makes the application easier to understand.

Abstraction

-> Data Abstraction is one of the most essential and important feature of Object Oriented 
   Programming in c++.
-> Abstraction means displays only the relevant attributes of objects and hides the unnecessary details
   like the background details and implementation.

Abstraction using class :
we can implement abstraction in c++ using classes. class helps us to group data members and member
functions using available access specifiers.

Example:
when we are driving a car, we are only concerned about driving the car like start/stop the car,
accelerate/ break, etc.

Advantages of Abstraction
1. Helps user to avoid writing the low level code.
2. Avoids code duplication and increases reusability.
3. Helps to increase security of an application or program as only required details are provided to the
   user.

Friend class and Friend function :

A friend class can access private and protected members of other class in which it is declared as friend.
It is sometimes useful to allow a particular class to access private members of other class.

Code :

#include<iostream>
using namespace std;

class A{
	int x;
		public:
			
	A(){
		x=10;
	}
	friend class B; //friend class
};

class B{
	public:
		void display(A &t){
			cout<<endl<<"The value of x="<<t.x;
		}
};

int main(){
	A _a;
	B _b;
	_b.display(_a);
	return 0;
}
Important points about friend functions and classes: 
1) Friends should be used only for limited purpose. too many functions or external classes are declared
   as friends of a class with protected or private data, it lessens the value of encapsulation of separate
   classes in object-oriented programming.
2) Friendship is not mutual. If class A is a friend of B, then B doesn’t become a friend of A automatically.
3) Friendship is not inherited.
4) The concept of friends is not there in Java.

Please do, give your valuable suggestion to improve the above article.
More on DSA
Graph Theory: https://leetcode.com/discuss/study-guide/2043791/graph-all-in-one-must-watch-for-beginners

If you like this post don't forget to upvote♥♥♥

Comments (6)