OOPs Concepts in C++ Explained with Examples

Updated on October 10, 2024

Article Outline

Object-Oriented Programming (OOP) is a programming style that uses objects to represent data and methods to manipulate that data. It allows for the creation of modular and reusable code, making it easier to manage and scale software projects. OOP is fundamental in many programming languages, including C++, which is known for its strong support for this paradigm.

 

In this blog, we will explore the key concepts of Object-Oriented Programming in C++. We will cover essential principles like encapsulation, inheritance, polymorphism, and abstraction. Additionally, we will compare OOP with procedural programming, discuss its pros and cons, and summarise the main concepts in a table.

What is OOP, and Why Is It Important?

Object-Oriented Programming (OOP) is a programming approach that uses objects to model real-world entities. Each object contains data, known as attributes, and functions, known as methods, that operate on this data. This structure allows for the creation of complex programs by combining simpler objects. OOP is based on four main principles: encapsulation, inheritance, polymorphism, and abstraction.

 

Key Benefits of OOP:

 

  • Code Reusability: Use existing code for new applications, reducing development time.
  • Modularity: Break down programs into smaller, manageable objects.
  • Ease of Maintenance: Modify and update code with minimal impact on other parts.
  • Real-World Modeling: Represent real-world entities and relationships directly in the code.
*Image
Get curriculum highlights, career paths, industry insights and accelerate your technology journey.
Download brochure

Key OOPs Concepts in C++

Object-Oriented Programming (OOP) in C++ is built on several key concepts that help in creating structured and efficient code. Understanding these concepts is crucial for anyone looking to master C++ and leverage its full potential.

Class

A class is a blueprint for creating objects. It defines properties and behaviours that the objects created from the class will have. Think of a class as a template that defines the structure and functions of an object.

 

Example:

 

In this example, we define a class named ‘Smartphone’ with one property, ‘brand’, which represents the brand of the smartphone.

 

class Smartphone { public:     string brand; };

Object

An object is an instance of a class. It contains real values instead of variables. When a class is defined, no memory is allocated until an object of that class is created.

 

Example:

 

In this example, we create an object ‘myPhone’ from the Smartphone class. We set the brand property to “Samsung” and printed it. This shows how objects can be used to store and manipulate data defined by the class.

 

#include <iostream> using namespace std; class Smartphone { public:     string brand; // Defining the class property }; int main() {     Smartphone myPhone; // Defining the object of the class     myPhone.brand = "Samsung"; // Assigning the value to the class properties     cout << "Brand: " << myPhone.brand << endl;     return 0; }


Output:

Brand: Samsung

Constructor

A constructor is a special member function of a class that is automatically called when an object of that class is created. The main purpose of a constructor is to initialise objects. It has the same name as the class and does not have a return type.

 

Example:

 

In this example:

 

  • We define a constructor for the Smartphone class that takes two parameters: b for brand and m for model.
  • When we create the myPhone object, the constructor is called with “Samsung” and “Galaxy S21” as arguments, initialising the brand and model properties.
  • We then print the brand and model properties to show the values assigned by the constructor.


This example demonstrates how constructors are used to initialise objects with specific values at the time of their creation.

 

#include <iostream> using namespace std; class Smartphone { public:      string brand;      string model;     // Constructor with parameters      Smartphone(string b, string m) {          brand = b;          model = m;      } }; int main() {     // Create an object of the Smartphone class      Smartphone myPhone("Samsung", "Galaxy S21");     cout << "Brand: " << myPhone.brand << endl;      cout << "Model: " << myPhone.model << endl;      return 0; }

Output:

Brand: Samsung Model: Galaxy S21

Inheritance

Inheritance is a fundamental concept in OOP that allows a class to inherit properties and methods from another class. This helps in reusing existing code and extending functionalities. 

 

There are different types of inheritance in C++: 

  • single inheritance
  • multiple inheritance
  • multilevel inheritance
  • hierarchical inheritance
  • hybrid inheritance.

Single Inheritance

Single inheritance is when a class (derived class) inherits from one base class. This is the most straightforward form of inheritance.

 

