Class

 

OOP stands for Object-Oriented Programming.

Procedural programming is about writing procedures or functions that perform operations on the data, while object-oriented programming is about creating objects that contain both data and functions.

Object-oriented programming has several advantages over procedural programming:

  • OOP is faster and easier to execute
  • OOP provides a clear structure for the programs
  • OOP helps to keep the C++ code DRY "Don't Repeat Yourself", and makes the code easier to maintain, modify and debug
  • OOP makes it possible to create full reusable applications with less code and shorter development time

C++ What are Classes and Objects?

Classes and objects are the two main aspects of object-oriented programming

A class is a template for objects, and an object is an instance of a class.

When the individual objects are created, they inherit all the variables and functions from the class.

C++ Class Definitions

In C++, the definition of a type—a class, struct, or record—is like a blueprint that specifies what the type can do. An object is basically a block of memory that has been allocated and configured according to the blueprint. 

A class definition starts with the keyword class followed by the class name; and the class body, enclosed by a pair of curly braces. A class definition must be followed either by a semicolon or a list of declarations. For example, we defined the Box data type using the keyword class as follows −

class Box {

   public:

      double length;   // Length of a box

      double breadth;  // Breadth of a box

      double height;   // Height of a box

};

Define C++ Objects

A class provides the blueprints for objects, so basically an object is created from a class. We declare objects of a class with exactly the same sort of declaration that we declare variables of basic types. Following statements declare two objects of class Box −

Box Box1;          // Declare Box1 of type Box
Box Box2;          // Declare Box2 of type Box

Both of the objects Box1 and Box2 will have their own copy of data members.

Accessing the Data Members

The public data members of objects of a class can be accessed using the direct member access operator (.). Let us try the following example to make the things clear 

#include <iostream>

using namespace std;

class Box {
   public:
      double length;   // Length of a box
      double breadth;  // Breadth of a box
      double height;   // Height of a box
};

int main() {
   Box Box1;        // Declare Box1 of type Box
   Box Box2;        // Declare Box2 of type Box
   double volume = 0.0;     // Store the volume of a box here
 
   // box 1 specification
   Box1.height = 5.0; 
   Box1.length = 6.0; 
   Box1.breadth = 7.0;

   // box 2 specification
   Box2.height = 10.0;
   Box2.length = 12.0;
   Box2.breadth = 13.0;
   
   // volume of box 1
   volume = Box1.height * Box1.length * Box1.breadth;
   cout << "Volume of Box1 : " << volume <<endl;

   // volume of box 2
   volume = Box2.height * Box2.length * Box2.breadth;
   cout << "Volume of Box2 : " << volume <<endl;
   return 0;
}

In C++, there are three access specifiers:

  • public - members are accessible from outside the class
  • private - members cannot be accessed (or viewed) from outside the class
  • protected - members cannot be accessed from outside the class, however, they can be accessed in inherited classes.
  • By default, all members of a class are private if you don't specify an access specifier

In the following example, we demonstrate the differences between public and private members:

Example

class MyClass {
  public:    // Public access specifier
    int x;   // Public attribute
  private:   // Private access specifier
    int y;   // Private attribute
};

int main() {
  MyClass myObj;
  myObj.x = 25;  // Allowed (public)
  myObj.y = 50;  // Not allowed (private)
  return 0;
}

Encapsulation

The meaning of Encapsulation, is to make sure that "sensitive" data is hidden from users. To achieve this, you must declare class variables/attributes as private (cannot be accessed from outside the class). If you want others to read or modify the value of a private member, you can provide public get and set methods.


Access Private Members

To access a private attribute, use public "get" and "set" methods:

Example

#include <iostream>
using namespace std;

class Employee {
  private:
    // Private attribute
    int salary;

  public:
    // Setter
    void setSalary(int s) {
      salary = s;
    }
    // Getter
    int getSalary() {
      return salary;
    }
};

int main() {
  Employee myObj;
  myObj.setSalary(50000);
  cout << myObj.getSalary();
  return 0;
}

Inheritance

In C++, it is possible to inherit attributes and methods from one class to another. We group the "inheritance concept" into two categories:

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

To inherit from a class, use the : symbol.

In the example below, the Car class (child) inherits the attributes and methods from the Vehicle class (parent):

Example

// Base class
class Vehicle {
  public:
    string brand = "Ford";
    void honk() {
      cout << "Tuut, tuut! \n" ;
    }
};

// Derived class
class Car: public Vehicle {
  public:
    string model = "Mustang";
};

int main() {
  Car myCar;
  myCar.honk();
  cout << myCar.brand + " " + myCar.model;
  return 0;
}

Multilevel Inheritance

A class can also be derived from one class, which is already derived from another class.

