System Programming Topic
C++ Object-Oriented Programming
1. Classes & Objects
Classes - Blueprint/template for creating objects
cpp
#include <iostream>
#include <string>
using namespace std;
// CLASS DEFINITION: Blueprint for objects
class Student {
private: // Access specifier - only class members can access
string name;
int age;
double gpa;
public: // Access specifier - accessible from outside
// Member functions (methods)
void displayInfo() {
cout << "Name: " << name << endl;
cout << "Age: " << age << endl;
cout << "GPA: " << gpa << endl;
}
// Setter functions (mutators)
void setName(string n) {
name = n;
}
void setAge(int a) {
if (a > 0) age = a;
}
void setGPA(double g) {
if (g >= 0.0 && g <= 4.0) gpa = g;
}
// Getter functions (accessors)
string getName() { return name; }
int getAge() { return age; }
double getGPA() { return gpa; }
};
// OBJECT CREATION - Instance of a class
int main() {
// Creating objects
Student student1; // Object creation using default constructor
Student student2; // Another independent object
// Accessing member functions using dot operator
student1.setName("Alice");
student1.setAge(20);
student1.setGPA(3.8);
student2.setName("Bob");
student2.setAge(22);
student2.setGPA(3.5);
// Display information
cout << "Student 1:" << endl;
student1.displayInfo();
cout << "\nStudent 2:" << endl;
student2.displayInfo();
// Accessing data through getters
cout << "\nStudent 1's GPA: " << student1.getGPA() << endl;
return 0;
}
Access Specifiers & Member Functions
cpp
#include <iostream>
using namespace std;
class BankAccount {
private: // Encapsulation: Data hiding
double balance;
string accountNumber;
protected: // Accessible in this class and derived classes
string bankName;
public: // Public interface
// Member function types:
// 1. Accessor (getter) - const member function
double getBalance() const {
return balance;
}
// 2. Mutator (setter)
void setAccountNumber(string accNum) {
accountNumber = accNum;
}
// 3. Utility function
void displayAccountInfo() const {
cout << "Account: " << accountNumber << endl;
cout << "Balance: $" << balance << endl;
cout << "Bank: " << bankName << endl;
}
// 4. Operation function
void deposit(double amount) {
if (amount > 0) {
balance += amount;
cout << "Deposited: $" << amount << endl;
}
}
bool withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
cout << "Withdrawn: $" << amount << endl;
return true;
}
cout << "Insufficient funds!" << endl;
return false;
}
};
int main() {
BankAccount account;
// account.balance = 1000; // Error: private member
account.deposit(1000);
account.displayAccountInfo();
return 0;
}
2. Constructors & Destructors
Constructors - Special functions called when object is created
cpp
#include <iostream>
#include <string>
using namespace std;
class Book {
private:
string title;
string author;
double price;
int pages;
public:
// 1. DEFAULT CONSTRUCTOR - No parameters
Book() {
title = "Unknown";
author = "Unknown";
price = 0.0;
pages = 0;
cout << "Default constructor called!" << endl;
}
// 2. PARAMETERIZED CONSTRUCTOR - Takes parameters
Book(string t, string a, double p, int pg) {
title = t;
author = a;
price = p;
pages = pg;
cout << "Parameterized constructor called!" << endl;
}
// 3. COPY CONSTRUCTOR - Creates copy of another object
Book(const Book& other) {
title = other.title;
author = other.author;
price = other.price;
pages = other.pages;
cout << "Copy constructor called!" << endl;
}
// 4. CONSTRUCTOR WITH DEFAULT ARGUMENTS
Book(string t, string a = "Anonymous", double p = 0.0) {
title = t;
author = a;
price = p;
pages = 100;
}
// 5. DESTRUCTOR - Called when object is destroyed
~Book() {
cout << "Destructor called for: " << title << endl;
}
// Member function
void display() {
cout << "Title: " << title << endl;
cout << "Author: " << author << endl;
cout << "Price: $" << price << endl;
cout << "Pages: " << pages << endl;
}
// Setter for copy demonstration
void setTitle(string t) { title = t; }
};
int main() {
cout << "=== CONSTRUCTORS DEMO ===\n" << endl;
// 1. Default constructor
Book book1;
book1.display();
// 2. Parameterized constructor
Book book2("C++ Programming", "Bjarne Stroustrup", 49.99, 500);
book2.display();
// 3. Constructor with default arguments
Book book3("Learn Python");
book3.display();
// 4. Copy constructor (3 ways it's called)
cout << "\n=== COPY CONSTRUCTOR SCENARIOS ===" << endl;
// a) Explicit copy
Book book4 = book2; // Copy constructor
book4.setTitle("Copy of C++");
book4.display();
// b) Passing object by value to function
// (Destructor shows when copies are destroyed)
// c) Returning object from function
// 5. Dynamic object creation
cout << "\n=== DYNAMIC OBJECTS ===" << endl;
Book* ptrBook = new Book("Dynamic Book", "Author", 29.99, 300);
ptrBook->display();
delete ptrBook; // Destructor called
cout << "\n=== END OF MAIN - Destructors will be called ===" << endl;
return 0;
}
// Destructors for book1, book2, book3, book4 called here
3. Inheritance
Inheritance - Creating new classes from existing ones (IS-A relationship)
cpp
#include <iostream>
#include <string>
using namespace std;
// BASE CLASS (Parent/Super class)
class Vehicle {
protected: // Accessible in derived classes
string brand;
string model;
int year;
public:
Vehicle(string b, string m, int y) : brand(b), model(m), year(y) {
cout << "Vehicle constructor called" << endl;
}
void displayInfo() {
cout << "Brand: " << brand << endl;
cout << "Model: " << model << endl;
cout << "Year: " << year << endl;
}
void honk() {
cout << "Beep beep!" << endl;
}
};
// 1. SINGLE INHERITANCE - One base class
class Car : public Vehicle { // Derived class (Child/Sub class)
private:
int doors;
string fuelType;
public:
// Constructor with initialization list
Car(string b, string m, int y, int d, string f)
: Vehicle(b, m, y), doors(d), fuelType(f) {
cout << "Car constructor called" << endl;
}
void displayCarInfo() {
displayInfo(); // Call base class function
cout << "Doors: " << doors << endl;
cout << "Fuel: " << fuelType << endl;
}
};
// 2. MULTILEVEL INHERITANCE - Chain of inheritance
class SportsCar : public Car {
private:
double topSpeed;
public:
SportsCar(string b, string m, int y, int d, string f, double ts)
: Car(b, m, y, d, f), topSpeed(ts) {
cout << "SportsCar constructor called" << endl;
}
void displaySportsInfo() {
displayCarInfo();
cout << "Top Speed: " << topSpeed << " mph" << endl;
}
void race() {
cout << "Racing at high speed!" << endl;
}
};
// 3. MULTIPLE INHERITANCE - Inheriting from multiple base classes
class Engine {
protected:
int horsepower;
public:
Engine(int hp) : horsepower(hp) {}
void startEngine() {
cout << "Engine started with " << horsepower << " HP" << endl;
}
};
class Electric {
protected:
int batteryCapacity;
public:
Electric(int cap) : batteryCapacity(cap) {}
void charge() {
cout << "Charging battery: " << batteryCapacity << " kWh" << endl;
}
};
// Multiple inheritance
class ElectricCar : public Car, public Electric {
public:
ElectricCar(string b, string m, int y, int d, string f, int cap)
: Car(b, m, y, d, f), Electric(cap) {
cout << "ElectricCar constructor called" << endl;
}
void displayElectricInfo() {
displayCarInfo();
charge();
}
};
// ACCESS CONTROL in inheritance
class Base {
private: // Only Base can access
int privateVar = 1;
protected: // Base and derived classes can access
int protectedVar = 2;
public: // Anyone can access
int publicVar = 3;
void show() {
cout << "Private: " << privateVar << endl; // OK
}
};
// Different types of inheritance
class DerivedPublic : public Base {
// publicVar stays public
// protectedVar stays protected
// privateVar is inaccessible
};
class DerivedPrivate : private Base {
// publicVar becomes private
// protectedVar becomes private
// privateVar is inaccessible
};
class DerivedProtected : protected Base {
// publicVar becomes protected
// protectedVar stays protected
// privateVar is inaccessible
};
int main() {
cout << "=== SINGLE INHERITANCE ===" << endl;
Car myCar("Toyota", "Camry", 2022, 4, "Gasoline");
myCar.displayCarInfo();
myCar.honk(); // Inherited from Vehicle
cout << "\n=== MULTILEVEL INHERITANCE ===" << endl;
SportsCar ferrari("Ferrari", "F8", 2023, 2, "Gasoline", 211);
ferrari.displaySportsInfo();
ferrari.race();
cout << "\n=== MULTIPLE INHERITANCE ===" << endl;
ElectricCar tesla("Tesla", "Model 3", 2023, 4, "Electric", 75);
tesla.displayElectricInfo();
tesla.startEngine(); // If Engine was also inherited
cout << "\n=== ACCESS CONTROL ===" << endl;
DerivedPublic dp;
cout << "Public var: " << dp.publicVar << endl; // OK
// cout << dp.protectedVar; // Error: protected
// cout << dp.privateVar; // Error: private
return 0;
}
4. Polymorphism
Polymorphism - "Many forms", same interface, different implementations
cpp
#include <iostream>
using namespace std;
// BASE CLASS with virtual function
class Shape {
protected:
string color;
public:
Shape(string c) : color(c) {}
// VIRTUAL FUNCTION - Enables runtime polymorphism
virtual double calculateArea() const {
cout << "Shape area calculation" << endl;
return 0.0;
}
// PURE VIRTUAL FUNCTION - Makes class abstract
virtual void draw() const = 0; // Abstract class
virtual ~Shape() { // Virtual destructor
cout << "Shape destructor" << endl;
}
void setColor(string c) { color = c; }
string getColor() const { return color; }
};
// DERIVED CLASS 1
class Circle : public Shape {
private:
double radius;
public:
Circle(string c, double r) : Shape(c), radius(r) {}
// FUNCTION OVERRIDING - Same signature, different implementation
double calculateArea() const override { // override keyword ensures correct override
return 3.14159 * radius * radius;
}
void draw() const override {
cout << "Drawing a " << color << " circle" << endl;
}
~Circle() {
cout << "Circle destructor" << endl;
}
};
// DERIVED CLASS 2
class Rectangle : public Shape {
private:
double length, width;
public:
Rectangle(string c, double l, double w) : Shape(c), length(l), width(w) {}
double calculateArea() const override {
return length * width;
}
void draw() const override {
cout << "Drawing a " << color << " rectangle" << endl;
}
~Rectangle() {
cout << "Rectangle destructor" << endl;
}
};
// DERIVED CLASS 3
class Triangle : public Shape {
private:
double base, height;
public:
Triangle(string c, double b, double h) : Shape(c), base(b), height(h) {}
double calculateArea() const override {
return 0.5 * base * height;
}
void draw() const override {
cout << "Drawing a " << color << " triangle" << endl;
}
};
// Demonstrating POLYMORPHISM
void printArea(const Shape& shape) {
cout << "Area: " << shape.calculateArea() << endl;
}
void drawShape(const Shape* shape) {
shape->draw();
}
int main() {
cout << "=== RUNTIME POLYMORPHISM ===\n" << endl;
// Base class pointer to derived class objects
Shape* shapes[3];
shapes[0] = new Circle("Red", 5.0);
shapes[1] = new Rectangle("Blue", 4.0, 6.0);
shapes[2] = new Triangle("Green", 3.0, 4.0);
// Same interface, different implementations
for (int i = 0; i < 3; i++) {
cout << "Shape " << i + 1 << ": ";
shapes[i]->draw();
cout << "Color: " << shapes[i]->getColor() << endl;
cout << "Area: " << shapes[i]->calculateArea() << endl;
cout << endl;
}
// Using references
Circle circle("Yellow", 3.0);
Rectangle rectangle("Purple", 5.0, 2.0);
cout << "Using printArea function:" << endl;
printArea(circle); // Calls Circle::calculateArea()
printArea(rectangle); // Calls Rectangle::calculateArea()
// Clean up
for (int i = 0; i < 3; i++) {
delete shapes[i];
}
cout << "\n=== FUNCTION OVERRIDING VS OVERLOADING ===" << endl;
return 0;
}
// Example showing override keyword importance
class BaseClass {
public:
virtual void display(int x) {
cout << "Base: " << x << endl;
}
};
class DerivedClass : public BaseClass {
public:
// Error if uncommented (detected by override keyword)
// void display(double x) override { // Error: doesn't override
// cout << "Derived: " << x << endl;
// }
void display(int x) override { // Correct override
cout << "Derived: " << x << endl;
}
};
5. Encapsulation & Abstraction
Encapsulation - Bundling data and methods, hiding implementation details
Abstraction - Showing only essential features, hiding complexity
cpp
#include <iostream>
#include <string>
using namespace std;
// ENCAPSULATION EXAMPLE
class BankAccount {
private: // Data hiding - internal details hidden
string accountNumber;
double balance;
string password;
// Private helper methods (implementation details hidden)
bool authenticate(string pwd) {
return pwd == password;
}
void logTransaction(string type, double amount) {
cout << "[LOG] " << type << ": $" << amount << endl;
}
public: // Public interface - what users can do
BankAccount(string accNum, string pwd, double initial = 0.0)
: accountNumber(accNum), password(pwd), balance(initial) {}
// Abstraction: Simple interface for complex operations
bool deposit(double amount, string pwd) {
if (!authenticate(pwd)) {
cout << "Authentication failed!" << endl;
return false;
}
if (amount > 0) {
balance += amount;
logTransaction("DEPOSIT", amount);
return true;
}
return false;
}
bool withdraw(double amount, string pwd) {
if (!authenticate(pwd)) {
cout << "Authentication failed!" << endl;
return false;
}
if (amount > 0 && amount <= balance) {
balance -= amount;
logTransaction("WITHDRAW", amount);
return true;
}
cout << "Invalid amount or insufficient funds!" << endl;
return false;
}
double getBalance(string pwd) {
if (authenticate(pwd)) {
return balance;
}
cout << "Authentication failed!" << endl;
return -1;
}
// Users don't need to know about authentication or logging
};
// ABSTRACTION with Abstract Classes (Interfaces)
class Vehicle { // Abstract class (interface)
public:
// Pure virtual functions = abstract methods
virtual void start() = 0; // Must be implemented by derived classes
virtual void stop() = 0;
virtual void honk() = 0;
// Concrete method (can have implementation)
void displayType() {
cout << "I am a Vehicle" << endl;
}
virtual ~Vehicle() {} // Virtual destructor
};
// Concrete implementation
class Car : public Vehicle {
private:
string model;
public:
Car(string m) : model(m) {}
void start() override {
cout << model << " car started with key" << endl;
}
void stop() override {
cout << model << " car stopped" << endl;
}
void honk() override {
cout << model << " car goes Beep Beep!" << endl;
}
};
class Bike : public Vehicle {
public:
void start() override {
cout << "Bike started with kick" << endl;
}
void stop() override {
cout << "Bike stopped with brakes" << endl;
}
void honk() override {
cout << "Bike goes Ring Ring!" << endl;
}
};
// Using abstraction - client code works with Vehicle interface
void operateVehicle(Vehicle* v) {
v->start();
v->honk();
v->stop();
cout << endl;
}
// Complete example combining concepts
class SmartHomeDevice {
private: // ENCAPSULATION
string deviceId;
bool isOn;
int powerConsumption;
protected: // For inheritance
string location;
public: // ABSTRACTION
SmartHomeDevice(string id, string loc, int power = 0)
: deviceId(id), location(loc), powerConsumption(power), isOn(false) {}
virtual void turnOn() { // Can be overridden
isOn = true;
cout << deviceId << " turned ON" << endl;
}
virtual void turnOff() {
isOn = false;
cout << deviceId << " turned OFF" << endl;
}
virtual void getStatus() { // Can be overridden
cout << "Device: " << deviceId << endl;
cout << "Location: " << location << endl;
cout << "Status: " << (isOn ? "ON" : "OFF") << endl;
cout << "Power: " << powerConsumption << "W" << endl;
}
// Pure virtual function - makes class abstract
virtual void performAction() = 0;
virtual ~SmartHomeDevice() {}
};
// Concrete implementations
class SmartLight : public SmartHomeDevice {
private:
int brightness;
string color;
public:
SmartLight(string id, string loc)
: SmartHomeDevice(id, loc, 10), brightness(50), color("White") {}
void turnOn() override {
SmartHomeDevice::turnOn();
cout << "Light brightness: " << brightness << "%" << endl;
}
void performAction() override {
cout << "Emitting " << color << " light at " << brightness << "% brightness" << endl;
}
void setBrightness(int level) { // Extended functionality
brightness = level;
cout << "Brightness set to " << brightness << "%" << endl;
}
void setColor(string c) {
color = c;
cout << "Color changed to " << color << endl;
}
};
class SmartThermostat : public SmartHomeDevice {
private:
double temperature;
public:
SmartThermostat(string id, string loc, double temp = 22.0)
: SmartHomeDevice(id, loc, 5), temperature(temp) {}
void performAction() override {
cout << "Maintaining temperature at " << temperature << "°C" << endl;
}
void setTemperature(double temp) {
temperature = temp;
cout << "Temperature set to " << temperature << "°C" << endl;
}
};
int main() {
cout << "=== ENCAPSULATION EXAMPLE ===" << endl;
BankAccount myAccount("ACC123", "secret123", 1000.0);
// User interacts with simple interface
myAccount.deposit(500, "secret123");
myAccount.withdraw(200, "secret123");
cout << "Balance: $" << myAccount.getBalance("secret123") << endl;
// Can't access internal details
// myAccount.balance = 10000; // Error: private
// myAccount.password = "hack"; // Error: private
cout << "\n=== ABSTRACTION EXAMPLE ===" << endl;
Car toyota("Toyota");
Bike bmx;
operateVehicle(&toyota);
operateVehicle(&bmx);
// Working with abstract interface
Vehicle* garage[2];
garage[0] = new Car("Honda");
garage[1] = new Bike();
for (int i = 0; i < 2; i++) {
garage[i]->displayType();
garage[i]->start();
garage[i]->honk();
cout << endl;
}
cout << "\n=== SMART HOME EXAMPLE (Combined) ===" << endl;
SmartLight livingRoomLight("LR1", "Living Room");
SmartThermostat hallThermostat("TH1", "Hall", 22.5);
livingRoomLight.turnOn();
livingRoomLight.setBrightness(75);
livingRoomLight.setColor("Warm White");
livingRoomLight.performAction();
cout << endl;
hallThermostat.turnOn();
hallThermostat.setTemperature(21.5);
hallThermostat.performAction();
// Clean up
for (int i = 0; i < 2; i++) {
delete garage[i];
}
return 0;
}
Key OOP Principles Summary:
-
Encapsulation: Bundle data + methods, hide implementation details
-
Uses
private/protectedaccess specifiers -
Provides getters/setters for controlled access
-
-
Inheritance: Create new classes from existing ones
-
Promotes code reuse
-
Types: Single, Multilevel, Multiple
-
Access control:
public,protected,privateinheritance
-
-
Polymorphism: Same interface, different implementations
-
Compile-time: Function overloading, operator overloading
-
Runtime: Virtual functions, function overriding
-
Uses
virtualkeyword and base class pointers/references
-
-
Abstraction: Show only essential features
-
Abstract classes with pure virtual functions
-
Interfaces define what can be done, not how
-
Reduces complexity for users
-
Comments (0)
No comments yet. Be the first to comment!