Example:

 

  • We define a base class Smartphone with a property brand and a method displayBrand().
  • The derived class Model inherits from the Smartphone and adds an additional property model and a method displayModel().
  • The Model class constructor calls the Smartphone constructor to initialise the brand property.
  • In the main function, we create an object of the Model class and use it to display the brand and model.
#include <iostream> using namespace std; // Base class class Smartphone { public: string brand; // Constructor for base class Smartphone(string b) { brand = b; } // Method to display the brand void displayBrand() { cout << "Brand: " << brand << endl; } }; // Derived class class Model : public Smartphone { public: string model; // Constructor for derived class Model(string b, string m) : Smartphone(b) { model = m; } // Method to display the model void displayModel() { cout << "Model: " << model << endl; } }; int main() { // Create an object of the derived class Model myPhone("Samsung", "Galaxy S21"); // Call methods to display brand and model myPhone.displayBrand(); // Output: Brand: Samsung myPhone.displayModel(); // Output: Model: Galaxy S21 return 0; }


Output:

 

Brand: Samsung Model: Galaxy S21

Multiple Inheritance

Multiple inheritance is when a class inherits from more than one base class. This allows a derived class to inherit features from multiple base classes.

 

Example:

 

  • We define two base classes, Brand and Model, each with its own constructor.
  • The derived class Smartphone inherits from both Brand and Model.
  • The Smartphone constructor initialises the brand and model properties by calling the constructors of the Brand and Model.
  • In the main function, we create an object of the Smartphone class and use it to display the brand and model.
#include <iostream> using namespace std; // Base class 1 class Brand { public: string brand; // Constructor for base class 1 Brand(string b) { brand = b; } }; // Base class 2 class Model { public: string model; // Constructor for base class 2 Model(string m) { model = m; } }; // Derived class class Smartphone : public Brand, public Model { public: // Constructor for derived class Smartphone(string b, string m) : Brand(b), Model(m) {} // Method to display brand and model void display() { cout << "Brand: " << brand << ", Model: " << model << endl; } }; int main() { // Create an object of the derived class Smartphone myPhone("Samsung", "Galaxy S21"); // Call method to display brand and model myPhone.display(); // Output: Brand: Samsung, Model: Galaxy S21 return 0; }

 

Output:

Brand: Samsung, Model: Galaxy S21

Multilevel Inheritance

Multilevel inheritance is when a class inherits from a derived class, forming a chain of inheritance.

 

Example:

 

  • We define a base class Brand and a derived class Model that inherits from Brand.
  • The further derived class Smartphone inherits from Model.
  • The Smartphone constructor initialises the brand and model properties by calling the Model constructor, which in turn calls the Brand constructor.
  • In the main function, we create an object of the Smartphone class and use it to display the brand and model.
#include <iostream> using namespace std; // Base class class Brand { public: string brand; // Constructor for base class Brand(string b) { brand = b; } }; // Derived class class Model : public Brand { public: string model; // Constructor for derived class Model(string b, string m) : Brand(b) { model = m; } }; // Further derived class class Smartphone : public Model { public: // Constructor for further derived class Smartphone(string b, string m) : Model(b, m) {} // Method to display brand and model void display() { cout << "Brand: " << brand << ", Model: " << model << endl; } }; int main() { // Create an object of the further derived class Smartphone myPhone("Samsung", "Galaxy S21"); // Call method to display brand and model myPhone.display(); // Output: Brand: Samsung, Model: Galaxy S21 return 0; }

Output:

Brand: Samsung, Model: Galaxy S21

Hierarchical Inheritance

Hierarchical inheritance is when multiple classes inherit from a single base class.

 

Example:

 

  • We define a base class Brand with a property brand and a method displayBrand().
  • Two derived classes, Model1 and Model2, inherit from Brand.
  • Each derived class has its own method to display the specific model.
  • In the main function, we create objects of Model1 and Model2 and use them to display the brand and specific models.