In the following example, MyGrandChild is derived from class MyChild (which is derived from MyClass).

Example

// Base class (parent)
class MyClass {
  public:
    void myFunction() {
      cout << "Some content in parent class." ;
    }
};

// Derived class (child)
class MyChild: public MyClass {
};

// Derived class (grandchild)
class MyGrandChild: public MyChild {
};

int main() {
  MyGrandChild myObj;
  myObj.myFunction();
  return 0;}

Multiple Inheritance

A class can also be derived from more than one base class, using a comma-separated list:

Example

// Base class
class MyClass {
  public:
    void myFunction() {
      cout << "Some content in parent class." ;
    }
};

// Another base class
class MyOtherClass {
  public:
    void myOtherFunction() {
      cout << "Some content in another class." ;
    }
};

// Derived class
class MyChildClass: public MyClass, public MyOtherClass {
};

int main() {
  MyChildClass myObj;
  myObj.myFunction();
  myObj.myOtherFunction();
  return 0;
}

Polymorphism

Polymorphism means "many forms", and it occurs when we have many classes that are related to each other by inheritance.

Like we specified in the previous chapter; Inheritance lets us inherit attributes and methods from another class. Polymorphism uses those methods to perform different tasks. This allows us to perform a single action in different ways.

Why Polymorphism?

Polymorphism allows us to create consistent code. For example,

Suppose we need to calculate the area of a circle and a square. To do so, we can create a Shape class and derive two classes Circle and Square from it.

In this case, it makes sense to create a function having the same name calculateArea() in both the derived classes rather than creating functions with different names, thus making our code more consistent.

Another example, think of a base class called Animal that has a method called animalSound(). Derived classes of Animals could be Pigs, Cats, Dogs, Birds - And they also have their own implementation of an animal sound (the pig oinks, and the cat meows, etc.):

Example

// Base class
class Animal {
  public:
    void animalSound() {
      cout << "The animal makes a sound \n";
    }
};

// Derived class
class Pig : public Animal {
  public:
    void animalSound() {
      cout << "The pig says: wee wee \n";
    }
};

// Derived class
class Dog public Animal {
  public:
    void animalSound() {
      cout << "The dog says: bow wow \n";
    }
};

Remember from the Inheritance chapter that we use the : symbol to inherit from a class.

Now we can create Pig and Dog objects and override the animalSound() method:

Example

// Base class
class Animal {
  public:
    void animalSound() {
      cout << "The animal makes a sound \n";
    }
};

// Derived class
class Pig : public Animal {
  public:
    void animalSound() {
      cout << "The pig says: wee wee \n";
    }
};

// Derived class
class Dog public Animal {
  public:
    void animalSound() {
      cout << "The dog says: bow wow \n";
    }
};

int main() {
  Animal myAnimal;
  Pig myPig;
  Dog myDog;

  myAnimal.animalSound();
  myPig.animalSound();
  myDog.animalSound();
  return 0;
}

We can implement polymorphism in C++ using the following ways:

  1. Function overloading
  2. Operator overloading
  3. Function overriding
  4. Virtual functionsIn C++

C++ Function Overloading
In C++, we can use two functions having the same name if they have different parameters (either types or number of arguments).

And, depending upon the number/type of arguments, different functions are called. For example,
// C++ program to overload sum() function

#include <iostream>
using namespace std;

// Function with 2 int parameters
int sum(int num1, int num2) {
    return num1 + num2;
}

// Function with 2 double parameters
double sum(double num1, double num2) {
    return num1 + num2;
}

// Function with 3 int parameters
int sum(int num1, int num2, int num3) {
    return num1 + num2 + num3;
}

int main() {
    // Call function with 2 int parameters
    cout << "Sum 1 = " << sum(5, 6) << endl;

    // Call function with 2 double parameters
    cout << "Sum 2 = " << sum(5.5, 6.6) << endl;

    // Call function with 3 int parameters
    cout << "Sum 3 = " << sum(5, 6, 7) << endl;

    return 0;
}
Here, we have created 3 different sum() functions with different parameters (number/type of parameters). And, based on the arguments passed during a function call, a particular sum() is called.

It's a compile-time polymorphism because the compiler knows which function to execute before the program is compiled.

C++ Operators Overloading

We can change the way operators work for user-defined types like objects and structures. This is known as operator overloading. For example,

Suppose we have created three objects c1, c2 and result from a class named Complex that represents complex numbers.

Since operator overloading allows us to change how operators work, we can redefine how the + operator works and use it to add the complex numbers of c1 and c2 by writing the following code:

result = c1 + c2

Operator overloading is a compile-time polymorphism in which the operator is overloaded to provide the special meaning to the user-defined data type. The advantage of Operators overloading is to perform different operations on the same operand.

