Complete OOPs Tutorial in CPP.

Basics of OOPs

Welcome to the first post in our C++ OOPs tutorial series! In this post, we will be discussing the concepts of classes and objects in C++. If you are already familiar with the basics of C language, you will find that classes and objects in C++ are similar in many ways, but also offer some powerful new features.

What are Classes and Objects?

A class in C++ is a blueprint for creating objects. It defines a set of data members (variables) and member functions (methods) that the objects created from the class will have. For example, you might have a class called Car which has data members such as make, model, and year, and member functions such as start() and stop().

An object, on the other hand, is a specific instance of a class. When you create an object from a class, you are essentially creating a new copy of the class's data members and member functions. For example, you might create an object called myCar which is an instance of the Car class, and has the values Toyota, Corolla, and 2020 for the make, model, and year data members, respectively.

How to define a class in C++?

The basic syntax for defining a class in C++ is as follows:

class className {
    // data members
    // member functions
};

For example, here is a simple class for a rectangle:

class Rectangle {
    public:
        int width, height;
        void setWidth(int w) {
            width = w;
        }
        void setHeight(int h) {
            height = h;
        }
        int getArea() {
            return width * height;
        }
};

In this example, the class Rectangle has three data members: width, height, and three member functions: setWidth(), setHeight(), getArea().

Creating an object from a class:

Once you have defined a class, you can create objects from it using the following syntax:

className objectName;

For example, if you have defined a class called "Rectangle", you can create an object from it like this:

Rectangle rect;

Accessing Data Members and Member Functions:

Once you have created an object from a class, you can access its data members and member functions using the dot operator (.). For example, you can set the width and height of the rect object like this:

rect.setWidth(5);
rect.setHeight(10);

and you can access the area of the rect object like this:

int area = rect.getArea();

Examples :

Static Class with objects :

#include <iostream>
using namespace std;
class employee
{
private:
    int id;
    static int count;

public:
    void setdata()
    {
        cout << "Enter the id of employee :\n";
        cin >> id;
        count++;
    }
    void getdata()
    {
        cout << "The id of employee with count " << count << " is " << id << endl;
    }
    void counter();
};
int employee ::count = 100;
void employee ::counter()
{
    cout << "The value of counter is " << count << endl;
}
int main()
{
    employee papa, aai, dada;

    aai.setdata();
    aai.getdata();
    // cout<<"The value of counter is -->"<<aai.count<<endl;
    aai.counter();

    dada.setdata();
    dada.counter();
    dada.getdata();
    // cout<<"The value of counter is -->"<<dada.count<<endl; <-- this do not work since the count variable is private.

    papa.setdata();
    papa.getdata();
    // cout<<"The value of counter is -->"<<papa.count<<endl;
    papa.counter();

    return 0;
}

This program defines a class employee that contains a private integer variable id and a static integer variable count. The class has three public functions: setdata, getdata, and counter. The setdata function prompts the user to enter an employee ID and increments the count variable. The getdata function prints the employee ID and the current value of count. The counter function prints the current value of count. In the main function, three objects of the employee class are created and the setdata, getdata, and counter functions are called on each of them. The program demonstrates how the count variable can be shared among all objects of the employee class, while the id variable is unique to each object.

Array of objects:

#include <iostream>
using namespace std;
class employee
{
private:
    int id;
    int salary;

public:
    void setid(int x)
    {
        salary = 1200;
        cout << "Enter the id of employee " << x << " -->";
        cin >> id;
    }
    void getid()
    {
        cout << "The id of employee is " << id << " with salary " << salary << endl;
    }
};

int main()
{
    employee com[4];
    for (int a = 0; a < 4; a++)
    {
        com[a].setid(a + 1);
        com[a].getid();
    }
    return 0;
}

This program defines a class employee that contains two private member variables, id and salary. The class has two public member functions, setid and getid. The setid function takes an integer as an argument, assigns a default salary of 1200 and prompts the user to enter the employee ID. The getid function prints the employee ID and salary. In the main function, an array of four objects of the employee class is created, and the setid and getid functions are called on each of the objects in a for loop. The program demonstrates how to create an array of objects and how to set and get the values of the member variables for each object in the array.

Passing object as argument:

#include <iostream>
using namespace std;
class complex
{
    int a, b;

public:
    void setdata(int x, int y)
    {
        a = x;
        b = y;
    }
    void getdata(complex o1, complex o2)
    {
        a = o1.a + o2.a;
        b = o1.b + o2.b;
    }
    void print()
    {
        cout << a << "+" << b << "i" << endl;
    }
};
int main()
{
    complex a1, a2, a3;
    a1.setdata(2, 5);
    a2.setdata(1, 6);
    a1.print();
    a2.print();
    // a3.setdata(9, 8);

    a1.getdata(a1, a2);
    a1.print();
    // a2.getdata(a2, a3);

    return 0;
}

This program defines a class complex that has three member functions: setdata, getdata, and print. The setdata function takes two integers as arguments and assigns them to the private member variables a and b of the class. The getdata function takes two objects of the complex class as arguments and assigns the sum of their a and b variables to the a and b variables of the calling object. The print function prints the values of the a and b variables in the format a+bi. In the main function, three objects of the complex class are created and the setdata, getdata, and print functions are called on them. The program demonstrates how the getdata function can be used to add two complex numbers represented by objects of the complex class.

Constructors and Destructors

Constructors:

A constructor is a special member function that is called when an object is created. It is used to initialize the data members of the object. A class can have multiple constructors with different parameters. The constructors are defined using the name of the class, with no return type.

For example, here is a constructor for the "Rectangle" class:

class Rectangle {
    public:
        int width, height;
        Rectangle(int w, int h) {
            width = w;
            height = h;
        }
        // other member functions
};

In this example, the constructor Rectangle(int w, int h) takes two parameters, wand h., and initializes the width and height data members with these values.

You can create an object of the class and initialize it's variables by passing the value to the constructor like this:

Rectangle rect(5,10);

Destructors:

A destructor is a special member function that is called when an object goes out of scope or is deleted. It is used to release any resources that the object may have acquired during its lifetime. A class can have only one destructor. The destructor is defined using the name of the class, prefixed with a tilde (~), with no return type.

For example, here is a destructor for the "Rectangle" class:

class Rectangle {
    public:
        int width, height;
        // constructor
        ~Rectangle() {
            // release resources
        }
        // other member functions
};

In this example, the destructor "~Rectangle()" releases any resources that the "Rectangle" object may have acquired during its lifetime.

It's important to note that constructors are called automatically when an object is created, while destructors must be called manually.

In C++, the rule of three, five or zero applies, if you define one of these three special member functions: copy constructor, copy assignment operator, and destructor, you should define all three.

That's a brief explanation of Classes and Objects in C++, including constructors and destructors. I hope this helps you understand the basics of working with classes and objects in C++.

Examples:

#include <iostream>
using namespace std;
class complex
{
    int x, y;

public:
    complex()
    {
        x = 10;
        y = 15;
        cout << "This is a magic of constructor!!!!\n";
    }
    void print()
    {
        cout << x << " + " << y << "i" << endl;
    }
};

int main()
{
    complex v, v1, v2, v3, v4, v5, v6;
    v.print();
    v1.print();
    v2.print();
    v3.print();
    v4.print();
    v5.print();
    v6.print();
    return 0;
}

Parameterized constructor:

#include <iostream>
using namespace std;
class complex
{
    int x, y;

public:
    complex(int, int);
    void print()
    {
        cout << x << " + " << y << "i" << endl;
    }
};
complex::complex(int a, int b)
{
    x = a;
    y = b;
}

int main()
{
    complex s(5, 6);
    s.print();

    complex t = complex(9, 55);
    t.print();
    return 0;
}

This program defines a class complex that contains two private member variables, x and y. The class has one public member function, print, which outputs the values of x and y. The class also has a constructor that takes two integer arguments, a and b, which are used to initialize the values of x and y. In the main function, two objects of the complex class are created, one using the constructor and the other using the copy constructor. The program demonstrates how to create an object of a class using a constructor and how to initialize the member variables of an object using a constructor.

#include <iostream>
#include <math.h>
using namespace std;
class point
{
    int x, y;
    // point(point, point);

public:
    void setdata(int a, int b)
    {
        x = a;
        y = b;
    }
    friend void distance(point o1, point o2);
};
void distance(point o1, point o2)
{
    float dist, distsq;
    distsq = ((o1.x * o1.x) - (o2.x * o2.x)) + ((o1.y * o1.y) - (o2.y * o2.y));
    dist = sqrt(distsq);
    cout << "The distance between these two points is " << dist << endl;
}
int main()
{
    point p1, p2;
    p1.setdata(5, 2);
    p2.setdata(3, 1);
    distance(p1, p2);
    return 0;
}

