Master Computer Science The Smart Way

OOPs Concepts in Depth (with Examples)

OOPs Concepts in Depth (with Examples)
0

C++ What is OOP?

OOP stands for Object-Oriented Programming.

Object-oriented programming is about creating “objects”, which can hold data and functions that work on that data.


Advantages of OOP

  • OOP provides a clear structure to programs
  • Makes code easier to maintain, reuse, and debug
  • Helps keep your code DRY (Don’t Repeat Yourself)
  • Makes it possible to create full reusable applications with less code and shorter development time

Tip: The DRY principle means you should avoid writing the same code more than once. Move repeated code into functions or classes and reuse it.


What are Classes and Objects?

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

A class defines what an object should look like, and an object is created based on that class. For example:

ClassObjects
FruitApple, Banana, Mango
CarVolvo, Audi, Toyota

When you create an object from a class, it inherits all the variables and functions defined inside that class.

In the next chapters, you will learn how to:

  • Define a class
  • Create objects
  • Access class members
  • And much more

Procedural vs Object-Oriented Programming

Procedural programming is about writing functions that operate on data.

Object-oriented programming (OOP) is about creating objects that contain both the data and the functions.

In procedural programming, the code is organized around functions.
In object-oriented programming, the code is organized around objects.

C++ Classes and Objects

In Object Oriented Programming, classes and objects are basic concepts of that are used to represent real-world concepts and entities.

  • A class is a template to create objects having similar properties and behavior, or in other words, we can say that a class is a blueprint for objects.
  • An object is an instance of a class. For example, the animal type Dog is a class, while a particular dog named Tommy is an object of the Dog class.

C++ Classes

A class is a user-defined data type, which holds its own data members and member functions that can be accessed and used by creating an instance of that class. A C++ class is like a blueprint for an object.

Create a Class : A class must be defined before its use. C++ class is defined using the keyword class keyword.

#include <iostream>
using namespace std;
// Class definition
class GfG
{
  public:
    // Data member
    int val;
    // Member function
    void show()
    {
        cout << "Value: " << val << endl;
    }
};
int main()
{
    // Object will declareed here
    return 0;
}

In the above, GfG class is created with a data member val and member function show(). Here, member function is defined inside the class, but they can also be just declared in the class and then defined outside using scope resolution operator ::

The above is called class definition or template.

C++ Objects

When a class is defined, only the specification (attributes and behaviour) for the object is defined. No memory is allocated to the class definition. To use the data and access functions defined in the class, we need to create its objects.

Objects are the actual entities that are created as an instance of a class. There can be as many objects of a class as desired. For example, in the above, we discussed the class of Cars. If we create an actual car based on the properties of the Car class, the car we made is the object of that class.

Create Object : Once the class is defined, we can create its object in the same way we declare the variables of any other inbuilt data type.

  • An object is created by declaring it with the class name followed by the object name, like className objectName;.

Member Access : Members of the class can be accessed inside the class itself simply by using their assigned name.

  • To access them outside, the (.) dot operatoris used with the object of the class.
  • Class members are accessed through the object using object.member for variables and object.member() for functions.

Local Class

Classes are generally declared in global scope and are accessible to every function or other classes once they are defined. But C++ also provides facility to define a class within a function. It is called local class in C++ and is only accessible in that function.

Nested Class

nested class is a class defined within another enclosing class. As a member of the enclosing class, it has the same access rights as any other member. The members of the enclosing class do not have special access to the members of the nested class; the standard access rules apply.

#include <iostream>
using namespace std;
class Outer
{
  public:
    // Nested class inside Outer
    class Inner
    {
      public:
        void display()
        {
            cout << "This is the Inner class" << endl;
        }
    };
    void show()
    {
        cout << "This is the Outer class" << endl;
    }
};
int main()
{
    // Creating object of Outer class
    Outer outerObj;
    outerObj.show();
    // Creating object of Inner class using Outer
    Outer::Inner innerObj;
    innerObj.display();
    return 0;
}

Output

This is the Outer class
This is the Inner class

Enum Class

Enum classes in C++ are a safer and more organized way of using enums. They help to group related constants together while avoiding naming problems and ensuring better type safety.

Class vs Object

The following table lists the primary differences between the classes and objects in C++:

ClassObject
A blueprint or template for creating objects.An instance of a class with actual values.
No memory is allocated for a class until an object is created.Memory is allocated when an object is created.
Conceptual entity describing structure and behaviour.A real-world entity created from the class.
Defines properties and functions common to all objects of that type.Stores specific data and manipulates it using class functions.
Represents a general concept or type.Represents a specific instance of the class.