#include <iostream> using namespace std; // Base class class Brand { public: string brand; // Constructor for base class Brand(string b) { brand = b; } // Method to display the brand void displayBrand() { cout << "Brand: " << brand << endl; } }; // Derived class 1 class Model1 : public Brand { public: Model1(string b) : Brand(b) {} // Method to display specific model void displayModel1() { cout << "Model1: " << brand << endl; } }; // Derived class 2 class Model2 : public Brand { public: Model2(string b) : Brand(b) {} // Method to display specific model void displayModel2() { cout << "Model2: " << brand << endl; } }; int main() { // Create objects of the derived classes Model1 phone1("Samsung"); Model2 phone2("Apple"); // Call methods to display brand and specific models phone1.displayBrand(); // Output: Brand: Samsung phone1.displayModel1(); // Output: Model1: Samsung phone2.displayBrand(); // Output: Brand: Apple phone2.displayModel2(); // Output: Model2: Apple return 0; }


Output:

 

Brand: Samsung Model1: Samsung Brand: Apple Model2: Apple

Hybrid Inheritance

Hybrid inheritance is a combination of two or more types of inheritance.

 

Example:

 

  • We define a base class Brand with a property brand.
  • Two derived classes, Model1 and Model2, inherit from Brand.
  • The further derived class Smartphone inherits from both Model1 and Model2.
  • The Smartphone constructor initialises the brand properties by calling the constructors of Model1 and Model2.
  • In the main function, we create an object of the Smartphone class and use it to display the brands from both models.
#include <iostream> using namespace std; // Base class class Brand { public: string brand; // Constructor for base class Brand(string b) { brand = b; } }; // Derived class 1 class Model1 : public Brand { public: Model1(string b) : Brand(b) {} }; // Derived class 2 class Model2 : public Brand { public: Model2(string b) : Brand(b) {} }; // Derived class that inherits from Model1 and Model2 class Smartphone : public Model1, public Model2 { public: // Constructor for derived class Smartphone(string b1, string b2) : Model1(b1), Model2(b2) {} // Method to display brand from both models void display() { cout << "Model1 Brand: " << Model1::brand << ", Model2 Brand: " << Model2::brand << endl; } }; int main() { // Create an object of the derived class Smartphone myPhone("Samsung", "Apple"); // Call method to display brand from both models myPhone.display(); // Output: Model1 Brand: Samsung, Model2 Brand: Apple return 0; }


Output:

Model1 Brand: Samsung, Model2 Brand: Apple

Polymorphism

Polymorphism is an OOP concept where a single function or method can have different behaviours based on the object that invokes it. In C++, polymorphism is achieved through function overloading, operator overloading, and method overriding using inheritance.

Function Overloading

Function overloading allows multiple functions with the same name but different parameters to coexist.

 

Example:

 

  • The MathOperations class has two add methods with different parameter types.
  • The correct add method is called based on the argument types provided.
#include <iostream> using namespace std; class MathOperations { public: // Function to add two integers int add(int a, int b) { return a + b; } // Function to add two double values double add(double a, double b) { return a + b; } }; int main() { MathOperations math; // Call add function with integers cout << "Sum of integers: " << math.add(5, 3) << endl; // Output: Sum of integers: 8 // Call add function with doubles cout << "Sum of doubles: " << math.add(5.5, 3.2) << endl; // Output: Sum of doubles: 8.7 return 0; }

Output:

Sum of integers: 8 Sum of doubles: 8.7

Operator Overloading

Operator overloading allows you to redefine the functionality of operators for user-defined types.

 

Example:

 

  • The Complex class overloads the + operator to add two complex numbers.
  • The c1 + c2 expression calls the overloaded + operator.

 

#include <iostream> using namespace std; class Complex { public: double real, imag; Complex(double r, double i) : real(r), imag(i) {} // Overload the + operator to add two complex numbers Complex operator + (const Complex& other) { return Complex(real + other.real, imag + other.imag); } // Method to display the complex number void display() { cout << real << " + " << imag << "i" << endl; } }; int main() { Complex c1(3.0, 4.0), c2(1.0, 2.0); // Add two complex numbers using overloaded + operator Complex c3 = c1 + c2; // Display the result c3.display(); // Output: 4.0 + 6.0i return 0; }

Output:

4 + 6i

Method Overriding

Method overriding allows a derived class to provide a specific implementation of a method that is already defined in its base class.

 

Example:

 

  • The Animal class has a virtual method makeSound.
  • The Dog class overrides makeSound to provide a specific implementation.
  • A base class pointer animalPtr calls the overridden method, demonstrating runtime polymorphism.