This program is defining a class point which has two private data members x and y and a public member function setdata(int a, int b) which sets the values of x and y to the values of a and b respectively. It also has a friend function distance(point o1, point o2) which calculates the distance between two points and prints it out.

In the main function, the program creates two objects of class point, p1 and p2. It then calls the setdata() function to set the values of x and y for both p1 and p2. Finally, it calls the friend function distance() and passes the two point objects p1 and p2 as arguments, which calculates and prints the distance between the two points.

Copy Constructor:

#include <iostream>
using namespace std;
class complex
{
    int x, y;

public:
    complex()
    {
        x = 0;
        y = 0;
    }
    complex(int a, int b)
    {
        x = a;
        y = b;
    }
    void print()
    {
        cout << x << " + " << y << "i" << endl;
    }
};

int main()
{
    complex o1,o2(2,3);
    o1.print();
    o2.print();

    return 0;
}

his program defines a class called complex with two private members, x and y, which represent the real and imaginary parts of a complex number, respectively. The class has two constructors: the default constructor, complex(), which initializes x and y to 0, and the constructor complex(int a, int b), which assigns the values of a and b to x and y, respectively. The class also has a print() function which prints the complex number in the form "x + yi".

In main(), two objects of the class complex are created, one using the default constructor and the other using the constructor with arguments. The print() method is called on both objects to print the values of x and y.

When the program is run, it will output:

0 + 0i

2 + 3i

Polymorphism:

Polymorphism is one of the fundamental concepts in object-oriented programming. It allows a single function or operator to work with different types of data, or to have different meanings depending on the context in which it is used.

There are two types of polymorphism in C++: compile-time polymorphism (also known as static polymorphism) and runtime polymorphism (also known as dynamic polymorphism).

Compile-time polymorphism:

Compile-time polymorphism is achieved through function overloading and operator overloading. Function overloading allows multiple functions to have the same name but different parameters. The correct function to be called is determined at compile time based on the number and types of the arguments passed.

For example:

class Rectangle {
    public:
        int width, height;
        // constructor
        Rectangle(int w, int h) {
            width = w;
            height = h;
        }
        int area() {
            return width * height;
        }
        int area(int w, int h) {
            return w * h;
        }
};

In this example, the class Rectangle has two functions with the same name area, but with different parameters. The first one calculates the area of the rectangle using the width and height data members, while the second one calculates the area of any rectangle using the parameters passed to it.

Operator overloading allows operators to have different meanings depending on the types of the operands. For example, the + operator can be used to add two integers, but it can also be used to concatenate two strings.

For example:

class Complex {
    public:
        int real, imag;
        // constructor
        Complex(int r, int i) {
            real = r;
            imag = i;
        }
        Complex operator + (Complex c) {
            return Complex(real + c.real, imag + c.imag);
        }
};

In this example, the class Complex has an operator + function that is used to add two complex numbers.

Function overloading :

Function overloading is a feature in C++ where multiple functions can have the same name but different parameters. When a function is called, the compiler determines which function to call based on the number and types of arguments passed to the function. This allows for more flexibility and code reuse, as the same function name can be used for different tasks depending on the arguments passed to it. In C++, function overloading can be achieved by defining multiple functions with the same name but different parameter lists. The function that is called is determined by the type and number of arguments passed to the function. Function overloading can be used in conjunction with default arguments, which allows you to assign default values to function parameters. When a function is called without passing a value for a default argument, the default value is used instead.

#include <iostream>
using namespace std;
int global;
int area(int a, int b) { return a * b; }
int area(int side) { return side * side; }
float area(double radius) { return (radius * radius * 3.142); }
int main() {
  cout << "The area of the square with side length 2 is " << area(2) << endl;
  cout << "The area of circle with radius 3.6 is " << area(3.6) << endl;
  cout << "The area of rectangle with side length 2 and height 3 is "
       << area(2, 3) << endl;
}

The first function takes two integers as arguments and returns their product, representing the area of a rectangle. The second function takes an integer as an argument and returns the square of the integer, representing the area of a square. The third function takes a double as an argument and returns the area of a circle, which is calculated using the formula of pi * radius^2.

