Skip to main content

OOP USING C++ ROADMAP BY LOVE BABBAR

 What is Object-Oriented Programming?

Object-oriented programming is a programming paradigm based on the concept of "objects", which can contain data and code: data in the form of fields, and code, in the form of procedures. A feature of objects is that an object's own procedures can access and often modify the data fields of itself.

Object Oriented Programming is considered as a design methodology for building non-rigid software. In OOPS, every logic is written to get our work done, but represented in form of Objects. OOP allows us to break our problems into small unit of work that is represented via objects and their functions. We build functions around  objects.

 

There are mainly four pillars (features) of OOP. If all of these four features are presented in programming, the programming is called  perfect Object Oriented Programming.

  1. Abstraction
  2. Encapsulation
  3. Inheritance
  4. Polymorphism

disadvantages of object-oriented programming include:

  1. Steep learning curve: The thought process involved in object-oriented programming may not be natural for some people, and it can take time to get used to it. It is complex to create programs based on interaction of objects. Some of the key programming techniques, such as inheritance and polymorphism, can be challenging to comprehend initially.
  2. Larger program size: Object-oriented programs typically involve more lines of code than procedural programs.
  3. Slower programs: Object-oriented programs are typically slower than procedure-based programs, as they typically require more instructions to be executed.
  4. Not suitable for all types of problems: There are problems that lend themselves well to functional-programming style, logic-programming style, or procedure-based programming style, and applying object-oriented programming in those situations will not result in efficient programs.

 

Class:

 A class in C++ 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. A C++ class is like a blueprint for an object.

class Geeks

{

    // Access specifier

    public:

 

    // Data Members

    string geekname;

 

    // Member Functions()

    void printname()

    {

       cout << "Geekname is: " << geekname;

    }

};

 

CLASS AND STRUCTURE:

Class

Structure

Classes are of reference types.

Structs are of value types.

All the reference types are allocated on heap memory.

All the value types are allocated on stack memory.

Allocation of large reference type is cheaper than allocation of large value type.

Allocation and de-allocation is cheaper in value type as compare to reference type.

Class has limitless features.

Struct has limited features.

Class is generally used in large programs.

Struct are used in small programs.

Classes can contain constructor or destructor.

Structure does not contain parameter less constructor or destructor, but can contain Parameterized constructor or static constructor.

Classes used new keyword for creating instances.

Struct can create an instance, with or without new keyword.

A Class can inherit from another class.

A Struct is not allowed to inherit from another struct or class.

The data member of a class can be protected.

The data member of struct can’t be protected.

Function member of the class can be virtual or abstract.

Function member of the struct cannot be virtual or abstract.

Two variable of class can contain the reference of the same object and any operation on one variable can affect another variable.

Each variable in struct contains its own copy of data(except in ref and out parameter variable) and any operation on one variable can not effect another variable.

 

Access modifiers:

Access modifier are used to implement an important aspect of Object-Oriented Programming known as Data Hiding.

There are 3 types of access modifiers available in C++: 

1.      Public

2.      Private

3.      Protected

 1. Public: All the class members declared under the public specifier will be available to everyone. The data members and member functions declared as public can be accessed by other classes and functions too. The public members of a class can be accessed from anywhere in the program using the direct member access operator (.) with the object of that class. 

class Circle

{

    public:

        double radius;

        double  compute_area()

        {

            return 3.14*radius*radius;

        }     

};

 

2. Private: The class members declared as private can be accessed only by the member functions inside the class. They are not allowed to be accessed directly by any object or function outside the class. Only the member functions or the friend functions are allowed to access the private data members of a class. 

class Circle

{  

    // private data member

    private:

        double radius;

     

    // public member function  

    public:  

        double  compute_area()

        {   // member function can access private

            // data member radius

            return 3.14*radius*radius;

        }

};

 

3. Protected: Protected access modifier is similar to private access modifier in the sense that it can’t be accessed outside of it’s class unless with the help of friend class, the difference is that the class members declared as Protected can be accessed by any subclass(derived class) of that class as well. 

 

#include <bits/stdc++.h>

using namespace std;

 

// base class

class Parent

{  

    // protected data members

    protected:

    int id_protected;

   

};

 

// sub class or derived class from public base class

class Child : public Parent

{

    public:

    void setId(int id)

    {

         

        // Child class is able to access the inherited

        // protected data members of base class

         

        id_protected = id;

         

    }

     

    void displayId()

    {

        cout << "id_protected is: " << id_protected << endl;

    }

};

 

// main function

int main() {

     

    Child obj1;

     

    // member function of the derived class can

    // access the protected data members of the base class

     

    obj1.setId(81);

    obj1.displayId();

    return 0;

}

Output

id_protected is: 81

 

Friend Class 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. For example, a LinkedList class may be allowed to access private members of Node. 

 

class Node {

private:

    int key;

    Node* next;

    /* Other members of Node Class */

 

    // Now class  LinkedList can

    // access private members of Node

    friend class LinkedList;

};

 

Friend Function Like friend class, a friend function can be given a special grant to access private and protected members. A friend function can be: 
a) A member of another class 
b) A global function 