#include <iostream> using namespace std; // Base class class Animal { public: virtual void makeSound() { cout << "Animal makes a sound" << endl; } }; // Derived class class Dog : public Animal { public: void makeSound() override { cout << "Dog barks" << endl; } }; int main() { Animal* animalPtr; Dog dog; // Pointing base class pointer to derived class object animalPtr = &dog; // Call the overridden method animalPtr->makeSound(); // Output: Dog barks return 0; }


Output:

Dog barks

Abstraction

Abstraction is an OOP concept that hides the complex implementation details and shows only the essential features of an object. This simplifies the user interaction with the object and makes the code more readable and maintainable. In C++, abstraction is achieved using abstract classes and interfaces.

 

Abstract Class

 

An abstract class is a class that cannot be instantiated and is designed to be subclassed. It often contains one or more pure virtual functions.

 

Example:

 

  • The Device class is an abstract class with pure virtual functions start and stop.
  • The Smartphone class inherits from Device and provides implementations for start and stop.
  • In the main function, we create an object of the Smartphone and call the implemented methods.
#include <iostream> using namespace std; // Abstract class class Device { public: // Pure virtual function virtual void start() = 0; virtual void stop() = 0; }; // Derived class class Smartphone : public Device { public: void start() override { cout << "Smartphone is starting" << endl; } void stop() override { cout << "Smartphone is stopping" << endl; } }; int main() { // Create an object of the derived class Smartphone myPhone; // Call the abstract class methods implemented by the derived class myPhone.start(); // Output: Smartphone is starting myPhone.stop(); // Output: Smartphone is stopping return 0; }


Output:

Smartphone is starting Smartphone is stopping

 

This example demonstrates how abstraction allows you to define a template for future classes and ensure they implement specific methods, simplifying complex functionalities and improving code organisation.

Encapsulation

Encapsulation is an OOP concept that bundles the data (attributes) and methods (functions) that operate on the data into a single unit, called a class. It restricts direct access to some of an object’s components, which is a means of preventing accidental interference and misuse of the data. Encapsulation helps in protecting the internal state of an object and only allows manipulation through defined methods.

 

Example:

 

  • The Smartphone class encapsulates the properties brand and model as private members. This means they cannot be accessed directly from outside the class.
  • Public methods (setBrand, getBrand, setModel, and getModel) provide controlled access to modify and retrieve the private data.
  • The displayInfo method allows displaying the current state of the Smartphone object.
  • In the main function, we create an object of the Smartphone class, use the methods to modify its properties, and display the results.

 

#include <iostream> using namespace std; class Smartphone { private: string brand; string model; public: // Constructor to initialise the brand and model Smartphone(string b, string m) { brand = b; model = m; } // Method to set the brand void setBrand(string b) { brand = b; } // Method to get the brand string getBrand() { return brand; } // Method to set the model void setModel(string m) { model = m; } // Method to get the model string getModel() { return model; } // Method to display the smartphone details void displayInfo() { cout << "Brand: " << brand << ", Model: " << model << endl; } }; int main() { // Create an object of the Smartphone class Smartphone myPhone("Samsung", "Galaxy S21"); // Display the initial smartphone details myPhone.displayInfo(); // Output: Brand: Samsung, Model: Galaxy S21 // Modify the smartphone details using setter methods myPhone.setBrand("Apple"); myPhone.setModel("iPhone 12"); // Display the updated smartphone details myPhone.displayInfo(); // Output: Brand: Apple, Model: iPhone 12 return 0; }


Output:

Brand: Samsung, Model: Galaxy S21 Brand: Apple, Model: iPhone 12

 

Dynamic Binding

Dynamic binding, also known as late binding, is a concept in OOP where the method to be called is determined at runtime. This is mainly used with polymorphism and allows for more flexible and extensible code. In C++, dynamic binding is achieved using virtual functions.

 

Example:

 

  • The Device class has a virtual function start.
  • The Smartphone and Laptop classes override the start function.
  • A pointer to the Device class can point to objects of Smartphone and Laptop.
  • The actual function called is determined at runtime based on the object being pointed to.