C++ Class Methods

Class is a blueprint of an object, which has data members and member functions also known as methods. A method is a procedure or function in the OOP concept. A method is a function that belongs to a class.

There are two ways to define a procedure or function that belongs to a class:

  • Inside Class Definition
  • Outside Class Definition

1. Inside Class Definition

When a member function is defined directly inside the class definition, it becomes part of the class itself. Public member functions can be accessed using the class object and the dot (.) operator, just like public data members.

Syntax:

class class_name{
public:
return_type Method_name() // method inside class definition
{
// body of member function
}
};

Example:

#include <iostream>
using namespace std;
class rectangle {
private:
    int length;
    int breadth;
public:
    // Constructor
    rectangle(int length, int breadth){
        this->length = length; 
        this->breadth = breadth;
    }
    // area() function inside class
    int area() { return (length * breadth); }
    // perimeter() function outside class
    int perimeter() { return 2 * (length + breadth); }
};
int main(){
    // Creating object
    rectangle r(2, 3);
    cout << "perimeter: " << r.perimeter() << endl;
    cout << "area: " << r.area() << endl;
    return 0;
}

Output

perimeter: 10
area: 6

Note: this-> keyword is used to distinguish the class data members (length and breadth) from the constructor parameters with the same names. Here, this refers to the current object, so “this->length = length;” assigns the parameter value to the object’s data member, avoiding naming ambiguity.

2. Outside Class Definition

The member function is defined outside the class definition it can be defined using the scope resolution operator. Similar to accessing a data member in the class we can also access the public member functions through the class object using the dot operator (.).

Syntax:

class Class_name{
public:
return_type Method_name(); // method outside class definition
};

// Outside the Class using scope resolution operator
return_type Class_name :: Method_name() {
// body of member function
}

Example: In the following code, a rectangle class, in which member function area() and member function perimeter() is defined outside the class by using the scope resolution operator.

#include <iostream>
using namespace std;
class rectangle {
private:
    int length;
    int breadth;
public:
    // Constructor
    rectangle(int length, int breadth){
        this->length = length; 
        this->breadth = breadth;
    }
    // area() function defined outside the class
    int area();
    // perimeter() function defined outside the class
    int perimeter();
};
// function defining using scope resolution operator "::"
int rectangle::area() { return (length * breadth); }
int rectangle::perimeter(){
    return 2 * (length + breadth);
}
int main(){
    // Creating object
    rectangle r(2, 3);
    cout << "perimeter: " << r.perimeter() << endl;
    cout << "area: " << r.area() << endl;
    return 0;
}

Output

perimeter: 10
area: 6

C++ Constructors

 Constructors in C++ classes!

Have you ever wondered how objects in your code are created and initialized? This is where constructors come into play. Constructors are special functions that are automatically called when an object of a class is created. They help set up the object with initial values and are essential for managing resources efficiently. In this lesson, our goal is to understand different types of constructors in C++: defaultparameterized, and copy constructors, and learn how to implement them in a class.

Understanding Constructors

So, what exactly is a constructor? A constructor is a special member function of a class that initializes objects. It has the same name as the class and does not have a return type, not even void.

Think of a constructor like setting up a new house. When you move in, you need to set up the furniture before you can comfortably live in it. Similarly, when an object is created, a constructor sets up the initial state of the object.

Example of a Default Constructor

default constructor is a constructor that either has no parameters or has parameters with default values. Its primary purpose is to initialize objects with default settings.

Let’s see how to write a default constructor using an example:

C++Copy to clipboard#include <iostream>

class MyClass {
public:
    // Default constructor
    MyClass() {
        std::cout << "Default constructor called!" << std::endl;
    }
};

int main() {
    MyClass obj; // Default constructor is called here
    return 0;
}

In this example, when we create an object obj of MyClass, the default constructor is called, displaying the message “Default constructor called!”.

Parameterized Constructor

Parameterized constructors help when you need to initialize objects with specific values. These constructors accept arguments to initialize an object with provided values.

Let’s extend our previous example:

C++Copy to clipboard#include <iostream>

class MyClass {
public:
    int value;

    // Default constructor
    MyClass() {
        value = 0;
        std::cout << "Default constructor called!" << std::endl;
    }

    // Parameterized constructor
    MyClass(int param) {
        value = param;
        std::cout << "Parameterized constructor called! Value: " << value << std::endl;
    }
};

