BIT153 Object Oriented Programming

Object Oriented ProgrammingUnit 213 min read

Classes & Objects: Structure, Encapsulation & Real-World Modeling

Unit 2 of Object Oriented Programming: This note explains how classes and objects model real-world entities, covering their definitions, syntax, memory allocation, constructors, destructors, and practical applications with detailed examples and visuals.

TAKEAWAYS:

  • A class is a blueprint for objects, defining attributes (data) and behaviors (methods), while an object is an instance of that blueprint.
  • Encapsulation bundles data and methods into a single unit (class) and restricts direct access via access specifiers (public, private, protected).
  • Constructors initialize objects, while destructors clean up resources when objects are destroyed.
  • Objects can be passed as arguments to functions, enabling modular and reusable code.
  • Friend functions break encapsulation selectively to allow external functions to access private data.
  • Real-world systems (e.g., eSewa transactions, Daraz order processing) use classes and objects to model entities like users, payments, and inventory.

1. Introduction to Classes and Objects

1.1 Definitions

  • Class: A logical grouping of data (attributes) and functions (methods) that operate on that data. Think of it as a template or blueprint.
    classDiagram
        class Class {
            +int hours
            +int minutes
            +int seconds
            +void setTime(int h, int m, int s)
            +void displayTime()
        }
  • Object: An instance of a class. It occupies memory and holds actual data. Example: A Car class defines attributes like model, color, and methods like start(), stop(). An object like myCar is a specific instance with model = "Toyota" and color = "Red".

1.2 Why Use Classes and Objects?

Traditional (Procedural) Approach Object-Oriented Approach
Data and functions are separate. Data and functions are bundled together in a class.
Harder to maintain and reuse code. Easier to maintain, extend, and reuse.
Example: Functions manipulate global variables. Example: Objects encapsulate their own data.

Real-World Analogy:

  • Structure (C-style): Like a file cabinet where data and functions are separate drawers.
  • Class (OOP): Like a modular desk where everything related to an entity (e.g., a BankAccount) is stored together.

2. Declaring and Defining a Class

2.1 Syntax

class ClassName {
    // Access specifiers
    private:
        // Private data members
        int hours;
        int minutes;

    public:
        // Public member functions
        void setTime(int h, int m);
        void displayTime();
};

2.2 Access Specifiers

Specifier Description Example
private Data/methods are accessible only within the class. int salary;
public Data/methods are accessible from anywhere. void display();
protected Data/methods are accessible within the class and derived classes. Used in inheritance.

Visualization: Example: A BankAccount class might have private data like balance but public methods like deposit() and withdraw().


3. Creating Objects

3.1 Object Declaration

ClassName objectName;

Example:

Time myTime; // Declares an object of class Time

3.2 Memory Allocation

When an object is created, memory is allocated for its data members. For example: Figure: Memory layout for Time myTime; (assuming int is 4 bytes).

+---------------------+
| hours (4 bytes)     |
+---------------------+
| minutes (4 bytes)   |
+---------------------+
| seconds (4 bytes)   |
+---------------------+

4. Constructors

Constructors are special member functions that initialize objects when they are created.

Time(10,30,45)Time(5,0,0)Time(0,0,0)TOP
Stack of Time objects created using different constructors (top is most recently created).

4.1 Default Constructor

ClassName() {
    // Initialization code
}

Example:

class Time {
public:
    Time() { // Default constructor
        hours = 0;
        minutes = 0;
        seconds = 0;
    }
};

4.2 Parameterized Constructor

ClassName(type param1, type param2) {
    // Initialization using parameters
}

Example:

Time(int h, int m, int s) {
    hours = h;
    minutes = m;
    seconds = s;
}

4.3 Constructor Overloading

Multiple constructors with different parameters.

Time() { hours = 0; minutes = 0; seconds = 0; } // Default
Time(int h) { hours = h; minutes = 0; seconds = 0; } // Partial init
Time(int h, int m, int s) { hours = h; minutes = m; seconds = s; } // Full init

Worked Example:

#include <iostream>
using namespace std;