#include <iostream> using namespace std; // Base class class Device { public: // Virtual function virtual void start() { cout << "Device is starting" << endl; } }; // Derived class class Smartphone : public Device { public: void start() override { cout << "Smartphone is starting" << endl; } }; // Another derived class class Laptop : public Device { public: void start() override { cout << "Laptop is starting" << endl; } }; int main() { Device* device; Smartphone phone; Laptop laptop; // Point to a Smartphone object device = ☎ device->start(); // Output: Smartphone is starting // Point to a Laptop object device = &laptop; device->start(); // Output: Laptop is starting return 0; }


Output:

Smartphone is starting Laptop is starting

Message Passing

Message passing in OOP refers to the process of objects communicating with each other by sending and receiving information. This is usually done through method calls, where one object invokes a method on another object.

 

Example:

 

  • The Processor class has a method processMessage that takes a string message.
  • The Smartphone class contains an object of the Processor class and a method sendMessage.
  • The sendMessage method in Smartphone calls the processMessage method of the Processor object, demonstrating message passing between objects.
  • In the main function, we create a Smartphone object and send a message, showing how the message is passed and processed.
#include <iostream> using namespace std; class Processor { public: void processMessage(string message) { cout << "Processing message: " << message << endl; } }; class Smartphone { private: Processor processor; public: void sendMessage(string message) { cout << "Sending message: " << message << endl; // Pass the message to the Processor object for further action processor.processMessage(message); } }; int main() { // Create an object of the Smartphone class Smartphone myPhone; // Send a message using the Smartphone object myPhone.sendMessage("Hello, World!"); // Output: Sending message: Hello, World! // Processing message: Hello, World! return 0; }


Output:

Sending message: Hello, World! Processing message: Hello, World!

Procedural Programming vs. Object-Oriented Programming

Feature Procedural Programming Object-Oriented Programming (OOP)
Approach Top-down Bottom-up
Basic Unit Function Class and Object
Data Handling Global data shared across functions Encapsulated data within objects
Code Reusability Limited reusability, primarily through functions High reusability through inheritance and polymorphism
Focus Functions and sequences of actions Objects and interactions between them
Modularity Functions Classes and Objects
Data Security Low, data is accessible by any function High, data is hidden and protected within objects
Maintenance Harder to maintain in large projects Easier to maintain due to modular structure
Examples C, Pascal C++, Java, Python

Conclusion

Object-Oriented Programming is all about managing code in C++. By learning how you can apply classes, objects, inheritance, polymorphism, abstraction, encapsulation, dynamic binding and message passing you will be able to create software that is modular which can also be reused and maintained too.

 

OOP’s ability to model real-world entities and relationships makes it a preferred choice for complex software development. Whether transitioning from procedural programming or starting from scratch mastering these concepts in C++ would significantly improve your coding skills as well as project outcomes.

 

FAQs
An emphasis on functions and sequence of actions are the main features of procedural programming while focus on objects’ interactions lies at the core of OOP.
Inheritance permits a class to acquire properties plus behaviours from other classes, thereby facilitating the reuse and extension of code.
Different behaviours may be exhibited by methods depending on which object calls them, i.e., upon function overloading, operator overloading method overriding, etc. This mechanism is otherwise known as Polymorphism.
Encapsulation limits direct access to an object’s information and thus possesses control measures through which information can only be interacted with through defined methods.
The method that is determined at run time is known as dynamic binding. In other words, a base class pointer that points to derived objects can call overridden methods based on the actual object type at runtime.

Updated on October 10, 2024

Link
left dot patternright dot pattern

Programs tailored for your success

Popular

Management

Data Science

Finance

Technology

Future Tech

Upskill with expert articles

View all
Hero Vired logo
Hero Vired is a leading LearnTech company dedicated to offering cutting-edge programs in collaboration with top-tier global institutions. As part of the esteemed Hero Group, we are committed to revolutionizing the skill development landscape in India. Our programs, delivered by industry experts, are designed to empower professionals and students with the skills they need to thrive in today’s competitive job market.
Blogs
Reviews
Events
In the News
About Us
Contact us
Learning Hub
18003093939     ·     hello@herovired.com     ·    Whatsapp
Privacy policy and Terms of use

|

Sitemap

© 2024 Hero Vired. All rights reserved