In the main function, these three functions are called with different arguments, first with a single integer to find the area of a square, second with a double to find the area of a circle and last with two integers to find the area of rectangle.

The program output will be:

The area of the square with side length 2 is 4.

The area of circle with radius 3.6 is 40.3856.

The area of rectangle with side length 2 and height 3 is 6.

Constructor overloading:

Constructor overloading is a feature in C++ where a class can have multiple constructors with different parameter lists. Each constructor performs a different task, and the appropriate constructor to call is chosen based on the parameters passed to it. This allows the programmer to create objects with different initial states depending on the context. In the given program, the class "area" and "volume" have multiple constructors with different parameters, which are being used to perform different tasks and provide different initial states for the objects of these classes. This results in a more flexible and efficient code, as the same class can be used to perform different tasks depending on the input.

#include <iostream>
using namespace std;
class area {
public:
  area() {
    cout<<"This is a default constructor"<<endl;
  }
  area(int r) {
    cout << "The area of the circle with radius " << r << " is " << 3.14 * r * r
         << endl;
  }
  area(int l, int b) {
    cout << "The area of rectangle with length " << l << " and breadth " << b
         << " is " << l * b << endl;
  }
  area(double b, double height) {
    cout << "The area of triangle with base " << b << " and " << height
         << " is " << .5 * b * height << endl;
  }
};
class volume {
public:
  // volume() {}//default 
  volume(float r) {
    cout << "The volume of the sphere with radius " << r << " is "
         << (4 / 3) * 3.142 * r * r * r << endl;
  }
  volume(int r, int h) {
    cout << "The volume of the cone with radius " << r << " and height " << h
         << " is " << 1 / float(3) * 3.142 * r * r * h << endl;
  }
  volume(double r, double h) {
    cout << "The volume of the cylinder with radius " << r << " and height "
         << h << " is " << 3.142 * r * r * h << endl;
  }
};

int main() {
  area a1(6), a2(3.156, 2.14), a3(2, 4), a4;
  cout << endl;
  volume v1(2.1603), v2(3, 4), v3(3.65, 0.246);

  return 0;
}

This program defines two classes, area and volume, which each have multiple constructors. The area class has four constructors: one default constructor and three other constructors that take different numbers and types of parameters to calculate the area of different shapes (a circle, a rectangle, and a triangle). The volume class also has three constructors: one that calculates the volume of a sphere, one that calculates the volume of a cone, and one that calculates the volume of a cylinder.

In the main() function, objects of both classes are created and initialized with different arguments, which invoke the corresponding constructors. The program then calculates and prints the area or volume of each shape, using the values passed to the constructors.

Note that the default constructor is invoked when object of class area is declared without any argument. Also, the default constructor is not defined in the volume class but the program still runs fine.

Runtime polymorphism:

Runtime polymorphism is achieved through virtual functions and function pointers. A virtual function is a member function that is declared as virtual in the base class and can be overridden in derived classes. The correct function to be called is determined at runtime based on the type of the object.

For example:

class Shape {
    public:
        virtual int area() = 0;
};
class Rectangle : public Shape {
    public:
        int width, height;
        // constructor
        Rectangle(int w, int h) {
            width = w;
            height = h;
        }
        int area() {
            return width * height;
        }
};
class Circle : public Shape {
    public:
        int radius;
        // constructor
        Circle(int r) {
            radius = r;
        }
        int area() {
            return 3.14 * radius * radius;
        }
};

In this code, we have a base class "Shape" which has a pure virtual function "area()" declared in it. This means that the class Shape is an Abstract Base Class (ABC) and cannot be instantiated on its own.

Then we have two derived classes "Rectangle" and "Circle" which inherit from the base class "Shape". Both the derived classes have their implementation of the "area()" function. This is known as function overriding.

The classes "Rectangle" and "Circle" also have their constructors which take in different parameters. This is known as constructor overloading. The Rectangle class takes in two parameters, width and height, whereas the Circle class takes in one parameter, radius. These parameters are used to initialize the respective class's attributes.

Using polymorphism, we can create pointers or references of type Shape and point them to objects of the derived classes. This allows us to call the appropriate implementation of the "area()" function depending on the type of the object being pointed to.