int main() {
    MyClass obj1; // Default constructor is called
    MyClass obj2(100); // Parameterized constructor is called
    return 0;
}

Here, obj1 uses the default constructor, and obj2 uses the parameterized constructor to initialize the value to 100.

This Keyword

In C++, this is a keyword that refers to the current instance of the class. Inside a class member function, this can be used to reference the calling object’s members. This is particularly useful in constructors to avoid naming conflicts between parameters and class members.

Let’s consider an example:

C++Copy to clipboard#include <iostream>
#include <string>

class BankAccount {
public:
    std::string accountHolderName;
    int accountNumber;
    double balance;

    BankAccount(std::string param1, int param2, double param3) {
        accountHolderName = param1;
        accountNumber = param2;
        balance = param3;
    }
};

int main() {
    BankAccount acc("John Doe", 123456, 1000.50);
    std::cout << "Account Holder: " << acc.accountHolderName << ", Account Number: " << acc.accountNumber << ", Balance: " << acc.balance << std::endl;
    return 0;
}

Here, naming parameters param1param2 and param3 is confusing and doesn’t reflect the meaning of the variables. However, we can’t call them accountHolderNameaccountNumber and balance, because it will cause naming conflict between the attributes and the parameters.

We can solve this problem using this keyword:

C++Copy to clipboard#include <iostream>
#include <string>

class BankAccount {
public:
    std::string accountHolderName;
    int accountNumber;
    double balance;

    // Parameterized constructor using 'this' keyword
    BankAccount(std::string accountHolderName, int accountNumber, double balance) {
        this->accountHolderName = accountHolderName;
        this->accountNumber = accountNumber;
        this->balance = balance;
    }
};

int main() {
    BankAccount acc("John Doe", 123456, 1000.50);
    std::cout << "Account Holder: " << acc.accountHolderName << ", Account Number: " << acc.accountNumber << ", Balance: " << acc.balance << std::endl;
    return 0;
}

In this example, this->accountHolderName specifies that we are referring to the class member accounHolderName instead of the constructor parameter accounHolderName. This way, we can call parameters the same way as the class members, making the code clearer.

Copy Constructor

copy constructor is used to initialize an object by copying another object of the same class. It is essential when you need to create a copy of an existing object.

Here’s how a copy constructor works:

C++Copy to clipboard#include <iostream>

class MyClass {
public:
    int value;

    // Default constructor
    MyClass() {
        value = 0;
        std::cout << "Default constructor called!" << std::endl;
    }

    // Parameterized constructor
    MyClass(int value) {
        this->value = value;
        std::cout << "Parameterized constructor called! Value: " << value << std::endl;
    }

    // Copy constructor
    MyClass(const MyClass &obj) {
        value = obj.value;
        std::cout << "Copy constructor called! Value: " << value << std::endl;
    }
};

int main() {
    MyClass obj1(100); // Parameterized constructor is called
    MyClass obj2 = obj1; // Copy constructor is called
    return 0;
}

Output:

Copy to clipboardParameterized constructor called! Value: 100
Copy constructor called! Value: 100

In this example, obj2 is created as a copy of obj1 using the copy constructor. The value of obj1 is copied to obj2.

Defining Constructors Outside the Class

Just like member functions, constructors can also be defined outside the class. Here is an example:

C++Copy to clipboard#include <iostream>

class Demo {
public:
    int value;
    Demo();
};

Demo::Demo() {
    value = 42;
    std::cout << "Constructor defined outside the class. Value: " << value << std::endl;
}

int main() {
    Demo demoObj;
    return 0;
}

In this example, the constructor for the Demo class is defined outside the class using the scope resolution operator ::. When demoObj is created, the constructor is called and initializes value to 42.

Member Initializer List

C++ also allows constructors to initialize members using a member initializer list. Here’s an example:

C++Copy to clipboard#include <iostream>

class Wheel {
public:
    int size;

    // Constructor using member initializer list
    Wheel(int s) : size(s) {
        std::cout << "Wheel size: " << size << std::endl;
    }
};

int main() {
    Wheel myWheel(15); // Member initializer list sets the size
    return 0;
}

Output:

Copy to clipboardWheel size: 15

In this example, Wheel(int s) : size(s) {} is a constructor that uses the member initializer list to assign the value of s to the member size. This can be more efficient and is often used to initialize constant members or base classes in derived classes.

Comparison of Constructor Types