Operator that cannot be overloaded are as follows:

  • Scope operator (::)
  • Sizeof
  • member selector(.)
  • member pointer selector(*)
  • ternary operator(?:)
C++ Function Overriding

In C++ inheritance, we can have the same function in the base class as well as its derived classes.

When we call the function using an object of the derived class, the function of the derived class is executed instead of the one in the base class.

So, different functions are executed depending on the object calling the function.

This is known as function overriding in C++.

Example:
// C++ program to demonstrate function overriding

#include <iostream>
using namespace std;

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

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

int main() {
    Derived derived1;

    // Call print() function of Derived class
    derived1.print();

    return 0;
}

When we call print() using the Derived object derived1, it overrides the print() function of Base by executing the print() function of the Derived class.

It's a runtime polymorphism because the function call is not resolved by the compiler, but it is resolved in the runtime instead.

C++ Virtual Functions
In C++, we may not be able to override functions if we use a pointer of the base class to point to an object of the derived class.

Using virtual functions in the base class ensures that the function can be overridden in these cases.

Thus, virtual functions actually fall under function overriding. For example,
// C++ program to demonstrate the use of virtual functions

#include <iostream>
using namespace std;

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

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

int main() {
    Derived derived1;

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

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

    return 0;
}
Output: Derived Function
Here, we have used a virtual function print() in the Base class to ensure that it is overridden by the function in the Derived class.

Virtual functions are runtime polymorphism.

Constructors

A constructor in C++ is a special method that is automatically called when an object of a class is created.

To create a constructor, use the same name as the class, followed by parentheses ():

Example

class MyClass {     // The class
  public:           // Access specifier
    MyClass() {     // Constructor
      cout << "Hello World!";
    }
};

int main() {
  MyClass myObj;    // Create an object of MyClass (this will call the constructor)
  return 0;
}

A constructor with no parameters is known as a default constructor.

Example:

// C++ program to demonstrate the use of default constructor

#include <iostream>

using namespace std;


// declare a class

class  Wall {

  private:

    double length;


  public:

    // default constructor to initialize variable

    Wall() {

      length = 5.5;

      cout << "Creating a wall." << endl;

      cout << "Length = " << length << endl;

    }

};

int main() {

  Wall wall1;

  return 0;

}

A constructor with parameters is known as a parameterized constructor. This is the preferred method to initialize member data.

Example:

// C++ program to calculate the area of a wall


#include <iostream>

using namespace std;


// declare a class

class Wall {

  private:

    double length;

    double height;


  public:

    // parameterized constructor to initialize variables

    Wall(double len, double hgt) {

      length = len;

      height = hgt;

    }


    double calculateArea() {

      return length * height;

    }

};


int main() {

  // create object and initialize data members

  Wall wall1(10.5, 8.6);

  Wall wall2(8.5, 6.3);


  cout << "Area of Wall 1: " << wall1.calculateArea() << endl;

  cout << "Area of Wall 2: " << wall2.calculateArea();


  return 0;

}

C++ Destructor

A destructor works opposite to constructor; it destructs the objects of classes. It can be defined only once in a class. Like constructors, it is invoked automatically.

A destructor is defined like constructor. It must have same name as class. But it is prefixed with a tilde sign (~).

Note: C++ destructor cannot have parameters. Moreover, modifiers can't be applied on destructors.

C++ this Pointer

In C++ programming, 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.

Example:

Let's see the example of this keyword in C++ that refers to the fields of current class.

#include <iostream>  

using namespace std;  

class Employee {  

   public:  

       int id; //data member (also instance variable)      

       string name; //data member(also instance variable)  

       float salary;  

       Employee(int id, string name, float salary)    

        {    

             this->id = id;    

            this->name = name;    

            this->salary = salary;   

        }    

       void display()    

        {    

            cout<<id<<"  "<<name<<"  "<<salary<<endl;    

        }    

};  

int main(void) {  

    Employee e1 =Employee(101, "Anita", 890000); //creating an object of Employee   

    Employee e2=Employee(102, "Nakul", 59000); //creating an object of Employee  

    e1.display();    

    e2.display();    

    return 0;  

}  

Ref:

https://www.w3schools.com/cpp/cpp_polymorphism.asp

https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/object-oriented/ 

https://www.tutorialspoint.com/cplusplus/cpp_classes_objects.htm

https://www.w3schools.com/cpp/cpp_access_specifiers.asp

https://www.programiz.com/cpp-programming/polymorphism

https://www.programiz.com/cpp-programming/constructors

https://www.javatpoint.com/cpp-destructor

https://www.javatpoint.com/cpp-this-pointer