Inheritance:

Inheritance is a mechanism in C++ that allows one class to inherit properties and methods from another class. This allows for code reusability and a more organized object-oriented design.

Before diving into the inheritance let us understand the working of the access specifiers:

Access SpecifierDescription
publicMembers declared as public can be accessed from anywhere.
protectedMembers declared as protected can be accessed within the same class, derived classes, and in the same package.
privateMembers declared as private can only be accessed within the same class.

It is important to note that access specifiers determine the scope and accessibility of class members. Public members have the widest scope and accessibility, while private members have the narrowest scope and accessibility.

Now let's dive deep into the world of inheritance; consider a class called Animals that has properties such as name, age, and weight, as well as methods such as eat() and sleep(). Another class, called Mammals, can be created that inherits from the Animals class. The Mammals class would automatically have access to the properties and methods defined in the Animals class, but can also have additional properties and methods specific to mammals.

class Animals {
  public:
    std::string name;
    int age;
    int weight;
    void eat() { /* code to make the animal eat */ }
    void sleep() { /* code to make the animal sleep */ }
};

class Mammals : public Animals {
  public:
    int numLegs;
    bool hasFur;
    void giveBirth() { /* code to make the mammal give birth */ }
};

int main() {
  Mammals lion;
  lion.name = "Simba";
  lion.age = 5;
  lion.weight = 200;
  lion.numLegs = 4;
  lion.hasFur = true;

  lion.eat();
  lion.sleep();
  lion.giveBirth();
  return 0;
}

In the above example, the class Mammals is inheriting properties and methods from the class Animals, which is represented by the keyword public before the class name Animals in the class definition of Mammals. Here the class mammal can use all the properties and methods of the class animal.

In this way, the class Mammals has inherited all the properties and methods of the class Animals and can also have additional properties and methods specific to mammals.

Examples:

#include <iostream>
using namespace std;

class employee
{
    int salary = 47;

public:
    employee()
    {
        cout << "The salary of this employee is " << salary << endl;
    }
};
/*This is the syntax of the inheritance of the classes

{{class}} {{derived_class_name}} : {{visibility}} {{base_class_name}}
{
    code
}:

"by default the visibility is private."
"You can not inherite the private members of the base class."
*/
class programmer : public employee
{
public:
    programmer()
    {
        cout << "The employee is a programmer " << endl;
    }
};
int main()
{
    employee e1;
    programmer p1;

    return 0;
}

This program defines two classes: employee and programmer. The employee class has a single data member salary which is set to 47. The class also has a default constructor which outputs the value of the salary. The programmer class is defined as a derived class of the employee class using the public inheritance. The programmer class also has a default constructor which outputs the message "The employee is a programmer". In the main function, an object of the employee class and an object of the programmer class is created. When the objects are created, their respective constructors are called and the output is displayed.

The output will be :

"The salary of this employee is 47"

"The employee is a programmer".

Inheritance with default constructors:

#include <iostream>
using namespace std;

class employee
{
    int salary = 100;

public:
    employee(int a) // This constructor is used by only the objects of class employee with the argument.
    {
        salary = a;
        cout << "The salary of the employee is " << salary << endl;
    }
    employee()
    {
        cout << "The default constructor of class employee has been invoked\n";
    } // This is a defalt constructor which is used by the object of class programmer on declaration
    ~employee()
    {
        cout << "The destructor of class employee has been invoked\n";
    }
};

class progammer : public employee // after the declaration of object of class progammer the default constructor of employee will be called  .
{
public:
    progammer()
    {
        cout << "This employee is programmer\n";
    }
    progammer(int b)
    {
        cout << "The programmer have id " << b << endl;
    }
    ~progammer()
    {
        cout << "The destructor of class programmer has been invoked\n";
    }
};

int main()
{
    // employee e1(20);
    progammer p1, p2(20);

    return 0;
}

This program defines two classes: employee and programmer. The employee class has two constructors: one that takes an integer argument and assigns it to the salary attribute, and one that is the default constructor. It also has a destructor that prints out a message when it is invoked. The programmer class inherits from the employee class and has two constructors: one that is the default constructor and one that takes an integer argument and prints it out. It also has a destructor that prints out a message when it is invoked.