Let’s quickly compare the three types of constructors:

  • Default Constructor:
    • Initializes an object with default settings.
    • No parameters.
  • Parameterized Constructor:
    • Initializes an object with specific values.
    • Accepts arguments.
  • Copy Constructor:
    • Initializes an object by copying an existing object.
    • Takes a reference to an object of the same class as a parameter.

Each type has its unique use case and is crucial for effective object initialization and management.

C++ Access Specifiers

What are Access Specifiers?

In C++ access specifiers are keywords that decide how easily class elements, like data members and member functions can be reached. They manage which sections of a class are open, to parts of the program defining the degree of encapsulation and visibility.

C++ provides three types of access specifiers:

  • Public
  • Private
  • Protected

Types of Access Specifiers

Public

Public members can be reached from any part of the program outside the class and its subclasses.

Private

Private members are accessible only within the class they are declared in. They cannot be accessed by derived classes or other parts of the program, ensuring data hiding and encapsulation.

Protected

Protected members are like members but can also be accessed by classes that inherit from them. They are kept hidden from the rest of the program. Can be utilized in inheritance.

When a class is inherited the access specifier determines how the derived class interacts, with the base class members.

Example of Access Specifiers

class MyClass {
public:
    int publicVar;      // Public member

protected:
    int protectedVar;   // Protected member

private:
    int privateVar;     // Private member
};

int main() {
    MyClass obj;
    obj.publicVar = 10; // Accessible and modifiable
    // obj.protectedVar = 20; --> Inaccessible and not modifiable directly
    // obj.privateVar = 30; --> Inaccessible and not modifiable
    return 0;
}

In this case publicVar can be accessed from any location. Privatevar is limited to use within the class. On the hand protectedVar can be accessed within the class and any classes derived from it.

Importance of Access Specifiers in OOP

Access specifiers are crucial in object-oriented programming (OOP) as they control the visibility and accessibility of class members, supporting encapsulation and inheritance.

  • Encapsulation
    Encapsulation hides the internal implementation details of a class from outside access. Access specifiers like private protect the internal state of an object, ensuring data security and consistency.
  • Inheritance
    Inheritance allows new classes to inherit properties from existing ones. Access specifiers like protected enable derived classes to access certain members of the base class, promoting code reuse.

Public Access Specifier

Definition and Usage

The public access modifier enables class elements to be accessed from, in the program. It comes in handy when designing interfaces that can be readily used by classes or sections of code.

Example

class Rectangle {
public:
    int length;
    int width;

    // Public member function to calculate area
    int calculateArea() {
        return length * width;
    }
};

int main() {
    Rectangle myRectangle;
    myRectangle.length = 5;
    myRectangle.width = 3;
    int area = myRectangle.calculateArea();
    std::cout << "Area: " << area << std::endl;
    return 0;
}

In this instance the measurements of length and width are considered attributes that are accessible and alterable directly. Additionally the calculateArea() method is accessible, to the public. Can be invoked from external sources.

Advantages of Using Public Functions

  • Enhanced Accessibility; Public functions are easily accessible from any section of the program simplifying interaction with the class.
  • Improved Code Reusability; Public functions can be utilized across sections of the program minimizing the necessity for repeating code.
  • Secured Encapsulation; Public functions offer regulated access, to a class state ensuring that implementation details are kept confidential and safeguarded.

Private Access Specifier

The private access specifier limits the access to class members making them accessible, within the class. This helps in keeping data and functions secure and safeguarded from unauthorized changes or access.

C++ Encapsulation

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.


Real-Life Example

Think of an employee’s salary:

  • The salary is private – the employee can’t change it directly
  • Only their manager can update it or share it when appropriate

Encapsulation works the same way. The data is hidden, and only trusted methods can access or modify it.


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;
}

Example explained

  • salary is private – it cannot be accessed directly
  • setSalary() sets the value
  • getSalary() returns the value

We use myObj.setSalary(50000) to assign a value, and myObj.getSalary() to print it.


Why Encapsulation?

  • It is considered good practice to declare your class attributes as private (as often as you can). Encapsulation ensures better control of your data, because you (or others) can change one part of the code without affecting other parts
  • Increased security of data

C++ Inheritance

One of the most important concepts in object-oriented programming is that of inheritance. Inheritance allows us to define a class in terms of another class, which makes it easier to create and maintain an application. This also provides an opportunity to reuse the code functionality and fast implementation time.