class Node {

private:

    int key;

    Node* next;

 

    /* Other members of Node Class */

    friend int LinkedList::search();

    // Only search() of linkedList

    // can access internal members

};

 

Friend class:

#include <iostream>

class A {

private:

    int a;

 

public:

    A() { a = 0; }

    friend class B; // Friend Class

};

 

class B {

private:

    int b;

 

public:

    void showA(A& x)

    {

        // Since B is friend of A, it can access

        // private members of A

        std::cout << "A::a=" << x.a;

    }

};

 

int main()

{

    A a;

    B b;

    b.showA(a);

    return 0;

}

Output:

 

A::a=0

 

Friend function:

#include <iostream>

 

class B;

 

class A {

public:

    void showB(B&);

};

 

class B {

private:

    int b;

 

public:

    B() { b = 0; }

    friend void A::showB(B& x); // Friend function

};

 

void A::showB(B& x)

{

    // Since showB() is friend of B, it can

    // access private members of B

    std::cout << "B::b = " << x.b;

}

 

int main()

{

    A a;

    B x;

    a.showB(x);

    return 0;

}

Output:

 

B::b = 0

 

What is constructor? 
A constructor is a special type of member function of a class which initializes objects of a class. In C++, Constructor is automatically called when object(instance of class) create. It is special member function of the class because it does not have any return type.

  • Constructor has same name as the class itself
  • Constructors don’t have return type
  • A constructor is automatically called when an object is created.
  • It must be placed in public section of class.
  • If we do not specify a constructor, C++ compiler generates a default constructor for object (expects no parameters and has an empty body).

 

A picture containing diagram

Description automatically generated

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

#include <iostream>

using namespace std;

 

class construct

{

public:

    int a, b;

 

    // Default Constructor

    construct()

    {

        a = 10;

        b = 20;

    }

};

 

int main()

{

    // Default constructor called automatically

    // when the object is created

    construct c;

    cout << "a: " << c.a << endl

         << "b: " << c.b;

    return 1;

}

Output:

 

a: 10

b: 20

 

2. Parameterized Constructors: It is possible to pass arguments to constructors. Typically, these arguments help initialize an object when it is created. To create a parameterized constructor, simply add parameters to it the way you would to any other function. When you define the constructor’s body, use the parameters to initialize the object. 

#include <iostream>

using namespace std;

 

class Point

{

private:

    int x, y;

 

public:

    // Parameterized Constructor

    Point(int x1, int y1)

    {

        x = x1;

        y = y1;

    }

 

    int getX()

    {

        return x;

    }

    int getY()

    {

        return y;

    }

};

 

int main()

{

    // Constructor called

    Point p1(10, 15);

 

    // Access values assigned by constructor

    cout << "p1.x = " << p1.getX() << ", p1.y = " << p1.getY();

 

    return 0;

}

Output:

 

p1.x = 10, p1.y = 15

When an object is declared in a parameterized constructor, the initial values have to be passed as arguments to the constructor function. The normal way of object declaration may not work. The constructors can be called explicitly or implicitly.

 Example e = Example(0, 50); // Explicit call

Example e(0, 50);           // Implicit call

  • Uses of Parameterized constructor: 
    1. It is used to initialize the various data elements of different objects with different values when they are created.
    2. It is used to overload constructors.
  • Can we have more than one constructor in a class?
           Yes, It is called 
    Constructor Overloading.

3. Copy Constructor:

A copy constructor is a member function which initializes an object using another object of the same class. Detailed article on Copy Constructor.

Whenever we define one or more non-default constructors( with parameters ) for a class, a default constructor( without parameters ) should also be explicitly defined as the compiler will not provide a default constructor in this case. However, it is not necessary but it’s considered to be the best practice to always define a default constructor.

#include "iostream"

using namespace std;

 

class point

{

private:

  double x, y;

 

public:

   

  // Non-default Constructor &

  // default Constructor

  point (double px, double py)

  {

    x = px, y = py;

  }

};

 

int main(void)

{

 

  // Define an array of size

  // 10 & of type point

  // This line will cause error

  point a[10];

 

  // Remove above line and program

  // will compile without error

  point b = point(5, 6);

}

Output:

 

Error: point (double px, double py): expects 2 arguments, 0 provided

 

Shallow Copy:

In shallow copy, an object is created by simply copying the data of all variables of the original object. This works well if none of the variables of the object are defined in the heap section of memory. If some variables are dynamically allocated memory from heap section, then copied object variable will also reference then same memory location.
This will create ambiguity and run-time errors dangling pointer. Since both objects will reference to the same memory location, then change made by one will reflect those change in another object as well. Since we wanted to create a replica of the object, this purpose will not be filled by Shallow copy. 
Note: C++ compiler implicitly creates a copy constructor and overloads assignment operator in order to perform shallow copy at compile time.
 

Diagram

Description automatically generated

Shallow Copy of object if some variables are defined in heap memory, then:

Diagram

Description automatically generated

Deep Copy:

In Deep copy, an object is created by copying data of all variables and it also allocates similar memory resources with the same value to the object. In order to perform Deep copy, we need to explicitly define the copy constructor and assign dynamic memory as well if required. Also, it is required to dynamically allocate memory to the variables in the other constructors, as well.

Diagram

Description automatically generated

DIFFERENCE BETWEEN CONSTRUCTOR AND MEMBER FUNCTION:

Constructor name must be same as class name but functions cannot have same name as class name. Constructor does not have return type whereas functions must have. Constructors are invoked at the time of object creation automatically and cannot be called explicitly but functions are called explicitly using class objects.

VIRTUAL CONSTRUCTOR:

The virtual mechanism works only when we have a base class pointer to a derived class object. In C++, the constructor cannot be virtual, because when a constructor of a class is executed there is no virtual table in the memory, means no virtual pointer defined yet.

#include<iostream>

using namespace std;

class b {

   public:

      b() {

         cout<<"Constructing base \n";

      }

      virtual ~b() {

         cout<<"Destructing base \n";

      }

};

class d: public b {

   public:

      d() {

         cout<<"Constructing derived \n";

      }

      ~d() {

         cout<<"Destructing derived \n";

      }

};

int main(void) {

   d *derived = new d();

   b *bptr = derived;

   delete bptr;

   return 0;

}

Output

Constructing base

Constructing derived

Destructing derived

Destructing base

 

Destructor:

·         Destructor function is automatically invoked when the objects are destroyed.

·         It cannot be declared static or const.

·         The destructor does not have arguments.

·         It has no return type not even void.

·         An object of a class with a Destructor cannot become a member of the union.

·         A destructor should be declared in the public section of the class.

·         The programmer cannot access the address of destructor.

How are destructors different from a normal member function? 
Destructors have same name as the class preceded by a tilde (~). Destructors don’t take any argument and don’t return anything.

#include <iostream>  

using namespace std;  

class Employee  

 {  

   public:  

        Employee()    

        {    

            cout<<"Constructor Invoked"<<endl;    

        }    

        ~Employee()    

        {    

            cout<<"Destructor Invoked"<<endl;    

        }  

};  

int main(void)  

{  

    Employee e1; //creating an object of Employee  

    Employee e2; //creating an object of Employee  

    return 0;  

}

OUTPUT:

Constructor Invoked

Constructor Invoked

Destructor Invoked

Destructor Invoked

 

 

CLASS AND OBJECT REAL WORLD EXAMPLE:

Consider an ATM. An ATM is a class. It’s machine which is pretty much useless until you insert your debit card. After you insert your debit card, the machine has information about you and your bank account and the balance in it, so at this point it is an object. You have used a class and created an object, now you can perform operations on it like withdrawal of money or checking you balance or getting statement of your account, these operations will be methods belonging to that class (ATM) but you cannot use them until you create an object out of it.

And when you did perform whatever operation you wanted to perform and clicked exit/cancel and removed your card, you just destroyed the object. Now it is not an object, it has methods and all (the functions an ATM can perform) but you cannot use them until you insert your card again and create an object.

STATIC KEYWORD:

The static keyword in Java is used for memory management mainly. We can apply static keyword with variables, methods, blocks and nested classes. The static keyword belongs to the class than an instance of the class.

The static can be:

1.      Variable (also known as a class variable)

2.      Method (also known as a class method)

3.      Block

4.      Nested class

Virtual Function in C++

A virtual function is a member function which is declared within a base class and is re-defined(Overridden) by a derived class. When you refer to a derived class object using a pointer or a reference to the base class, you can call a virtual function for that object and execute the derived class’s version of the function. 

·         Virtual functions ensure that the correct function is called for an object, regardless of the type of reference (or pointer) used for function call.

·         They are mainly used to achieve Runtime polymorphism

·         Functions are declared with a virtual keyword in base class.

·         The resolving of function call is done at Run-time.

Rules for Virtual Functions:
Want to learn from the best curated videos and practice problems, check out the 
C++ Foundation Course for Basic to Advanced C++ and C++ STL Course for foundation plus STL.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

1.      Virtual functions cannot be static.

2.      A virtual function can be a friend function of another class.

3.      Virtual functions should be accessed using pointer or reference of base class type to achieve run time polymorphism.

4.      The prototype of virtual functions should be the same in the base as well as derived class.

5.      They are always defined in the base class and overridden in a derived class. It is not mandatory for the derived class to override (or re-define the virtual function), in that case, the base class version of the function is used.

6.      A class may have virtual destructor but it cannot have a virtual constructor.

Compile-time(early binding) VS run-time(late binding) behavior of Virtual Functions

#include <iostream>

using namespace std;

 

class base {

public:

    virtual void print()

    {

        cout << "print base class" << endl;

    }

 

    void show()

    {

        cout << "show base class" << endl;

    }

};

 

class derived : public base {

public:

    void print()

    {

        cout << "print derived class" << endl;

    }

 

    void show()

    {

        cout << "show derived class" << endl;

    }

};

 

int main()

{

    base* bptr;

    derived d;

    bptr = &d;

 

    // virtual function, binded at runtime

    bptr->print();

 

    // Non-virtual function, binded at compile time

    bptr->show();

}