In the main function, the program creates an object of the programmer class and calls the default constructor of the employee class, which is inherited by the programmer class. Then it creates another object of the programmer class, passing an argument of 20 to its constructor, which prints out the programmer's ID. The destructor of both classes will be invoked after the objects go out of scope.

#include <iostream>
using namespace std;

class base_class
{
private:
    int a;
    // The private memebers cannot be inherited to inherited 

protected:
    int b;
//The protected members be inherited but they are not accesseable to the any-other outsider function.
public:
    int c;
    base_class() {}
};

class derived1 : public base_class
{
    // In this case the public members of the base class are made public members of the derived1 class
    // Protected members of the base class are made protected members of the class derived1
};

class derived2 : private base_class
{
    // In this case the public members of the base class are made private members of the derived2 class
    // Protected members of the base class are made private members of the class derived2
};

class derived3 : protected base_class
{
    // In this case the public members of the base class are made protected members of the derived3 class
    // Protected members of the base class are made protected members of the derived3 class
};

int main()
{
    base_class p2;
    p2.c = 10;
    // p2.b;
    // This will not work since the protected members are similar to the private members the only difference is the protected memebers can be inherted
    return 0;
}

This code is self-explanatory now we move on to the next part of inheritance which is the types of inheritance.

Single Inheritance:

A single derived class inherits from a single base class. This is the simplest form of inheritance, where one class inherits the properties and behaviors of another class.

All of the examples were examples of single inheritance.

Multiple Inheritance:

Multiple inheritance refers to a feature in object-oriented programming languages where a single class can inherit characteristics from more than one base class. This allows a derived class to inherit the characteristics and behaviors of multiple parent classes.

In C++, multiple inheritance is implemented by having a derived class inherit from multiple base classes using the ":" operator. For example:

class Derived: public Base1, public Base2 {
   // class members 
};

Here, the Derived class inherits from both the Base1 and Base2 classes. This can lead to ambiguity if both base classes have members with the same name, which is resolved by using scope resolution operator (::) to specify which base class's member is being referred to.

Multiple inheritance can be useful in situations where a derived class needs to inherit characteristics from more than one base class, but it should be used with caution as it can lead to complexity and difficult-to-debug issues if not used properly.

It is important to carefully consider the design of the class hierarchy and inheritance relationships before implementing multiple inheritance in your code.

#include <iostream>
using namespace std;
class A {
  int id;
  char gender;
  string name;

public:
  void setdata(int id, char gender, string name) {
    this->id = id;
    this->gender = gender;
    this->name = name;
  }
  void getdata() {
    cout << "id: " << id << " gender: " << gender << " name: " << name << endl;
  }
};
class B {
  string Dept_name;
  string work;
  float time;

public:
  void setdata(string Dept_name, string work, float time) {
    this->Dept_name = Dept_name;
    this->work = work;
    this->time = time;
  }
  void getdata() {
    cout << "Dept_name: " << Dept_name << " work: " << work << " time: " << time
         << endl;
  }
};
class C : public A, public B {
public:
  void SetData() {
    A::setdata(1, 'M', "John");
    B::setdata("Engineering", "Software", 1.2);
  }
  void DISPLAY() {
    A::getdata();
    B::getdata();
  }
};
int main() {
  C obj;
  obj.SetData();
  obj.DISPLAY();
  return 0;
}

This code is defining a C++ program that demonstrates inheritance. Class A and B are base classes, and class C is a derived class that inherits from both classes A and B. The class C has a method SetData() that sets data for the member variables of both base classes, and a method DISPLAY() that prints the data of both base classes. Finally, the main function creates an object of class C and calls its SetData() and DISPLAY() methods. The output will be:

id: 1

gender: M

name: John

Dept_name: Engineering

work: Software

time: 1.2

 #include <iostream>
using namespace std;

class book {
public:
  void set_book(int a, int b, int c) {
    book_id = a;
    book_price = b;
    book_pages = c;
  }
  void show_book() {
    cout << "book id is: " << book_id << endl;
    cout << "book price is: " << book_price << endl;
    cout << "book pages is: " << book_pages << endl;
  }

private:
  int book_id;
  int book_price;
  int book_pages;
};
class author {
public:
  void set_author(string a, string b, string c) {
    author_name = a;
    author_email = b;
    author_gender = c;
  }
  void show_author() {
    cout << "author name is: " << author_name << endl;
    cout << "author email is: " << author_email << endl;
    cout << "author gender is: " << author_gender << endl;
  }

private:
  string author_name;
  string author_email;
  string author_gender;
};
class book_author : public book, public author {
public:
  void set_book_author(int a, int b, int c, string d, string e, string f) {
    set_book(a, b, c);
    set_author(d, e, f);
  }
  void show_book_author() {
    show_book();
    show_author();
  }
};
int main() {
  book_author b1;
  b1.set_book_author(1, 100, 200, "Atharv", "AtharvSankpal@gmail.com", "male");
  b1.show_book_author();
  return 0;
}

