Object-Oriented Programming in C++ using Encapsulation, Inheritance, Abstraction, Polymorphism.
Object-oriented programming (OOP) is a programming paradigm that empowers developers to create efficient, organised, and easily maintainable code. C++ is renowned for its robust support of OOP concepts, making it an ideal language for building diverse applications. In this article, we’ll embark on a journey through the key OOP principles—Encapsulation, Inheritance, Abstraction, and Polymorphism—by delving into code examples that showcase the power and flexibility of C++.
Encapsulation: Securing Data and Behaviour
Encapsulation is the practice of encapsulating data (attributes) and behavior (methods) within a single entity, known as a class. This shields the internal details from outside access, promoting data integrity and modularity. Let’s see how this works with an example:
#include <iostream>
class Student {
public:
Student(const std::string& name, int age) : name(name), age(age) {}
void introduce() {
std::cout << "Hi, I'm " << name << " and I'm " << age << " years old." << std::endl;
}
private:
std::string name;
int age;
};
int main() {
Student student("Alice", 20);
student.introduce();
return 0;
}
In this code, the Student
class encapsulates the student’s name and age, exposing the introduce()
method to interact with the encapsulated data.
Inheritance: Building on Existing Foundations
Inheritance is a cornerstone of OOP, allowing the creation of new classes (derived or child classes) that inherit properties and behaviors from existing classes (base or parent classes). This promotes code reuse and extensibility. Let’s examine inheritance in action:
#include <iostream>
class Animal {
public:
Animal(const std::string& name) : name(name) {}
void speak() const {
std::cout << name << " makes a sound." << std::endl;
}
private:
std::string name;
};
class Dog : public Animal {
public:
Dog(const std::string& name) : Animal(name) {}
void speak() const {
std::cout << "Woof Woof!" << std::endl;
}
};
int main() {
Dog dog("Buddy");
dog.speak();
return 0;
}
Here, the Dog
class inherits from the Animal
class, extending its behavior by overriding the speak()
method.
Abstraction: Focusing on Essentials
Abstraction involves modeling classes by capturing essential attributes and behaviors while hiding intricate details. This simplifies complex systems and enhances code clarity. Let’s observe abstraction in action:
#include <iostream>
class Shape {
public:
virtual double calculateArea() const = 0;
};
class Circle : public Shape {
public:
Circle(double radius) : radius(radius) {}
double calculateArea() const override {
return 3.14 * radius * radius;
}
private:
double radius;
};
int main() {
Circle circle(5);
std::cout << "Area of circle: " << circle.calculateArea() << std::endl;
return 0;
}
In this code, the Shape
class abstracts the concept of a shape and its area calculation, while the Circle
class implements the concrete functionality.
Polymorphism: Flexibility through Interfaces
Polymorphism allows objects of different classes to be treated as objects of a common base class. This facilitates writing flexible and reusable code. Let’s explore polymorphism in practice:
#include <iostream>
#include <vector>
class Shape {
public:
virtual double calculateArea() const = 0;
};
class Circle : public Shape {
public:
Circle(double radius) : radius(radius) {}
double calculateArea() const override {
return 3.14 * radius * radius;
}
private:
double radius;
};
class Rectangle : public Shape {
public:
Rectangle(double width, double height) : width(width), height(height) {}
double calculateArea() const override {
return width * height;
}
private:
double width, height;
};
int main() {
std::vector<Shape*> shapes;
shapes.push_back(new Circle(5));
shapes.push_back(new Rectangle(4, 6));
for (const auto shape : shapes) {
std::cout << "Area: " << shape->calculateArea() << std::endl;
}
// Clean up memory
for (const auto shape : shapes) {
delete shape;
}
return 0;
}
Here, polymorphism allows us to treat both Circle
and Rectangle
objects as Shape
objects, facilitating a unified approach to calculating areas.
Conclusion
Object-oriented programming empowers developers to build complex and maintainable systems by utilizing principles such as Encapsulation, Inheritance, Abstraction, and Polymorphism. These concepts foster modularity, reusability, and code organization, making C++ a versatile and powerful language for a wide range of applications. By mastering these principles and applying them judiciously, developers can unlock the full potential of C++ and create software that is both elegant and efficient.