Output:  

 

print derived class

show base class

 

abstract classes and these abstract classes should not be confused with data abstraction which is a concept of keeping implementation details separate from associated data.

A class is made abstract by declaring at least one of its functions as pure virtual function. A pure virtual function is specified by placing "= 0" in its declaration as follows −

The purpose of an abstract class (often referred to as an ABC) is to provide an appropriate base class from which other classes can inherit. Abstract classes cannot be used to instantiate objects and serves only as an interface. Attempting to instantiate an object of an abstract class causes a compilation error.

Thus, if a subclass of an ABC needs to be instantiated, it has to implement each of the virtual functions, which means that it supports the interface declared by the ABC. Failure to override a pure virtual function in a derived class, then attempting to instantiate objects of that class, is a compilation error.

Classes that can be used to instantiate objects are called concrete classes.

#include <iostream>

 

using namespace std;

 

// Base class

class Shape {

   public:

      // pure virtual function providing interface framework.

      virtual int getArea() = 0;

      void setWidth(int w) {

         width = w;

      }

   

      void setHeight(int h) {

         height = h;

      }

   

   protected:

      int width;

      int height;

};

 

// Derived classes

class Rectangle: public Shape {

   public:

      int getArea() {

         return (width * height);

      }

};

 

class Triangle: public Shape {

   public:

      int getArea() {

         return (width * height)/2;

      }

};

 

int main(void) {

   Rectangle Rect;

   Triangle  Tri;

 

   Rect.setWidth(5);

   Rect.setHeight(7);

   

   // Print the area of the object.

   cout << "Total Rectangle area: " << Rect.getArea() << endl;

 

   Tri.setWidth(5);

   Tri.setHeight(7);

   

   // Print the area of the object.

   cout << "Total Triangle area: " << Tri.getArea() << endl;

 

   return 0;

}

Total Rectangle area: 35

Total Triangle area: 17

 

 

 final specifier in C++ 11: 
Sometimes you don’t want to allow derived class to override the base class’ virtual function. 
C++ 11 allows built-in facility to prevent overriding of virtual function using final specifier. 

#include <iostream>

class Base final

{

};

 

class Derived : public Base

{

};

 

int main()

{

    Derived d;

    return 0;

}

prog.cpp:6:7: error: cannot derive from ‘final’ base ‘Base’ in derived type ‘Derived’

 class Derived : public Base

       ^

 

 

 

 

 

The explicit keyword in :

C++ is used to mark constructors to not implicitly convert types. For example, if you have a class Foo −

class Foo {

public:

    Foo(int n); // allocates n bytes to the Foo object

    Foo(const char *p); // initialize object with char *p

};

Now if you try

Foo mystring = 'x';

 

 

The char 'x' is implicitly converted to int and then will call the Foo(int) constructor. But this is not what was intended. So to prevent such conditions and make the code less error-prone, define the constructor as explicit −

Example 

class Foo {

   public:

      explicit Foo (int n); //allocate n bytes

      Foo(const char *p); // initialize with string p

};

 

 

this is a keyword that refers to the current instance of the class. There can be 3 main usage of this keyword in C++.

·         It can be used to pass current object as a parameter to another method.

·         It can be used to refer current class instance variable.

·         It can be used to declare indexers.

 

The new operator:

 is an operator which denotes a request for memory allocation on the Heap. If sufficient memory is available, new operator initializes the memory and returns the address of the newly allocated and initialized memory to the pointer variable. When you create an object of class using new keyword(normal new).

·         The memory for the object is allocated using operator new from heap.

·         The constructor of the class is invoked to properly initialize this memory.

car *p = new car("Honda", 2017); //OBJECT

Operator new

Operator new is a function that allocates raw memory and conceptually a bit similar to malloc().

·         It is the mechanism of overriding the default heap allocation logic.

·         It doesn’t initializes the memory i.e constructor is not called. However, after our overloaded new returns, the compiler then automatically calls the constructor also as applicable.

·         It’s also possible to overload operator new either globally, or for a specific class

void *operator new(size_t size)

        {

            cout << "new operator overloaded" << endl;

            void *p = malloc(size);

            return p;

        }

const keyword is attached with any method(), variable, pointer variable, and with the object of a class it prevents that specific object/method()/variable to modify its data items value.

·         The const variable cannot be left un-initialized at the time of the assignment.

·         It cannot be assigned value anywhere in the program.

·         Explicit value needed to be provided to the constant variable at the time of declaration of the constant variable.

const variable

#include <iostream>

using namespace std;

 

// Driver Code

int main()

{

 

    // const int x;  CTE error

    // x = 9;   CTE error

    const int y = 10;

    cout << y;

 

    return 0;

}

Output:

10

 

 

Super is a keyword

It is used inside a sub-class method definition to call a method defined in the super class. Private methods of the super-class cannot be called. Only public and protected methods can be called by the super keyword. It is also used by class constructors to invoke constructors of its parent class.
C++ doesn't have a super or base keyword to designate "the base class", like C# and Java do. One reason for this is that C++ supports multiple inheritance, which would make such a keyword ambiguous.