class Time {
private:
    int hours, minutes, seconds;
public:
    Time() { hours = minutes = seconds = 0; }
    Time(int h) { hours = h; minutes = seconds = 0; }
    Time(int h, int m, int s) { hours = h; minutes = m; seconds = s; }
    void display() {
        cout << hours << ":" << minutes << ":" << seconds << endl;
    }
};

int main() {
    Time t1;          // Uses default constructor
    Time t2(5);       // Uses parameterized constructor (h=5)
    Time t3(10, 30, 45); // Uses full parameterized constructor

    t1.display(); // Output: 0:0:0
    t2.display(); // Output: 5:0:0
    t3.display(); // Output: 10:30:45
    return 0;
}

Trace Table:

Object Constructor Called State After Initialization
t1 Default hours=0, minutes=0, seconds=0
t2 Time(int h) hours=5, minutes=0, seconds=0
t3 Time(int h, int m, int s) hours=10, minutes=30, seconds=45

5. Destructors

Destructors are called when an object is destroyed to release resources (e.g., memory, file handles).

5.1 Syntax

~ClassName() {
    // Cleanup code
}

Example:

class Resource {
public:
    Resource() { cout << "Resource allocated!" << endl; }
    ~Resource() { cout << "Resource freed!" << endl; }
};

int main() {
    Resource r; // Constructor called
    return 0;   // Destructor called when r goes out of scope
}

Output:

Resource allocated!
Resource freed!

6. Objects as Function Arguments

Objects can be passed to functions like any other data type.

100301462
Array after incrementTime() modifies the object by reference (seconds incremented).

6.1 Passing by Value

A copy of the object is passed.

void displayTime(Time t) {
    t.display();
}

Disadvantage: Inefficient for large objects.

6.2 Passing by Reference

A reference to the original object is passed (no copy).

void displayTime(Time &t) {
    t.display();
}

Advantage: More efficient and allows modification of the original object.

Example:

void incrementTime(Time &t) {
    t.seconds += 1;
    if (t.seconds >= 60) {
        t.seconds = 0;
        t.minutes += 1;
        if (t.minutes >= 60) {
            t.minutes = 0;
            t.hours += 1;
        }
    }
}

int main() {
    Time t(0, 0, 45);
    incrementTime(t); // Pass by reference
    t.display();      // Output: 0:0:46
    return 0;
}

7. Friend Functions

Friend functions are non-member functions that have access to the private and protected members of a class.

7.1 Syntax

class ClassName {
    friend returnType functionName(ClassName obj);
    // Other members...
};

Example:

class Complex {
private:
    int real, imag;
public:
    Complex(int r = 0, int i = 0) { real = r; imag = i; }
    friend Complex add(Complex c1, Complex c2); // Friend function declaration
};

Complex add(Complex c1, Complex c2) {
    return Complex(c1.real + c2.real, c1.imag + c2.imag);
}

int main() {
    Complex c1(3, 4), c2(5, 6);
    Complex c3 = add(c1, c2); // Output: (8, 10)
    return 0;
}

Why Use Friend Functions?

  • Allows external functions to access private data when necessary (e.g., arithmetic operations on private members).
  • Breaks encapsulation selectively, not entirely.

8. Real-World Applications

8.1 eSewa: Modeling Transactions

  • Class: Transaction
    • Private: amount, timestamp, userId
    • Public: processPayment(), displayDetails()
  • Objects: Each transaction is an instance of Transaction with unique amount and userId.

8.2 Daraz: Order Processing

  • Class: Order
    • Private: orderId, items, status
    • Public: addItem(), updateStatus(), calculateTotal()
  • Objects: Each customer order is an instance of Order with its own items and status.

8.3 Pathao: Ride Booking

  • Class: Ride
    • Private: driverId, passengerId, fare, route
    • Public: bookRide(), cancelRide(), calculateFare()
  • Objects: Each ride request is an instance of Ride with dynamic fare and route.

Worked Example: Daraz Order Queue

sequenceDiagram
    participant Customer
    participant OrderQueue
    participant OrderProcessor

    Customer->>OrderQueue: CreateOrder(orderId, items)
    OrderQueue->>OrderProcessor: Process(order)
    OrderProcessor->>OrderQueue: UpdateStatus("Processing")
    OrderProcessor->>OrderQueue: UpdateStatus("Shipped")
    OrderQueue->>Customer: Notify("Order shipped!")