This code is defining a C++ program that demonstrates multiple inheritance. The class book has member variables book_id, book_price, and book_pages and methods to set and display these variables. The class author has member variables author_name, author_email, and author_gender and methods to set and display these variables. The class book_author is derived from both classes book and author and has a method set_book_author that sets data for both base classes and a method show_book_author that displays data of both base classes. The main function creates an object of class book_author and calls its set_book_author and show_book_author methods to set and display the data. The output will be:

book id is: 1

book price is: 100

book pages is: 200

author name is: Atharv

author email is:

author gender is: male

Multi-level Inheritance:

A derived class inherits from a base class, which in turn inherits from another base class. This creates a hierarchy of classes, with each class inheriting properties and behaviors from its parent class.

#include <iostream>
using namespace std;

class student
{
protected:
    int roll;
    int physics;
    int maths;

public:
    void getroll(int a)
    {
        roll = a;
    }
    void displayroll()
    {
        cout << "The roll no of this student is " << roll << endl;
    }
};

class marks : public student
{
public:
    void getmarks(int a, int b)
    {
        maths = a;
        physics = b;
    }
};

class result : public marks
{
public:
   void displayresult()
    {
        cout << "The marks in maths of the student " << roll << " are " << maths << endl;
        cout << "The marks in physics of the student " << roll << " are " << physics << endl;
    }
};

int main()
{
    result r1;
    r1.getroll(55);
    r1.displayroll();
    r1.getmarks(89,79);
    r1.displayresult();
    return 0;
}

This is a program in C++ that uses inheritance to create a class hierarchy. The class student is the base class and it has two protected data members roll, physics and maths and two member functions getroll() and displayroll().

The class marks is derived from the class student and it has one member function getmarks() which takes in two integers as arguments and assigns them to the data members maths and physics inherited from the base class.

The class result is derived from the class marks and it has one member function displayresult() which displays the values of the data members maths and physics inherited from the base class using the roll number.

In main function, an object of the class result is created and the member functions are called in the order they are used to demonstrate the working of the class hierarchy.

Hierarchical Inheritance:

#include <iostream>
using namespace std;

class base1
{
protected:
    int base1int;

public:
    void setdata1(int a)
    {
        base1int = a;
    }
    void showdata1()
    {
        cout << "The value of base1int is " << base1int << endl;
    }
};

class base2
{
protected:
    int base2int;

public:
    void setdata2(int a)
    {
        base2int = a;
    }
    void showdata2()
    {
        cout << "The data of base2int is " << base2int << endl;
    }
};

class derived : public base1, public base2
{
public:
    void showdataderived()
    {
        cout << "The data of base1int is " << base1int << endl;
        cout << "The data of base2int is " << base2int << endl;
        cout << "The addition of the data1int and data2int is " << base1int + base2int << endl;
    }
};

int main()
{
    derived a;
    a.setdata1(55);
    a.setdata2(33);
    a.showdata1();
    a.showdata2();
    a.showdataderived();
    return 0;
}

This is a program in C++ that demonstrates multiple inheritance. The program has three classes: base1, base2 and derived.

The class base1 has one protected data member base1int and two member functions setdata1() and showdata1(). The member function setdata1() assigns the value passed as an argument to the data member base1int while showdata1() displays the value of base1int.

Similarly, the class base2 has one protected data member base2int and two member functions setdata2() and showdata2(). The member function setdata2() assigns the value passed as an argument to the data member base2int while showdata2() displays the value of base2int.

The class derived is derived from the classes base1 and base2 and it has one member function showdataderived(). This function displays the values of the data members base1int and base2int inherited from the base classes and also displays the sum of the two values.

In the main function, an object of the class derived is created and the member functions of the base classes and derived class are called in the order they are used to demonstrate the working of the multiple inheritance.