FEATURES OF OOP:

POLYMORPHISM:

The word polymorphism means having many forms. In simple words, we can define polymorphism as the ability of a message to be displayed in more than one form. A real-life example of polymorphism, a person at the same time can have different characteristics. Like a man at the same time is a father, a husband, an employee. So the same person posses different behavior in different situations. This is called polymorphism. Polymorphism is considered as one of the important features of Object Oriented Programming.

  • Compile time Polymorphism
  • Runtime Polymorphism

Polymorphism-in-CPP

  1. Compile time polymorphism: This type of polymorphism is achieved by function overloading or operator overloading.



    • Function Overloading: When there are multiple functions with same name but different parameters then these functions are said to be overloaded. Functions can be overloaded by change in number of arguments or/and change in type of arguments.

#include <bits/stdc++.h>

 

using namespace std;

class Geeks

{

    public:

     

    // function with 1 int parameter

    void func(int x)

    {

        cout << "value of x is " << x << endl;

    }

     

    // function with same name but 1 double parameter

    void func(double x)

    {

        cout << "value of x is " << x << endl;

    }

     

    // function with same name and 2 int parameters

    void func(int x, int y)

    {

        cout << "value of x and y is " << x << ", " << y << endl;

    }

};

 

int main() {

     

    Geeks obj1;

     

    // Which function is called will depend on the parameters passed

    // The first 'func' is called

    obj1.func(7);

     

    // The second 'func' is called

    obj1.func(9.132);

     

    // The third 'func' is called

    obj1.func(85,64);

    return 0;

}

Output:

 

value of x is 7

value of x is 9.132

value of x and y is 85, 64

 

·         Operator Overloading: C++ also provide option to overload operators. For example, we can make the operator (‘+’) for string class to concatenate two strings. We know that this is the addition operator whose task is to add two operands. So a single operator ‘+’ when placed between integer operands , adds them and when placed between string operands, concatenates them.
Example:

#include<iostream>

using namespace std;

   

class Complex {

private:

    int real, imag;

public:

    Complex(int r = 0, int i =0)  {real = r;   imag = i;}

       

    // This is automatically called when '+' is used with

    // between two Complex objects

    Complex operator + (Complex const &obj) {

         Complex res;

         res.real = real + obj.real;

         res.imag = imag + obj.imag;

         return res;

    }

    void print() { cout << real << " + i" << imag << endl; }

};

   

int main()

{

    Complex c1(10, 5), c2(2, 4);

    Complex c3 = c1 + c2; // An example call to "operator+"

    c3.print();

}

Output:

 

12 + i9

 

Runtime polymorphism: This type of polymorphism is achieved by Function Overriding.

  • Function overriding on the other hand occurs when a derived class has a definition for one of the member functions of the base class. That base function is said to be overridden.

#include <bits/stdc++.h>

using namespace std;

 

class base

{

public:

    virtual void print ()

    { cout<< "print base class" <<endl; }

   

    void show ()

    { cout<< "show base class" <<endl; }

};

   

class derived:public base

{

public:

    void print () //print () is already virtual function in derived class, we could also declared as virtual void print () explicitly

    { cout<< "print derived class" <<endl; }

   

    void show ()

    { cout<< "show derived class" <<endl; }

};

 

//main function

int main()

{

    base *bptr;

    derived d;

    bptr = &d;

       

    //virtual function, binded at runtime (Runtime polymorphism)

    bptr->print();

       

    // Non-virtual function, binded at compile time

    bptr->show();

 

    return 0;

}

Output:

 

print derived class

show base class

 

INHERITANCE:

he capability of a class to derive properties and characteristics from another class is called Inheritance. Inheritance is one of the most important feature of Object Oriented Programming. 
Sub Class: The class that inherits properties from another class is called Sub class or Derived Class. 
Super Class:The class whose properties are inherited by sub class is called Base Class or Super class.

Types of Inheritance in C++

1. Single Inheritance: In single inheritance, a class is allowed to inherit from only one class. i.e. one sub class is inherited by one base class only.

Diagram

Description automatically generated

Syntax

class subclass_name : access_mode base_class
{
  //body of subclass
};

// C++ program to explain

// Single inheritance

#include <iostream>

using namespace std;

 

// base class

class Vehicle {

  public:

    Vehicle()

    {

      cout << "This is a Vehicle" << endl;

    }

};

 

// sub class derived from a single base classes

class Car: public Vehicle{

 

};

 

// main function

int main()

{  

    // creating object of sub class will

    // invoke the constructor of base classes

    Car obj;

    return 0;

}

Output

This is a Vehicle

 

 

 

2. Multiple Inheritance: Multiple Inheritance is a feature of C++ where a class can inherit from more than one classes. i.e one sub class is inherited from more than one base classes.

Diagram

Description automatically generated

Syntax

class subclass_name : access_mode base_class1, access_mode base_class2, ....
{
  //body of subclass
};

Here, the number of base classes will be separated by a comma (‘, ‘) and access mode for every base class must be specified. 