9. Advantages and Disadvantages

Advantages Disadvantages
Encapsulation improves modularity. Overuse can lead to complex code.
Reusability of code through classes. Steeper learning curve for beginners.
Easier maintenance and debugging. Performance overhead due to object creation.
Supports inheritance and polymorphism. Not suitable for simple, small programs.

10. Exam Tips

  1. Understand Encapsulation: Always explain how private and public access specifiers restrict or allow access to data members.
  2. Constructors and Destructors: Know when and how they are called. Draw memory diagrams for object creation.
  3. Friend Functions: Highlight why they are used (e.g., for arithmetic operations) and how they break encapsulation selectively.
  4. Objects as Arguments: Practice passing objects by value vs. reference and explain the trade-offs.
  5. Real-World Mapping: Relate classes to real systems like eSewa, Daraz, or Pathao to show practical applications.
  6. Code Writing: Always include:
    • Class declaration with access specifiers.
    • Constructor(s) and destructor.
    • At least one method to demonstrate functionality.
    • A main() function to test the class.

Common Pitfalls:

  • Forgetting to initialize data members in constructors.
  • Misusing pass by value vs. pass by reference.
  • Overloading constructors incorrectly (e.g., not handling all cases).

Example Exam Question: Create a class Employee with private data members Eid, Ename, and Salary. Include public member functions read() and display(). Derive a class Typist from Employee that adds a private member speed (words per minute) and a public function calculateSalary() that returns Salary + (speed * 5). Write a program to demonstrate this.

Solution:

#include <iostream>
#include <string>
using namespace std;

class Employee {
private:
    int Eid;
    string Ename;
    float Salary;
public:
    void read() {
        cout << "Enter Employee ID: "; cin >> Eid;
        cout << "Enter Employee Name: "; cin >> Ename;
        cout << "Enter Salary: "; cin >> Salary;
    }
    void display() {
        cout << "ID: " << Eid << ", Name: " << Ename << ", Salary: " << Salary << endl;
    }
};

class Typist : public Employee {
private:
    int speed;
public:
    void readTypist() {
        read(); // Inherited function
        cout << "Enter Typing Speed (words/min): "; cin >> speed;
    }
    float calculateSalary() {
        return Salary + (speed * 5);
    }
    void displayTypist() {
        display(); // Inherited function
        cout << "Typing Speed: " << speed << " wpm" << endl;
        cout << "Total Salary: " << calculateSalary() << endl;
    }
};

int main() {
    Typist t;
    t.readTypist();
    t.displayTypist();
    return 0;
}

Trace Table:

Step Action State After Action
1 t.readTypist() called Eid, Ename, Salary read; speed read
2 t.displayTypist() called Displays Eid, Ename, Salary, speed, and calculated salary

In the real world:

  • eSewa uses classes like User, Transaction, and Wallet to model users, payments, and balances. The Transaction class encapsulates amount and timestamp as private data, while public methods like processPayment() handle the logic.
  • Daraz employs an Order class to manage each customer’s items, status, and total. The OrderQueue system uses objects to process orders in a FIFO manner, similar to a real-world queue.
  • Pathao models rides using a Ride class with private driverId and fare, while public methods like bookRide() interact with the system. The destructor ensures resources (e.g., ride allocations) are freed when rides end.

In the real world

  • eSewa Transactions: Uses encapsulation to bundle user data (e.g., userID, balance) and methods (e.g., transferFunds(), checkBalance()) into a UserAccount class. The private access specifier ensures sensitive data like balance cannot be modified directly, only through controlled methods like deposit() or withdraw().
  • Daraz Order Processing: Models orders as Order objects with attributes like orderID, customer, items, and methods like placeOrder(), cancelOrder(), and updateStatus(). The system uses constructors to initialize orders with default values (e.g., status = "pending") and destructors to clean up temporary resources like session data after checkout.
  • Nepali Bank Loans: Banks use objects as function arguments to pass LoanApplication objects to functions like processApplication() or validateCreditScore(). This modular approach allows reuse of validation logic across different loan types.

Based on the TU BIT syllabus for Object Oriented Programming (BIT153), unit 2.

Discussion

Loading…