When creating a class, instead of writing completely new data members and member functions, the programmer can designate that the new class should inherit the members of an existing class. This existing class is called the base class, and the new class is referred to as the derived class.

The idea of inheritance implements the is a relationship. For example, mammal IS-A animal, dog IS-A mammal hence dog IS-A animal as well and so on.

Base and Derived Classes

A class can be derived from more than one classes, which means it can inherit data and functions from multiple base classes. To define a derived class, we use a class derivation list to specify the base class(es). A class derivation list names one or more base classes and has the form −

classderived-class: access-specifier base-class

Where access-specifier is one of public, protected, or private, and base-class is the name of a previously defined class. If the access-specifier is not used, then it is private by default.

Consider a base class Shape and its derived class Rectangle as follows −

#include <iostream>usingnamespace std;// Base classclassShape{public:voidsetWidth(int w){
         width = w;}voidsetHeight(int h){
         height = h;}protected:int width;int height;};// Derived classclassRectangle:public Shape{public:intgetArea(){return(width * height);}};intmain(void){
   Rectangle Rect;
 
   Rect.setWidth(5);
   Rect.setHeight(7);// Print the area of the object.
   cout <<"Total area: "<< Rect.getArea()<< endl;return0;}

When the above code is compiled and executed, it produces the following result −

Total area: 35

Access Control and Inheritance

A derived class can access all the non-private members of its base class. Thus base-class members that should not be accessible to the member functions of derived classes should be declared private in the base class.

We can summarize the different access types according to – who can access them in the following way −

Accesspublicprotectedprivate
Same classyesyesyes
Derived classesyesyesno
Outside classesyesnono

A derived class inherits all base class methods with the following exceptions −

  • Constructors, destructors and copy constructors of the base class.
  • Overloaded operators of the base class.
  • The friend functions of the base class.

Type of Inheritance

When deriving a class from a base class, the base class may be inherited through public, protected or private inheritance. The type of inheritance is specified by the access-specifier as explained above.

We hardly use protected or private inheritance, but public inheritance is commonly used. While using different type of inheritance, following rules are applied −

  • Public Inheritance − When deriving a class from a public base class, public members of the base class become public members of the derived class and protected members of the base class become protected members of the derived class. A base class’s private members are never accessible directly from a derived class, but can be accessed through calls to the public and protected members of the base class.
  • Protected Inheritance − When deriving from a protected base class, public and protected members of the base class become protected members of the derived class.
  • Private Inheritance − When deriving from a private base class, public and protected members of the base class become private members of the derived class.

Multiple Inheritance

A C++ class can inherit members from more than one class using multiple inheritance. Multiple inheritance is a feature that allows a class to inherit from more than one base class, which means a derived class can have multiple parent classes and inherit attributes and behaviors from all the base classes.

and here is the extended syntax −

class derived-class: access baseA, access baseB....

Where access is one of public, protected, or private and would be given for every base class and they will be separated by comma as shown above. Let us try the following example −

#include <iostream>usingnamespace std;// Base class ShapeclassShape{public:voidsetWidth(int w){
         width = w;}voidsetHeight(int h){
         height = h;}protected:int width;int height;};// Base class PaintCostclassPaintCost{public:intgetCost(int area){return area *70;}};// Derived classclassRectangle:public Shape, public PaintCost{public:intgetArea(){return(width * height);}};intmain(void){
   Rectangle Rect;int area;
 
   Rect.setWidth(5);
   Rect.setHeight(7);

   area = Rect.getArea();// Print the area of the object.
   cout <<"Total area: "<< Rect.getArea()<< endl;// Print the total cost of painting
   cout <<"Total paint cost: $"<< Rect.getCost(area)<< endl;return0;}

When the above code is compiled and executed, it produces the following result −

Total area: 35
Total paint cost: $2450

C++ Polymorphism

Object-Oriented Programming (OOP). Understanding polymorphism empowers us to utilize a single interface to represent different types in various situations. Let’s get started.

Polymorphism: A Powerful OOP Principle

Polymorphism, one of the core principles of OOP, allows an object to take on multiple forms. Imagine a button in software; its behavior changes based on its type (e.g., a submit button versus a radio button). This dynamic showcases the essence of polymorphism!

Seeing Polymorphism in Action

Let’s observe polymorphism in action through a simple application involving shapes. In the base Shape class, we define a pure virtual area method and a virtual destructor. The area method is uniquely implemented in the derived classes Rectangle and Circle, while the virtual destructor ensures that the destructors of derived classes are called appropriately, preventing resource leaks.