#include <iostream>

using namespace std;

 

// first base class

class Vehicle {

  public:

    Vehicle()

    {

      cout << "This is a Vehicle" << endl;

    }

};

 

// second base class

class FourWheeler {

  public:

    FourWheeler()

    {

      cout << "This is a 4 wheeler Vehicle" << endl;

    }

};

 

// sub class derived from two base classes

class Car: public Vehicle, public FourWheeler {

 

};

 

// main function

int main()

{  

    // creating object of sub class will

    // invoke the constructor of base classes

    Car obj;

    return 0;

}

Output

This is a Vehicle

This is a 4 wheeler Vehicle

 

 

 

Please visit this link to learn multiple inheritance in details. 
3.
 Multilevel Inheritance: In this type of inheritance, a derived class is created from another derived class.

Diagram

Description automatically generated

 

// C++ program to implement

// Multilevel Inheritance

#include <iostream>

using namespace std;

 

// base class

class Vehicle

{

  public:

    Vehicle()

    {

      cout << "This is a Vehicle" << endl;

    }

};

 

// first sub_class derived from class vehicle

class fourWheeler: public Vehicle

{  public:

    fourWheeler()

    {

      cout<<"Objects with 4 wheels are vehicles"<<endl;

    }

};

// sub class derived from the derived base class fourWheeler

class Car: public fourWheeler{

   public:

     Car()

     {

       cout<<"Car has 4 Wheels"<<endl;

     }

};

 

// main function

int main()

{  

    //creating object of sub class will

    //invoke the constructor of base classes

    Car obj;

    return 0;

}

Output

This is a Vehicle

Objects with 4 wheels are vehicles

Car has 4 Wheels

 

 

4. Hierarchical Inheritance: In this type of inheritance, more than one sub class is inherited from a single base class. i.e. more than one derived class is created from a single base class.

Diagram

Description automatically generated

#include <iostream>

using namespace std;

 

// base class

class Vehicle

{

  public:

    Vehicle()

    {

      cout << "This is a Vehicle" << endl;

    }

};

 // first sub class

class Car: public Vehicle

{

 

};

 

// second sub class

class Bus: public Vehicle

{

     

};

 

// main function

int main()

{  

    // creating object of sub class will

    // invoke the constructor of base class

    Car obj1;

    Bus obj2;

    return 0;

}

Output

This is a Vehicle

This is a Vehicle

 

 

 

5. Hybrid (Virtual) Inheritance: Hybrid Inheritance is implemented by combining more than one type of inheritance. For example: Combining Hierarchical inheritance and Multiple Inheritance. 
Below image shows the combination of hierarchical and multiple inheritance:

Diagram

Description automatically generated

 

#include <iostream>

using namespace std;

 

// base class

class Vehicle

{

  public:

    Vehicle()

    {

      cout << "This is a Vehicle" << endl;

    }

};

 

//base class

class Fare

{

    public:

    Fare()

    {

        cout<<"Fare of Vehicle\n";

    }

};

 

// first sub class

class Car: public Vehicle

{

 

};

 

// second sub class

class Bus: public Vehicle, public Fare

{

     

};

 

// main function

int main()

{  

    // creating object of sub class will

    // invoke the constructor of base class

    Bus obj2;

    return 0;

}

Output

This is a Vehicle

Fare of Vehicle

 

 

6. A special case of hybrid inheritance : Multipath inheritance
A derived class with two base classes and these two base classes have one common base class is called multipath inheritance. An ambiguity can arrise in this type of inheritance.

#include <conio.h>

#include <iostream.h>

class ClassA {

public:

    int a;

};

 

class ClassB : public ClassA {

public:

    int b;

};

class ClassC : public ClassA {

public:

    int c;

};

 

class ClassD : public ClassB, public ClassC {

public:

    int d;

};

 

void main()

{

 

    ClassD obj;

 

    // obj.a = 10;                   //Statement 1, Error

    // obj.a = 100;                 //Statement 2, Error

 

    obj.ClassB::a = 10; // Statement 3

    obj.ClassC::a = 100; // Statement 4

 

    obj.b = 20;

    obj.c = 30;

    obj.d = 40;

 

    cout << "\n A from ClassB  : " << obj.ClassB::a;

    cout << "\n A from ClassC  : " << obj.ClassC::a;

 

    cout << "\n B : " << obj.b;

    cout << "\n C : " << obj.c;

    cout << "\n D : " << obj.d;

}

Output:

A from ClassB  : 10

A from ClassC  : 100

B : 20

C : 30

D : 40

·          

 

In the above example, both ClassB & ClassC inherit ClassA, they both have single copy of ClassA. However ClassD inherit both ClassB & ClassC, therefore ClassD have two copies of ClassA, one from ClassB and another from ClassC. 
If we need to access the data member a of ClassA through the object of ClassD, we must specify the path from which a will be accessed, whether it is from ClassB or ClassC, bco’z compiler can’t differentiate between two copies of ClassA in ClassD.
There are 2 ways to avoid this ambiguity: 
Avoiding ambiguity using scope resolution operator: 
Using scope resolution operator we can manually specify the path from which data member a will be accessed, as shown in statement 3 and 4, in the above example. 

