Object-oriented programming
Inheritance
Mechanism by which one class can derive or inherit its
features from another class.
public → Inherited as-is
protected → Accessible in child, not outside
private → Hidden from child
Benefits:
Code reusability(write once, use many)
Better organization through hierarchy
Scalability of software systems
Polymorphism
The same function or operator behaves differently based
on the object or context.
Two types of Polymorphism:
1.Method overloading/ function overloading is decided
at compile time.
2.Virtual functions — method overriding using
inheritance and virtual functions.
Benefits:
Flexibility and extensibility in code
Easier maintenance and upgrade of the system
Makes code easier and scalable
Abstract class/pure virtual functions
An abstract class is a class that cannot be
instantiated directly. It is meant to be a base class,
designed to be inherited by other classes. It usually
contains at least one pure virtual function.
A pure virtual function is a function that has no
implementation in the base class and is declared by
assigning = 0 at the end.
Friend function and class
A friend function is a non-member function that is
granted access to the private and protected members of
a class.
A friend class is a class that is allowed to access the
private and protected members of another class.
When to Use Friend Classes or Functions:
When tight coupling between two classes/functions
is intended and safe
When you need external functions to work closely
with class internals
When overloading operators that require access to
the private data of multiple objects.
Composition and Aggregation
The lifetime of the part is controlled by the whole.
If the container (whole) is destroyed, the part
(member) is also destroyed.
Think of "a human has-a heart" — if the human is
gone, the heart goes too.
Simple Code for Composition:
Imagine a Car and its Engine. A Car has an Engine, and
the Engine is created as part of the Car. If the Car is
destroyed, the Engine (as part of that car) is also
gone.
#include <iostream>
#include <string>
class Engine {
public:
Engine() {
std::cout << "Engine created for the car." << std::endl;
~Engine() {
std::cout << "Engine in the car is gone." << std::endl;
}
void start() const {
std::cout << "Engine started." << std::endl;
};
class Car {
private:
std::string model;
Engine engine; // Car *has* an Engine (object member)
public:
Car(std::string m) : model(m) {
std::cout << "Car '" << model << "' built." << std::endl;
~Car() {
std::cout << "Car '" << model << "' is scrapped." <<
std::endl;
// The Engine object 'engine' is automatically destroyed here
// because it's a member object.
void drive() const {
engine.start();
std::cout << "Car is moving." << std::endl;
};
int main() {
Car myCar("SimpleCar");
myCar.drive();
// When myCar is destroyed at the end of main(),
// the Engine object 'engine' that is a part of it is also
automatically destroyed.
return 0;
Aggregation (Weak Has-a)
The lifetime of the part is independent of the whole.
The contained object exists separately.
Example: "A student has-a laptop", but if the
student leaves the school, the laptop still exists.
Simple Code for Aggregation:
Imagine a Student and a Book. A Student might use a
Book, but the Book exists independently of that
particular Student.
#include <iostream>
#include <string>
class Book {
public:
std::string title;
Book(std::string t) : title(t) {
std::cout << "Book '" << title << "' exists." << std::endl;
~Book() {
std::cout << "Book '" << title << "' is gone." << std::endl;
void read() const {
std::cout << "Reading book: " << title << std::endl;
};
class Student {
public:
std::string name;
Book* currentBook; // Student *uses* a Book (pointer)
Student(std::string n) : name(n), currentBook(nullptr) {
std::cout << "Student '" << name << "' created." <<
std::endl;
~Student() {
std::cout << "Student '" << name << "' is done." <<
std::endl;
// The Student doesn't own the book, so doesn't delete it.
void borrowBook(Book* book) {
currentBook = book;
std::cout << name << " borrowed '" << book->title << "'."
<< std::endl;
}
void study() const {
if (currentBook) {
currentBook->read();
} else {
std::cout << name << " has no book to study." <<
std::endl;
};
int main() {
Book* book1 = new Book("The Great Adventure");
Student student1("Alice");
student1.borrowBook(book1);
student1.study();
Student student2("Bob");
student2.study(); // Bob has no book yet
delete book1; // The book can be deleted even if students
existed.
return 0;