Virtual Base Class:

#include <iostream>
using namespace std;

class student
{
protected:
    int roll;
    void showroll()
    {
        cout << "The roll number of the student is " << roll << endl;
    }

public:
    void setroll(int a)
    {
        roll = a;
    }
};

class theory : virtual public student
{
protected:
    int maths, cp, bet;
    void showtheory()
    {
        cout << "The marks obtained by the student with roll number " << roll << " in maths is " << maths << " in computer programming is " << cp << " and in basic electronics engineering is " << bet << endl;
    }

public:
    void settheory(int a, int b, int c)
    {
        maths = a;
        cp = b;
        bet = c;
    }
};

class lab : virtual public student
{
protected:
    int betlab;
    void showlab()
    {
        cout << "The marks obtained by the student with roll number " << roll << " in basic electronic laboratory is " << betlab << endl;
    }

public:
    void setlab(int a)
    {
        betlab = a;
    }
};

class result : public theory, public lab
{
    int total;

public:
    void showresult()
    {
        // showroll();
        // showtheory();
        // showlab();
        total = cp + maths + bet + betlab;
        cout << "The total marks obtained by the student with roll number " << roll << " is " << total << endl;
    }
};

int main()
{
    result r1;
    r1.setroll(840);
    r1.settheory(84, 87, 79);
    r1.setlab(45);
    r1.showresult();

    return 0;
}

This program demonstrates the use of virtual inheritance in C++. The program has four classes: student, theory, lab and result.

The class student has one protected data member roll and two member functions setroll() and showroll(). The member function setroll() assigns the value passed as an argument to the data member roll while showroll() displays the value of roll.

The class theory is derived from the class student using virtual inheritance. It has three protected data members maths, cp, and bet and two member functions settheory() and showtheory(). The member function settheory() assigns the values passed as arguments to the data members maths, cp and bet respectively while showtheory() displays the values of these data members.

The class lab is also derived from the class student using virtual inheritance. It has one protected data member betlab and two member functions setlab() and showlab(). The member function setlab() assigns the value passed as an argument to the data member betlab while showlab() displays the value of betlab.

The class result is derived from the classes theory and lab. It has one data member total and one member function showresult(). This function displays the total marks obtained by the student by adding the marks obtained in maths, computer programming, basic electronics engineering, and basic electronic laboratory. The roll number is also displayed here.

In the main function, an object of the class result is created and the member functions of the base classes are called in the order they are used to demonstrate the working of the multiple inheritance.

This keyword in C++

The this keyword in C++ is a pointer that holds the memory address of the current object. It is used to refer to the members of the current object within the class.

The this pointer is implicitly passed as a hidden argument to all non-static member functions. It is used to distinguish between the local variables and the class variables with the same name, giving priority to the class variable.

For example, in the following class:

class MyClass {
  int value;

public:
  void setValue(int value) {
    this->value = value;
  }

  int getValue() {
    return this->value;
  }
};

In the setValue(int value) function, the local variable "value" is given priority over the class variable "value" if not use this keyword. But by using the this pointer, the program can distinguish between the local variable "value" and the class variable "value", giving priority to the class variable.

In addition, the this pointer can also be used to pass the current object as an argument to a function or a constructor, or to return the current object from a function.

Example:

#include <iostream>
using namespace std;

class base_class
{
    int a;

public:
    void setdata(int a)
    {
        this->a = a;//The local variable is given priority but using this operator determine the variable of class
    }
    void getdata()
    {
        cout << "The value of a is " << a << endl;
    }
};

int main()
{
    base_class b1;
    b1.setdata(33);
    b1.getdata();
    return 0;
}

This program demonstrates the use of the this pointer in C++. The program has one class base_class with one private data member a and two member functions setdata() and getdata().

The member function setdata() assigns the value passed as an argument to the data member a using the this pointer. The this pointer is a pointer that holds the memory address of the current object. In this case, it points to the object of the class base_class that calls the setdata() function. By using the this pointer, the program can distinguish between the local variable a and the class variable a, giving priority to the class variable.

The member function getdata() displays the value of the data member a using the cout function.

In the main function, an object of the class base_class is created, and the member function setdata() is called with the value 33 as an argument. Then the member function getdata() is called, which displays the value of a as 33.

ย