obj.ClassB::a = 10;        //Statement 3

obj.ClassC::a = 100;      //Statement 4

#include<iostream.h>

     #include<conio.h>

 

     class ClassA

     {

            public:

            int a;

     };

 

     class ClassB : virtual public ClassA

     {

            public:

            int b;

     };

     class ClassC : virtual public ClassA

     {

            public:

            int c;

     };

 

     class ClassD : public ClassB, public ClassC

     {

            public:

            int d;

     };

 

     void main()

     {

 

            ClassD obj;

 

            obj.a = 10;        //Statement 3

            obj.a = 100;      //Statement 4

 

            obj.b = 20;

            obj.c = 30;

            obj.d = 40;

 

            cout<< "\n A : "<< obj.a;

            cout<< "\n B : "<< obj.b;

            cout<< "\n C : "<< obj.c;

            cout<< "\n D : "<< obj.d;

 

     }

Output:

A : 100

B : 20

C : 30

D : 40

 

 

Data encapsulation:

It is a mechanism of bundling the data, and the functions that use them and data abstraction is a mechanism of exposing only the interfaces and hiding the implementation details from the user. Encapsulation also lead to data abstraction or hiding. As using encapsulation also hides the data. In the above example the data of any of the section like sales, finance or accounts is hidden from any other section.

A primitive data type :
specifies the size and type of variable values, and it has no additional methods. Eg int, long, double, float, etc.

Array is not a primitive data type.

Binding:

 refers to the process of converting identifiers (such as variable and performance names) into addresses. Binding is done for each variable and functions. For functions, it means that matching the call with the right function definition by the compiler. It takes place either at compile time or at runtime.

cpp-binding

Early Binding (compile-time time polymorphism) As the name indicates, compiler (or linker) directly associate an address to the function call. It replaces the call with a machine language instruction that tells the mainframe to leap to the address of the function.

#include<iostream>

using namespace std;

   

class Base

{

public:

    void show() { cout<<" In Base \n"; }

};

   

class Derived: public Base

{

public:

    void show() { cout<<"In Derived \n"; }

};

   

int main(void)

{

    Base *bp = new Derived;

 

    // The function call decided at

    // compile time (compiler sees type

    // of pointer and calls base class

    // function.

    bp->show();  

 

    return 0;

}

Output:

 

In Base

 

Late Binding : (Run time polymorphism) In this, the compiler adds code that identifies the kind of object at runtime then matches the call with the right function definition (Refer this for details). This can be achieved by declaring a virtual function.

#include<iostream>

using namespace std;

   

class Base

{

public:

    virtual void show() { cout<<" In Base \n"; }

};

   

class Derived: public Base

{

public:

    void show() { cout<<"In Derived \n"; }

};

   

int main(void)

{

    Base *bp = new Derived;

    bp->show();  // RUN-TIME POLYMORPHISM

    return 0;

}

Output:

 

In Derived

 

Default access modifier private

Instances made for abstract class is 0.

 

Garbage collection:

is the process of managing memory, automatically. It finds the unused objects (that are no longer used by the program) and delete or remove them to free up the memory. The garbage collection mechanism uses several GC algorithms. The most popular algorithm that is used is Mark and Sweep.

The heap is a part of memory where objects live. It's the only part of memory that involved in the garbage collection process. It is also known as garbage collectible heap. All the garbage collection makes sure that the heap has as much free space as possible. The function of the garbage collector is to find and delete the objects that cannot be reached.

Important Points About Garbage Collector

·         It is controlled by a thread known as Garbage Collector.

·         Java provides two methods System.gc() and Runtime.gc() that sends request to the JVM for garbage collection. Remember, it is not necessary that garbage collection will happen.

·         Java programmer are free from memory management. We cannot force the garbage collector to collect the garbage, it depends on the JVM.

·         If the Heap Memory is full, the JVM will not allow to create a new object and shows an error java.lang.OutOfMemoryError.

·         When garbage collector removes object from the memory, first, the garbage collector thread calls the finalize() method of that object and then remove.

Exception:

An exception is a problem that arises during the execution of a program. A C++ exception is a response to an exceptional circumstance that arises while a program is running, such as an attempt to divide by zero.

Exceptions provide a way to transfer control from one part of a program to another. C++ exception handling is built upon three keywords: try, catch, and throw.

·        throw − A program throws an exception when a problem shows up. This is done using a throw keyword.

·        catch − A program catches an exception with an exception handler at the place in a program where you want to handle the problem. The catch keyword indicates the catching of an exception.

·        try − A try block identifies a block of code for which particular exceptions will be activated. It's followed by one or more catch blocks.

Assuming a block will raise an exception, a method catches an exception using a combination of the try and catch keywords. A try/catch block is placed around the code that might generate an exception. Code within a try/catch block is referred to as protected code, and the syntax for using try/catch as follows −

try {
   // protected code
} catch( ExceptionName e1 ) {
   // catch block
} catch( ExceptionName e2 ) {
   // catch block
} catch( ExceptionName eN ) {
   // catch block
}

