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
Carclass defines attributes likemodel,color, and methods likestart(),stop(). An object likemyCaris a specific instance withmodel = "Toyota"andcolor = "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.
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.
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()
- Private:
- Objects: Each transaction is an instance of
Transactionwith uniqueamountanduserId.
8.2 Daraz: Order Processing
- Class:
Order- Private:
orderId,items,status - Public:
addItem(),updateStatus(),calculateTotal()
- Private:
- Objects: Each customer order is an instance of
Orderwith its ownitemsandstatus.
8.3 Pathao: Ride Booking
- Class:
Ride- Private:
driverId,passengerId,fare,route - Public:
bookRide(),cancelRide(),calculateFare()
- Private:
- Objects: Each ride request is an instance of
Ridewith dynamicfareandroute.
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
- Understand Encapsulation: Always explain how
privateandpublicaccess specifiers restrict or allow access to data members. - Constructors and Destructors: Know when and how they are called. Draw memory diagrams for object creation.
- Friend Functions: Highlight why they are used (e.g., for arithmetic operations) and how they break encapsulation selectively.
- Objects as Arguments: Practice passing objects by value vs. reference and explain the trade-offs.
- Real-World Mapping: Relate classes to real systems like eSewa, Daraz, or Pathao to show practical applications.
- 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 valuevs.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, andWalletto model users, payments, and balances. TheTransactionclass encapsulatesamountandtimestampas private data, while public methods likeprocessPayment()handle the logic. - Daraz employs an
Orderclass to manage each customer’s items, status, and total. TheOrderQueuesystem uses objects to process orders in a FIFO manner, similar to a real-world queue. - Pathao models rides using a
Rideclass with privatedriverIdandfare, while public methods likebookRide()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 aUserAccountclass. Theprivateaccess specifier ensures sensitive data likebalancecannot be modified directly, only through controlled methods likedeposit()orwithdraw(). - Daraz Order Processing: Models orders as
Orderobjects with attributes likeorderID,customer,items, and methods likeplaceOrder(),cancelOrder(), andupdateStatus(). 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
LoanApplicationobjects to functions likeprocessApplication()orvalidateCreditScore(). 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…