Introduction to
Object-Oriented
Programming
A complete guide to the four pillars of OOP — encapsulation, abstraction, inheritance, and polymorphism — with full C++ examples.
What is Object-Oriented Programming?
Object-Oriented Programming (OOP) is a programming paradigm that organises software design around objects rather than functions and logic. An object is a self-contained entity that contains both data (attributes/properties) and behaviours (methods/functions) that operate on that data.
OOP is one of the most popular programming paradigms and forms the foundation of many modern languages including C++, Java, Python, and C#. Understanding OOP is essential for building large, maintainable software systems.
Further reading: MDN — Object-oriented programming · Britannica — OOP
Procedural vs Object-Oriented Programming
| Aspect | Procedural Programming | Object-Oriented Programming |
|---|---|---|
| Focus | Functions that perform operations | Objects that contain data and methods |
| Data | Data is separate from functions | Data and functions are bundled together |
| Organisation | Organised around procedures/functions | Organised around objects/classes |
| Reusability | Functions can be reused | Classes can be reused and extended |
| Security | Data is globally accessible | Data can be hidden (encapsulation) |
| Real-world mapping | Doesn't map well to real-world entities | Maps naturally to real-world entities |
Why OOP?
- Modularity: Objects are independent, making them easier to maintain and debug
- Reusability: Classes can be reused across different programs
- Flexibility: Easy to add new features without changing existing code
- Security: Data hiding prevents unauthorised access
- Maintainability: Changes in one part don't affect others
- Scalability: Easier to manage large, complex programs
Classes vs Objects
| Class | Object |
|---|---|
| Blueprint or template | Actual instance created from class |
| Defines properties and methods | Has actual values for properties |
| Exists at compile time | Created at runtime |
| No memory allocated until object created | Occupies memory |
Example: class Car | Example: Car myCar |
The Four Pillars of OOP
Encapsulation
Bundle data and methods; restrict direct access to internal components via access specifiers.
Abstraction
Hide complex implementation details; expose only essential features through abstract interfaces.
Inheritance
Derive new classes from existing ones, inheriting properties and establishing "is-a" relationships.
Polymorphism
One interface, many implementations. The same function call behaves differently depending on the object.
Encapsulation
Definition
Encapsulation is the bundling of data (attributes) and methods (functions) that operate on that data into a single unit (class), while restricting direct access to some of the object's internal components.
See also: cppreference — Access specifiers · GFG — Encapsulation in C++
Access Specifiers in C++
| Specifier | Access Level | Description |
|---|---|---|
private | Class only | Members cannot be accessed from outside the class |
protected | Class + Derived classes | Members accessible in class and derived classes |
public | Anywhere | Members accessible from anywhere |
Why Encapsulation?
- Data Protection: Prevents accidental or unauthorised modification
- Control: You can add validation logic before changing data
- Flexibility: You can change internal implementation without affecting external code
- Maintainability: Easier to debug because data access is controlled
- Abstraction: Users don't need to know how data is stored internally
Complete Encapsulation Example — Bank Account System
#include <iostream> #include <string> using namespace std; class BankAccount { private: string accountNumber; string accountHolderName; double balance; string pinCode; int failedLoginAttempts; bool validatePin(string enteredPin) { return pinCode == enteredPin; } void logTransaction(string transactionType, double amount) { cout << "[" << __TIME__ << "] " << transactionType << ": $" << amount << " - New balance: $" << balance << endl; } public: BankAccount(string accNo, string name, string pin, double initialDeposit = 0) { accountNumber = accNo; accountHolderName = name; pinCode = pin; balance = (initialDeposit >= 0) ? initialDeposit : 0; failedLoginAttempts = 0; logTransaction("Account Created", initialDeposit); } string getAccountNumber() { return "XXXX-XXXX-" + accountNumber.substr(accountNumber.length() - 4); } double getBalance(string enteredPin) { if (validatePin(enteredPin)) { failedLoginAttempts = 0; return balance; } else { failedLoginAttempts++; cout << "Invalid PIN. Attempt " << failedLoginAttempts << " of 3." << endl; if (failedLoginAttempts >= 3) cout << "ACCOUNT LOCKED! Contact customer support." << endl; return -1; } } bool deposit(double amount, string enteredPin) { if (!validatePin(enteredPin)) { cout << "Invalid PIN." << endl; return false; } if (amount <= 0) { cout << "Amount must be positive." << endl; return false; } balance += amount; logTransaction("Deposit", amount); return true; } bool withdraw(double amount, string enteredPin) { if (!validatePin(enteredPin)) { cout << "Invalid PIN." << endl; return false; } if (amount <= 0) { cout << "Amount must be positive." << endl; return false; } if (amount > balance) { cout << "Insufficient funds." << endl; return false; } balance -= amount; logTransaction("Withdrawal", amount); return true; } bool transferTo(BankAccount &destination, double amount, string enteredPin) { if (withdraw(amount, enteredPin)) { destination.deposit(amount, destination.pinCode); cout << "Transfer successful to: " << destination.getAccountNumber() << endl; return true; } return false; } void displaySummary(string enteredPin) { if (validatePin(enteredPin)) { cout << "\n=== ACCOUNT SUMMARY ===" << endl; cout << "Holder: " << accountHolderName << endl; cout << "Account: " << getAccountNumber() << endl; cout << "Balance: $" << balance << endl; } else { cout << "Invalid PIN. Cannot display summary." << endl; } } }; int main() { BankAccount acc1("1234567890", "John Doe", "1234", 1000); BankAccount acc2("9876543210", "Jane Smith", "5678", 500); // acc1.balance = 1000000; // ERROR: 'balance' is private // cout << acc1.pinCode; // ERROR: 'pinCode' is private acc1.displaySummary("1234"); acc1.deposit(500, "1234"); acc1.withdraw(300, "1234"); acc1.transferTo(acc2, 200, "1234"); return 0; }
Key Points About Encapsulation
- Data Hiding: Private members cannot be accessed directly
- Controlled Access: Public methods act as gatekeepers
- Validation: Setters can validate data before accepting it
- Internal Logic: Private methods handle internal operations
- Information Hiding: Users don't need to know how data is stored
Abstraction
Definition
Abstraction is the concept of hiding complex implementation details and showing only the essential features of an object. It focuses on what an object does rather than how it does it.
Further reading: cppreference — Abstract classes · GFG — Abstraction in C++
Abstract Class vs Concrete Class
| Abstract Class | Concrete Class |
|---|---|
| Has at least one pure virtual function | No pure virtual functions |
| Cannot be instantiated | Can be instantiated |
| Serves as a blueprint | Complete implementation |
Why Abstraction?
- Simplifies Complexity: Users interact with a simple interface
- Reduces Learning Curve: Don't need to understand internal workings
- Improves Maintainability: Internal changes don't affect users
- Enforces Consistency: All derived classes must implement abstract methods
- Promotes Extensibility: Easy to add new types
= 0: virtual double calculateArea() = 0; — any class containing one becomes abstract and cannot be instantiated.
Complete Abstraction Example — Shape Hierarchy
#include <iostream> #include <string> #include <vector> #include <cmath> using namespace std; class Shape { protected: string color, name; public: Shape(string shapeName, string shapeColor) : name(shapeName), color(shapeColor) {} virtual double calculateArea() = 0; virtual double calculatePerimeter() = 0; virtual void display() { cout << "\n=== " << name << " ===\nColor: " << color << "\nArea: " << calculateArea() << "\nPerimeter: " << calculatePerimeter() << endl; } virtual ~Shape() {} }; class Circle : public Shape { private: double radius; const double PI = 3.14159; public: Circle(string color, double r) : Shape("Circle", color), radius(r) { if(radius<=0) radius=1; } double calculateArea() override { return PI*radius*radius; } double calculatePerimeter() override { return 2*PI*radius; } void display() override { Shape::display(); cout << "Radius: " << radius << endl; } }; class Rectangle : public Shape { private: double length, width; public: Rectangle(string c, double l, double w) : Shape("Rectangle",c), length(l), width(w) {} double calculateArea() override { return length*width; } double calculatePerimeter() override { return 2*(length+width); } }; class Triangle : public Shape { private: double side1, side2, side3; public: Triangle(string c, double s1, double s2, double s3) : Shape("Triangle",c), side1(s1), side2(s2), side3(s3) {} double calculateArea() override { double s=(side1+side2+side3)/2; return sqrt(s*(s-side1)*(s-side2)*(s-side3)); } double calculatePerimeter() override { return side1+side2+side3; } }; class ShapeManager { private: vector<Shape*> shapes; public: void addShape(Shape* s) { shapes.push_back(s); } void displayAll() { for(Shape* s:shapes) s->display(); } double totalArea() { double t=0; for(Shape* s:shapes) t+=s->calculateArea(); return t; } ~ShapeManager() { for(Shape* s:shapes) delete s; } }; int main() { ShapeManager m; m.addShape(new Circle("Red",5)); m.addShape(new Rectangle("Blue",4,6)); m.addShape(new Triangle("Green",3,4,5)); m.displayAll(); cout << "Total area: " << m.totalArea() << endl; }
Key Points About Abstraction
- Pure Virtual Functions:
virtual f() = 0makes a class abstract - Cannot Instantiate: Abstract classes cannot create objects directly
- Must Override: Derived classes must implement all pure virtual functions
- Interface vs Implementation: Abstract class defines interface; derived classes provide implementation
- Polymorphism: Base class pointers can call derived class implementations
Inheritance
Definition
Inheritance is a mechanism where a new class (derived/child class) inherits properties and behaviours from an existing class (base/parent class). It establishes an "is-a" relationship between classes.
See also: cppreference — Derived classes · GFG — Inheritance in C++
Types of Inheritance in C++
Access Specifiers in Inheritance
| Base Class Access | Public Inheritance | Protected Inheritance | Private Inheritance |
|---|---|---|---|
public | public in derived | protected in derived | private in derived |
protected | protected in derived | protected in derived | private in derived |
private | inaccessible | inaccessible | inaccessible |
Complete Inheritance Example — Person Hierarchy
class Person { protected: string name; int age; string id; public: Person(string n, int a, string idNum) : name(n), age(a), id(idNum) {} virtual ~Person() {} virtual void introduce() { cout << "Hi, I'm " << name << ", Age: " << age << endl; } string getName() { return name; } }; class Student : public Person { private: string studentId; double gpa; vector<string> courses; public: Student(string n, int a, string idNum, string sId, double g) : Person(n,a,idNum), studentId(sId), gpa(g) {} void introduce() override { Person::introduce(); cout << "Student ID: " << studentId << ", GPA: " << gpa << endl; } void addCourse(string c) { courses.push_back(c); } void study() { cout << name << " is studying." << endl; } }; class Teacher : public Person { private: string employeeId, department; double salary; public: Teacher(string n, int a, string idNum, string eId, string dept, double sal) : Person(n,a,idNum), employeeId(eId), department(dept), salary(sal) {} void introduce() override { Person::introduce(); cout << "Dept: " << department << ", Salary: $" << salary << endl; } void teach(string c) { cout << name << " is teaching " << c << endl; } };
class GraduateStudent : public Student { private: string thesisTopic, supervisor; public: GraduateStudent(string n, int a, string idNum, string sId, double g, string topic, string sup) : Student(n,a,idNum,sId,g), thesisTopic(topic), supervisor(sup) {} void introduce() override { Student::introduce(); cout << "Thesis: " << thesisTopic << ", Supervisor: " << supervisor << endl; } void research() { cout << name << " is researching " << thesisTopic << endl; } void writeThesis() { cout << name << " is writing thesis..." << endl; } };
class TeachingAssistant : public Student, public Teacher { private: string contractType; double hoursPerWeek; public: TeachingAssistant(string n, int a, string idNum, string sId, double g, string eId, string dept, double sal, string contract, double hours) : Student(n,a,idNum,sId,g), Teacher(n,a,idNum,eId,dept,sal), contractType(contract), hoursPerWeek(hours) {} void introduce() { cout << "Name: " << Student::getName() << endl; cout << "Contract: " << contractType << ", " << hoursPerWeek << " hrs/wk" << endl; } };
Key Points About Inheritance
- "is-a" Relationship: Derived class is a type of base class
- Code Reuse: Inherit common functionality from base class
- Extensibility: Add new features without modifying existing code
- Polymorphism: Base class pointers/references can refer to derived objects
- Constructor/Destructor Order: Base constructed first, destroyed last
- Access Control: Protected members accessible in derived classes
Polymorphism
Definition
Polymorphism (Greek for "many forms") allows objects of different types to respond to the same function call in different ways. It provides a single interface to entities of different types.
See also: cppreference — Virtual functions · GFG — Polymorphism in C++
Types of Polymorphism
1. Function Overloading (Compile-Time)
class Calculator { public: int add(int a, int b) { return a+b; } int add(int a, int b, int c) { return a+b+c; } double add(double a, double b) { return a+b; } string add(string a, string b) { return a+b; } double add(int a, double b) { return a+b; } }; class Display { public: void show(int i) { cout << "Integer: " << i << endl; } void show(double d) { cout << "Double: " << d << endl; } void show(string s) { cout << "String: " << s << endl; } void show(int i, string s) { cout << i << " and " << s << endl; } }; int main() { Calculator calc; cout << calc.add(5, 10) << endl; cout << calc.add(3.14, 2.86) << endl; cout << calc.add("Hello ", "World") << endl; }
2. Operator Overloading (Compile-Time)
class ComplexNumber { private: double real, imag; public: ComplexNumber(double r=0, double i=0) : real(r), imag(i) {} ComplexNumber operator+(const ComplexNumber& o) const { return {real+o.real, imag+o.imag}; } ComplexNumber operator-(const ComplexNumber& o) const { return {real-o.real, imag-o.imag}; } ComplexNumber operator*(const ComplexNumber& o) const { return {real*o.real - imag*o.imag, real*o.imag + imag*o.real}; } bool operator==(const ComplexNumber& o) const { return real==o.real && imag==o.imag; } ComplexNumber& operator++() { ++real; ++imag; return *this; } friend ostream& operator<<(ostream& os, const ComplexNumber& c) { os << c.real; c.imag >= 0 ? os << " + " << c.imag << "i" : os << " - " << -c.imag << "i"; return os; } double magnitude() const { return sqrt(real*real + imag*imag); } };
3. Virtual Functions — Run-Time Polymorphism
class Employee { protected: string name; int id; double baseSalary; public: Employee(string n, int i, double sal) : name(n), id(i), baseSalary(sal) {} virtual ~Employee() {} virtual double calculateSalary() const = 0; virtual string getRole() const = 0; virtual void displayInfo() const { cout << "ID: " << id << " Name: " << name << " Role: " << getRole() << " Salary: $" << calculateSalary() << endl; } }; class Manager : public Employee { double bonus; int teamSize; public: Manager(string n, int i, double sal, double b, int sz) : Employee(n,i,sal), bonus(b), teamSize(sz) {} double calculateSalary() const override { return baseSalary+bonus+teamSize*1000; } string getRole() const override { return "Manager"; } }; class Engineer : public Employee { string spec; int overtime; double rate; public: Engineer(string n, int i, double sal, string s, int h, double r) : Employee(n,i,sal), spec(s), overtime(h), rate(r) {} double calculateSalary() const override { return baseSalary+overtime*rate; } string getRole() const override { return "Engineer"; } }; class Intern : public Employee { string school; int weeks; public: Intern(string n, int i, double sal, string s, int w) : Employee(n,i,sal), school(s), weeks(w) {} double calculateSalary() const override { return baseSalary; } string getRole() const override { return "Intern"; } }; int main() { vector<Employee*> company; company.push_back(new Manager("Alice",1001,80000,10000,8)); company.push_back(new Engineer("Bob",1002,70000,"C++",10,50)); company.push_back(new Intern("Carol",1003,2000,"MIT",12)); double total=0; for(Employee* e:company){ e->displayInfo(); total+=e->calculateSalary(); } cout << "Total payroll: $" << total << endl; for(Employee* e:company) delete e; }
4. Virtual Functions Deep Dive — VTable
class Base { public: void nonVirtual() { cout << "Base::nonVirtual()" << endl; } virtual void virtualFunc() { cout << "Base::virtualFunc()" << endl; } virtual void pureVirtual() = 0; virtual ~Base() {} }; class Derived : public Base { public: void nonVirtual() { cout << "Derived::nonVirtual()" << endl; } void virtualFunc() override { cout << "Derived::virtualFunc()" << endl; } void pureVirtual() override { cout << "Derived::pureVirtual()" << endl; } }; int main() { Base* ptr = new Derived(); ptr->nonVirtual(); // Compile-time: Base::nonVirtual() ptr->virtualFunc(); // Run-time: Derived::virtualFunc() ptr->pureVirtual(); // Run-time: Derived::pureVirtual() delete ptr; }
The Diamond Problem in C++
What is the Diamond Problem?
The Diamond Problem is an ambiguity issue that arises in multiple inheritance when a derived class inherits from two classes that both share a common base class. This creates two separate copies of the base class, causing ambiguity when accessing inherited members.
See also: cppreference — Virtual base classes · GFG — Multiple Inheritance
class Person { protected: string name; int age; public: Person(string n="", int a=0) : name(n), age(a) {} virtual ~Person() {} string getName() { return name; } }; class Student : public Person { // Person copy #1 protected: string studentId; public: Student(string n, int a, string id) : Person(n,a), studentId(id) {} }; class Teacher : public Person { // Person copy #2 protected: string employeeId; public: Teacher(string n, int a, string id) : Person(n,a), employeeId(id) {} }; class TeachingAssistant : public Student, public Teacher { public: TeachingAssistant(string n, int a, string sId, string eId) : Student(n,a,sId), Teacher(n,a,eId) {} void demonstrate() { // getName(); // ERROR: ambiguous! cout << Student::getName(); // must qualify cout << Teacher::getName(); // must qualify } };
class VStudent : virtual public Person { protected: string studentId; public: VStudent(string n, int a, string id) : Person(n,a), studentId(id) {} }; class VTeacher : virtual public Person { protected: string employeeId; public: VTeacher(string n, int a, string id) : Person(n,a), employeeId(id) {} }; class VTeachingAssistant : public VStudent, public VTeacher { private: string contractType; public: VTeachingAssistant(string n, int a, string sId, string eId, string c) : Person(n,a), // constructs the shared Person ONCE VStudent(n,a,sId), VTeacher(n,a,eId), contractType(c) {} void introduce() { cout << name << ", TA" << endl; // no ambiguity cout << getName() << endl; // direct access works } }; // Memory layout: // Without virtual: [Person][Student] [Person][Teacher] [TA] — 2 Persons // With virtual: [Person (shared)] [Student] [Teacher] [TA] — 1 Person
Virtual Functions vs Virtual Inheritance
| Concept | Virtual Functions | Virtual Inheritance |
|---|---|---|
| Purpose | Runtime polymorphism | Solve diamond problem |
| When used | Function overriding | Multiple inheritance |
| Effect | Dynamic dispatch | Single shared base instance |
| Keyword | virtual before function | virtual before base class |
| Memory impact | VTable per class | Extra indirection for base |
Comprehensive Programming Tasks
Task 1 — Bank Account System (Encapsulation)
#include <iostream> #include <string> #include <vector> #include <ctime> using namespace std; class BankAccount { private: string accountNumber, accountHolderName, pin; double balance; vector<string> transactionHistory; bool isActive; int failedAttempts; const int MAX_FAILED = 3; string getTime() { time_t now=time(0); return ctime(&now); } void log(string type, double amount) { transactionHistory.push_back(getTime()+": "+type+" $"+to_string(amount)+" Bal:$"+to_string(balance)); } bool auth(string p) { if(p==pin){failedAttempts=0;return true;} failedAttempts++; return false; } bool locked() { return failedAttempts>=MAX_FAILED; } public: BankAccount(string acc, string name, string pinCode, double init=0) : accountNumber(acc), accountHolderName(name), pin(pinCode), balance(init>=0?init:0), isActive(true), failedAttempts(0) { log("Created",init); } bool deposit(double a, string p) { if(!auth(p)||locked()) { cout<<"Auth failed\n"; return false; } if(a<=0) { cout<<"Positive amounts only\n"; return false; } balance+=a; log("Deposit",a); cout<<"Deposited $"<<a<<". Bal: $"<<balance<<"\n"; return true; } bool withdraw(double a, string p) { if(!auth(p)||locked()) { cout<<"Auth failed\n"; return false; } if(a<=0) { cout<<"Positive amounts only\n"; return false; } if(a>balance) { cout<<"Insufficient funds\n"; return false; } balance-=a; log("Withdrawal",a); cout<<"Withdrew $"<<a<<". Bal: $"<<balance<<"\n"; return true; } void showHistory(string p) { if(!auth(p)||locked()) { cout<<"Auth failed\n"; return; } cout<<"\n=== HISTORY ===\n"; for(const string& t:transactionHistory) cout<<t; } }; int main() { BankAccount acc("1234567890","John Doe","1234",1000); acc.deposit(500,"1234"); acc.withdraw(200,"1234"); acc.withdraw(2000,"1234"); acc.withdraw(100,"0000"); acc.showHistory("1234"); }
Task 2 — Abstract Shape Class (Abstraction)
#include <iostream> #include <vector> #include <cmath> using namespace std; class Shape { protected: string color, name; public: Shape(string n, string c) : name(n), color(c) {} virtual double area() const=0; virtual double perimeter() const=0; virtual void display() const { cout<<"\n=== "<<name<<" ===\nColor: "<<color <<"\nArea: "<<area()<<"\nPerimeter: "<<perimeter()<<endl; } virtual ~Shape() {} }; class Rectangle : public Shape { double l,w; public: Rectangle(string c,double l,double w):Shape("Rectangle",c),l(l>0?l:1),w(w>0?w:1){} double area() const override{return l*w;} double perimeter() const override{return 2*(l+w);} void display() const override{Shape::display();cout<<"Is square: "<<(l==w?"Yes":"No")<<endl;} }; class Circle : public Shape { double r; const double PI=3.14159; public: Circle(string c,double r):Shape("Circle",c),r(r>0?r:1){} double area() const override{return PI*r*r;} double perimeter() const override{return 2*PI*r;} }; class Triangle : public Shape { double s1,s2,s3; public: Triangle(string c,double a,double b,double d):Shape("Triangle",c),s1(a),s2(b),s3(d){} double area() const override{double s=(s1+s2+s3)/2;return sqrt(s*(s-s1)*(s-s2)*(s-s3));} double perimeter() const override{return s1+s2+s3;} }; int main() { vector<Shape*> shapes={new Rectangle("Red",5,3),new Circle("Blue",4),new Triangle("Green",3,4,5)}; double total=0; for(Shape* s:shapes){s->display();total+=s->area();} cout<<"\nTotal Area: "<<total<<endl; for(Shape* s:shapes) delete s; }
Task 3 — Employee Hierarchy with Virtual Functions (Polymorphism)
#include <iostream> #include <vector> #include <string> using namespace std; class Employee { protected: string name; int id; double baseSalary; public: Employee(string n,int i,double s):name(n),id(i),baseSalary(s){} virtual~Employee(){} virtual double calculatePay() const=0; virtual string getRole() const=0; virtual void display() const{ cout<<"ID: "<<id<<" | "<<name<<" | "<<getRole()<<" | $"<<calculatePay()<<endl; } int getId() const{return id;} }; class Manager:public Employee{ double bonus; vector<int> team; public: Manager(string n,int i,double s,double b):Employee(n,i,s),bonus(b){} double calculatePay() const override{return baseSalary+bonus+team.size()*500;} string getRole() const override{return "Manager";} void addMember(int id){team.push_back(id);} }; class Engineer:public Employee{ string spec; int overtime; double rate; public: Engineer(string n,int i,double s,string sp,double r):Employee(n,i,s),spec(sp),overtime(0),rate(r){} double calculatePay() const override{return baseSalary+overtime*rate;} string getRole() const override{return "Engineer ("+spec+")";} void addOvertime(int h){if(h>0)overtime+=h;} }; class Intern:public Employee{ string school; int weeks; public: Intern(string n,int i,double s,string sc,int w):Employee(n,i,s),school(sc),weeks(w){} double calculatePay() const override{return baseSalary;} string getRole() const override{return "Intern @ "+school;} }; class PayrollSystem{ vector<Employee*> employees; public: void add(Employee* e){employees.push_back(e);} Employee* find(int id){ for(auto* e:employees)if(e->getId()==id)return e; return nullptr; } void run(){ double total=0; cout<<"\n=== PAYROLL ===\n"; for(auto* e:employees){e->display();total+=e->calculatePay();} cout<<"TOTAL: $"<<total<<endl; } ~PayrollSystem(){for(auto* e:employees)delete e;} }; int main(){ PayrollSystem p; p.add(new Manager("Alice",1001,80000,10000)); p.add(new Engineer("Bob",1002,70000,"C++",50)); p.add(new Intern("Carol",1003,2000,"MIT",12)); if(Engineer* b=dynamic_cast<Engineer*>(p.find(1002))) b->addOvertime(10); p.run(); }
Summary
| Pillar | Purpose | How Achieved | Key Benefit |
|---|---|---|---|
| Encapsulation | Bundle data and methods, hide internal details | Private members, public getters/setters | Data protection, controlled access |
| Abstraction | Show essential features, hide implementation | Pure virtual functions, abstract classes | Simplify complex systems |
| Inheritance | Reuse code, establish relationships | Derive classes from base classes | Code reusability, hierarchical organisation |
| Polymorphism | One interface, many implementations | Function overloading, virtual functions | Flexibility, extensibility |
Further Resources
- ISO C++ FAQ — official FAQ on C++ features and best practices
- cppreference — Classes — comprehensive language reference
- learncpp.com — OOP Chapter — beginner-friendly tutorials
- GeeksforGeeks C++ — examples and problem sets
- Compiler Explorer — run and explore C++ assembly live
- Stack Overflow C++ OOP — community Q&A
- Bjarne Stroustrup's FAQ — from the creator of C++ himself
