Object-Oriented Programming in C++: A Hands-On Approach

Joshua M. Ayala Mejill
6 min readMar 12, 2023

Introduction:

Object-Oriented Programming (OOP) is a programming paradigm that emphasizes the use of objects to design and build complex software applications. C++ is a powerful programming language that supports OOP principles, making it a popular choice for building complex, scalable, and reusable software applications. In this article, we’ll explore how to use OOP principles in C++ to build robust and scalable software applications.

Encapsulation:

Encapsulation is a core principle of Object-Oriented Programming (OOP) that involves bundling data and functions into a single unit, known as a class. In C++, the class keyword is used to define a class, and data members and member functions are declared within it. Access specifiers such as private, public, and protected are used to control the access to data members and member functions within the class. This approach allows for better data security, reduces code duplication, and simplifies code maintenance. By hiding implementation details and exposing only necessary functionality, encapsulation promotes modular and scalable code design in C++.

To demonstrate encapsulation, let’s create a simple C++ class called Person with private data members name and age, and public member functions setName, setAge, getName, and getAge.

class Person {
private:
std::string name;
int age;
public:
void setName(std::string name) {
this->name = name;
}
void setAge(int age) {
this->age = age;
}
std::string getName() const {
return name;
}
int getAge() const {
return age;
}
};

In this example, name and age are private members, which means that they cannot be accessed directly from outside the class. Instead, we use public member functions like setName, setAge, getName, and getAge to manipulate these private members.

Let’s say we want to create a Person object and set its name and age:

Person person;
person.setName("John");
person.setAge(30);

Here, the setName and setAge functions are used to set the private members of the Person object. Now, let’s say we want to retrieve the name and age of the Person object:

std::cout << "Name: " << person.getName() << std::endl;
std::cout << "Age: " << person.getAge() << std::endl;

Here, the getName and getAge functions are used to retrieve the private members of the Person object. Note that we cannot access the name and age members directly.

Encapsulation can help to prevent bugs and other issues in code by ensuring that private data members are only modified in ways that the class designer intended. It also helps to simplify code by providing an interface that hides implementation details from the user.

However, it is important to note that encapsulation does not provide complete security. If an attacker gains access to a class object, they can still modify its private members. Additionally, encapsulation can make code more difficult to understand and maintain if not used properly. Therefore, it is important to use encapsulation judiciously and with care.

Inheritance:

Inheritance is another essential principle of OOP, which allows us to create a new class by inheriting properties from an existing class. In C++, we can achieve inheritance using the class keyword followed by a colon and the access specifier public, followed by the name of the base class. The derived class can inherit the data members and member functions of the base class and can also define its data members and member functions. Inheritance is useful when we want to create a new class that shares some properties with an existing class but also has some unique properties.

To create a derived class, which inherits from a base class, the colon operator and the keyword “public” are used. Here’s an example:

class Base {
public:
void foo() {
std::cout << "Base::foo()" << std::endl;
}
};

class Derived : public Base {
public:
void bar() {
std::cout << "Derived::bar()" << std::endl;
}
};

In this example, the Derived class is publicly inherited from the Base class. This means that all public members of the Base class, including its member functions, are inherited by the Derived class. We can then define new members or override existing members in the Derived class.

Derived d;
d.foo(); // calls Base::foo()
d.bar(); // calls Derived::bar()

In this code, we create an instance of the Derived class and call its foo() and bar() member functions. The foo() function is inherited from the Base class, while the bar() function is defined in the Derived class.

We can also override the behavior of the Base class by defining a member function with the same name in the Derived class. For example:

class Base {
public:
virtual void foo() {
std::cout << "Base::foo()" << std::endl;
}
};

class Derived : public Base {
public:
void foo() override {
std::cout << "Derived::foo()" << std::endl;
}
};

Base* b = new Derived();
b->foo(); // calls Derived::foo()

In this example, we define a virtual function foo() in the Base class, and override it in the Derived class. We also create an instance of the Derived class and assign it to a pointer of type Base*. When we call the foo() function on this pointer, it calls the overridden function in the Derived class.

Polymorphism:

Polymorphism is a crucial principle of object-oriented programming, enabling objects of different classes to be treated as if they belonged to a common base class. In C++, this is achieved through the use of virtual functions, which can be overridden in derived classes. Virtual functions are declared with the “virtual” keyword in the base class, and when called on a base class pointer that points to a derived class object, the derived class implementation of the function is executed. This makes programming more flexible and dynamic, allowing for the creation of functions that can work with different types of objects.

Let’s consider an example where we have a base class named “Shape” and two derived classes named “Rectangle” and “Circle”. Each of these classes has a member function named “getArea()” that calculates the area of the shape.

#include <iostream>

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

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

class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) {}
double getArea() override { return 3.14 * radius * radius; }
};

int main() {
Shape* s1 = new Rectangle(4, 5);
Shape* s2 = new Circle(3);

std::cout << "Rectangle area: " << s1->getArea() << std::endl;
std::cout << "Circle area: " << s2->getArea() << std::endl;

delete s1;
delete s2;

return 0;
}

In this example, we define a base class “Shape” that has a virtual function “getArea()”. We also define two derived classes “Rectangle” and “Circle” that override the “getArea()” function to calculate the area of the respective shape. In the main function, we create two objects of type “Shape” using pointers to the derived classes. When we call the “getArea()” function on these objects, the correct implementation of the function is called based on the type of the object. This is an example of polymorphism, where objects of different types can be treated as if they were objects of a common base class.

Conclusion:

In conclusion, OOP principles are essential for building complex, scalable, and reusable software applications. C++ is a powerful programming language that supports OOP principles and provides a rich set of features to build robust and scalable software solutions. By using encapsulation, inheritance, and polymorphism, we can create classes that are easier to maintain, more secure, and more reusable. By following the best practices and guidelines, we can become proficient C++ developers and create software applications that meet the highest standards of quality and performance.

--

--

Joshua M. Ayala Mejill

Fourth-year Computer Science student passionate about C++ and Cobol, eager to learn more in AI, cybersecurity, and web programming.