You can list down multiple catch statements to catch different type of exceptions in case your try block raises more than one exception in different situations.

Throwing Exceptions

Exceptions can be thrown anywhere within a code block using throw statement. The operand of the throw statement determines a type for the exception and can be any expression and the type of the result of the expression determines the type of exception thrown.

Following is an example of throwing an exception when dividing by zero condition occurs −

double division(int a, int b) {
   if( b == 0 ) {
      throw "Division by zero condition!";
   }
   return (a/b);
}

Catching Exceptions

The catch block following the try block catches any exception. You can specify what type of exception you want to catch and this is determined by the exception declaration that appears in parentheses following the keyword catch.

try {
   // protected code
} catch( ExceptionName e ) {
  // code to handle ExceptionName exception
}

Above code will catch an exception of ExceptionName type. If you want to specify that a catch block should handle any type of exception that is thrown in a try block, you must put an ellipsis, ..., between the parentheses enclosing the exception declaration as follows −

try {
   // protected code
} catch(...) {
  // code to handle any exception
}

The following is an example, which throws a division by zero exception and we catch it in catch block.

#include <iostream>

using namespace std;

 

double division(int a, int b) {

   if( b == 0 ) {

      throw "Division by zero condition!";

   }

   return (a/b);

}

 

int main () {

   int x = 50;

   int y = 0;

   double z = 0;

 

   try {

      z = division(x, y);

      cout << z << endl;

   } catch (const char* msg) {

     cerr << msg << endl;

   }

 

   return 0;

}

 

condition ? value_if_true : value_if_false

The statement evaluates to value_if_true if condition is met, and value_if_false otherwise.

int a = 10, b = 20, c;
c = (a < b) ? a : b;
printf("%d", c);

 

Deadlock is a situation where a set of processes are blocked because each process is holding a resource and waiting for another resource acquired by some other process. 
Consider an example when two trains are coming toward each other on the same track and there is only one track, none of the trains can move once they are in front of each other. A similar situation occurs in operating systems when there are two or more processes that hold some resources and wait for resources held by other(s). For example, in the below diagram, Process 1 is holding Resource 1 and waiting for resource 2 which is acquired by process 2, and process 2 is waiting for resource 1. 
 

 

deadlock

Deadlock can arise if the following four conditions hold simultaneously (Necessary Conditions) 
Mutual Exclusion: One or more than one resource are non-shareable (Only one process can use at a time) 
Hold and Wait: A process is holding at least one resource and waiting for resources. 
No Preemption: A resource cannot be taken from a process unless the process releases the resource. 
Circular Wait: A set of processes are waiting for each other in circular form. 

Methods for handling deadlock 
There are three ways to handle deadlock 
1) Deadlock prevention or avoidance: The idea is to not let the system into a deadlock state. 
One can zoom into each category individually, Prevention is done by negating one of above mentioned necessary conditions for deadlock. 
Avoidance is kind of futuristic in nature. By using strategy of “Avoidance”, we have to make an assumption. We need to ensure that all information about resources which process will need are known to us prior to execution of the process. We use Banker’s algorithm (Which is in-turn a gift from Dijkstra) in order to avoid deadlock. 

2) Deadlock detection and recovery: Let deadlock occur, then do preemption to handle it once occurred. 

3) Ignore the problem altogether: If deadlock is very rare, then let it happen and reboot the system. This is the approach that both Windows and UNIX take.

 

Comments

Popular posts from this blog

Price Comparer website using django and web scrapping

Our website compares the prices of any given product which is available on the amazon and filpkart, thus shows you the result of price available on both site along with the suitable links. To develop this project we have used the python web framework known as Django. Web pages are made using the bootstrap HTML they are web.html and about.html.   fig directories of Project /PriceCompare directory is the main folder generated by command $ django-admin startproject PriceCompare Which contains the manage.py file that helps to run the server and host our web on localhost / app1 folder is created   by a command $ python manage.py startapp app1 Here will find all the required files like views.py, urls.py, etc. /Template directory contains all the HTML files   Views.py file contains the code which compare the user given data. We have used the selenium module of python to scrap the web data which are allowed to scrape . Selenium webdriver is used to autom...

DBMS_notes roadmap by love babbar

  DATABASE : A database is an organized collection of structured information, or data, stored electronically in a computer system. DATASTRUCTURE USED BY DATABASE: The most frequently used data structures for one-dimensional database indexes are dynamic tree-structured indexes such as B/B+-Trees and hash-based indexes using extendible and linear hashing. DBMS(DATABASE MANAGEMENT SYSTEM): A Database Management System (DBMS) is software designed to store, retrieve, update, define, and manage data in a database. NEEDS OF DBMS: ü   Controlling redundancy(redundancy refers to repeated instances(The situation where a data or information is stored in the database at a particular moment of time is called an instance.) of the same data.) and inconsistency. A DBMS uses data normalization to avoid redundancy and duplicates. ü   Efficient memory management and indexing ü   Concurrency control (Concurrency Control in Database Management System is a procedure of ma...