C++Copy to clipboard#include <iostream>
using namespace std;

class Shape {
public:
    virtual ~Shape() {} // virtual destructor
    virtual double area() const = 0; // pure virtual function
};

class Rectangle : public Shape {
private:
    double length, width;
public:
    Rectangle(double l, double w) : length(l), width(w) {}
    
    double area() const override { // calculate rectangle area
        return length * width;
    }
};

class Circle : public Shape {
private:
    double radius;
public:
    Circle(double r) : radius(r) {}
    
    double area() const override { // calculate circle area
        return 3.14 * radius * radius;
    }
};

int main() {
    Rectangle rectangle(2, 3);
    cout << rectangle.area() << endl; // Outputs: 6

    Circle circle(5);
    cout << circle.area() << endl; // Outputs: 78.5

    return 0;
}

In this example, polymorphism is demonstrated as the area function takes multiple forms and behaves differently based on whether it’s attached to a Rectangle or a Circle. The inclusion of a virtual destructor in the Shape class ensures that when a derived object is deleted through a base pointer, the correct destructor is invoked, reflecting proper resource management and preventing memory leaks.

Dynamic Polymorphism: Runtime Method Overriding

C++ supports polymorphism through the use of virtual functions. Dynamic polymorphism occurs during runtime and involves method overriding within base and derived classes. Here’s an example of implementing a simple shape hierarchy using virtual functions:

C++Copy to clipboard#include <iostream>
using namespace std;

class Shape {
public:
    virtual double area() const {
        return 0;
    }
};

class Rectangle : public Shape {
private:
    double length, width;
public:
    Rectangle(double l, double w) : length(l), width(w) {}

    double area() const override {
        return length * width;
    }
};

class Circle : public Shape {
private:
    double radius;
public:
    Circle(double r) : radius(r) {}

    double area() const override {
        return 3.14 * radius * radius;
    }
};

void printArea(const Shape& shape) {
    cout << "Area: " << shape.area() << endl;
}

int main() {
    Shape* rectangle = new Rectangle(2, 3);
    Shape* circle = new Circle(5);
    printArea(*rectangle); // Output: Area: 6
    printArea(*circle);    // Output: Area: 78.5
    return 0;
}

In the above snippet, the printArea function exemplifies the added value of polymorphism by allowing us to pass any derived Shape object and print its area without knowing the object’s specific type.

Static Polymorphism: Templates and Function Overloading

Apart from dynamic polymorphism, C++ also supports static polymorphism, which is resolved at compile time. Two popular mechanisms to achieve static polymorphism are function overloading and templates.

Function overloading allows functions to have the same name but with different parameter types or numbers:

C++Copy to clipboard#include <iostream>
using namespace std;

// Overloaded functions for displaying details
void display(int i) {
    cout << "Integer: " << i << endl;
}

void display(double d) {
    cout << "Double: " << d << endl;
}

int main() {
    display(5);    // Calls display(int)
    display(3.14); // Calls display(double)

    return 0;
}

In this example, the display function is overloaded to handle both integers and doubles, demonstrating static polymorphism by resolving the correct function at compile time.

On the other hand, Templates enable generic programming, where functions or classes can operate with different data types:

C++Copy to clipboard#include <iostream>
using namespace std;

template <typename T>
T add(T a, T b) {
    return a + b;
}

int main() {
    cout << add(3, 4) << endl;     // Outputs: 7
    cout << add(2.5, 4.3) << endl; // Outputs: 6.8

    return 0;
}

Here, the add function template can accept parameters of any type, allowing operations on both integers and floating-point numbers.

The usage of both dynamic and static polymorphism promotes versatility in our code, enabling us to write flexible and reusable functions and classes.

FAQs on OOP Concepts

1. What is OOP?

Object-Oriented Programming is a paradigm that organizes code using objects and classes, focusing on data and behavior together.

2. What are the four main pillars of OOP?

Encapsulation, Inheritance, Polymorphism, and Abstraction.

3. What is the difference between abstraction and encapsulation?

Abstraction hides complexity (what it does), encapsulation hides data (how it does it).

4. What is the difference between overloading and overriding?

Overloading: same method name, different parameters (compile-time). Overriding: redefining parent method in child (runtime).

5. What is the difference between abstract class and interface?

Abstract class can have state and implemented methods; interface is purely a contract (before Java 8). Multiple interfaces can be implemented, but only one class extended.

Leave A Reply

Your email address will not be published.