Elective Object Oriented Programming in C++

Object Oriented Programming in C++Unit 221 min read

Classes & Objects: Structure, Encapsulation, Data Hiding & Member Functions

Unit 2 of Object Oriented Programming in C++ covers the core concepts of classes (blueprints) and objects (instances), including data members, member functions, constructors, access specifiers (public/private/protected), and the principles of encapsulation and data hiding with practical examples and comparisons to proc

TAKEAWAYS:

  • Classes are blueprints for objects, combining data (attributes) and functions (methods) into a single unit.
  • Encapsulation bundles data and methods that operate on that data while data hiding restricts access to sensitive data using access specifiers.
  • Member functions can be inline (defined inside the class) or out-of-class (defined outside but declared inside).
  • Objects are instances of classes, created using the new keyword or stack allocation, and accessed via the dot (.) operator.
  • Default member functions (constructors, destructors, copy constructor, assignment operator) are automatically generated if not defined by the programmer.
  • Classes enable modularity, reusability, and maintainability in large-scale software projects.

1. Introduction to Classes and Objects

1.1 Definitions

  • Class: A user-defined data type that acts as a blueprint for creating objects. It encapsulates data (attributes) and functions (methods) that operate on the data.
  • Object: An instance of a class. It occupies memory and holds actual values.

1.2 Why Classes and Objects?

Object-Oriented Programming (OOP) improves upon Procedural-Oriented Programming (POP) by:

Feature POP OOP
Organization Functions and data are separate Data and functions are bundled
Modularity Low (functions operate on global data) High (data and functions are encapsulated)
Reusability Limited (functions must be rewritten) High (classes can be reused)
Maintainability Difficult (global data changes affect many functions) Easy (changes are localized to classes)
Data Hiding Not supported Supported (private/protected members)
Polymorphism Not supported Supported (functions can have multiple forms)

1.3 Real-World Analogy

Think of a class as a blueprint of a car (e.g., Toyota Corolla):

  • Data members: Color, model, mileage (attributes of the car).
  • Member functions: start(), accelerate(), brake() (actions the car can perform).
  • Object: An actual car (e.g., myCar) built from the blueprint with specific values (e.g., red, 2023 model, 10,000 miles).

2. Defining a Class in C++

A class is defined using the class keyword followed by the class name and body enclosed in curly braces {}.

2.1 Syntax

class ClassName {
    // Access specifiers
    private:
        // Private data members (hidden from outside)
    public:
        // Public data members and member functions (accessible from outside)
    protected:
        // Protected data members (accessible within the class and derived classes)
};

**2.2 Example: Person Class

class Person {
    private:          // Data hiding: accessible only within the class
        string name;
        int age;

    public:           // Accessible from outside the class
        void setName(string n) {
            name = n;
        }
        void setAge(int a) {
            age = a;
        }
        string getName() {
            return name;
        }
        int getAge() {
            return age;
        }
};

2.3 Creating Objects

Objects are created using the class name followed by the object name.

Person p1;          // Object created on the stack
Person *p2 = new Person();  // Object created on the heap

2.4 Accessing Members

Members are accessed using the dot (.) operator for stack objects and the arrow (->) operator for heap objects.

p1.setName("Ram");
p1.setAge(20);
cout << "Name: " << p1.getName() << ", Age: " << p1.getAge();

p2->setName("Hari");
p2->setAge(25);
cout << "Name: " << p2->getName() << ", Age: " << p2->getAge();

3. Data Members and Member Functions

headCS101Sita85.5NULL
State of Student object after setting roll, name, and marks (Step 4 in execution trace)

3.1 Data Members

  • Variables declared inside a class.
  • Can be of any data type (int, float, string, arrays, pointers, etc.).
  • Can be private, public, or protected.

3.2 Member Functions

  • Functions defined inside a class.
  • Can be inline (defined inside the class) or out-of-class (declared inside but defined outside).
  • Can access all members of the class, including private members.

**3.3 Example: Student Class with Inline and Out-of-Class Functions

class Student {
    private:
        string roll;
        string name;
        float marks;

    public:
        // Inline function
        void setRoll(string r) {
            roll = r;
        }

        // Declaration of out-of-class function
        void setName(string n);
        void setMarks(float m);
        string getDetails();
};

// Definition of out-of-class functions
void Student::setName(string n) {
    name = n;
}

void Student::setMarks(float m) {
    marks = m;
}

string Student::getDetails() {
    return "Roll: " + roll + ", Name: " + name + ", Marks: " + to_string(marks);
}

3.4 Tracing the Execution

Step Action State After Step
1 Student s1; s1 is created on the stack.
2 s1.setRoll("CS101"); s1.roll = "CS101"
3 s1.setName("Sita"); s1.name = "Sita"
4 s1.setMarks(85.5); s1.marks = 85.5
5 cout << s1.getDetails(); Output: Roll: CS101, Name: Sita, Marks: 85.5

4. Access Specifiers

Access specifiers define how members of a class can be accessed.

classDiagram
  class BankAccount {
    -accountNumber: string
    -balance: float
    -accountHolderName: string
    +deposit(float amount)
    +withdraw(float amount)
    +getBalance()
  }
  BankAccount : private
  BankAccount : protected
  BankAccount : public
Access specifiers in the BankAccount class hierarchy

4.1 private

  • Members are accessible only within the class.
  • Used for data hiding (protecting sensitive data).

4.2 public

  • Members are accessible from anywhere (outside the class).
  • Used for interfaces (functions that interact with objects).

4.3 protected

  • Members are accessible within the class and derived classes (inheritance).
  • Used in inheritance to allow controlled access.

**4.4 Example: Access Specifiers in BankAccount

class BankAccount {
    private:
        string accountNumber;
        float balance;

    protected:
        string accountHolderName;

    public:
        void deposit(float amount) {
            balance += amount;
        }
        void withdraw(float amount) {
            if (amount <= balance) {
                balance -= amount;
            }
        }
        float getBalance() {
            return balance;
        }
};

4.5 Real-World Example: Ncell Prepaid Plan

  • Private Data: User’s balance and transaction history (hidden from other apps).
  • Public Functions: recharge(), checkBalance(), makeCall() (accessible via Ncell app).
  • Protected Data: Plan details (accessible only within Ncell’s system for upgrades).

5. Default Member Functions

C++ provides default member functions if not explicitly defined by the programmer.

5.1 Default Constructor

  • Called when an object is created.
  • If not defined, C++ provides a default constructor that initializes members to default values.

5.2 Default Copy Constructor

  • Copies data from one object to another.
  • If not defined, C++ provides a member-wise copy.

5.3 Default Assignment Operator

  • Assigns values from one object to another.
  • If not defined, C++ provides a member-wise assignment.

5.4 Default Destructor

  • Called when an object is destroyed.
  • If not defined, C++ provides a default destructor that cleans up resources.

**5.5 Example: Employee Class with Default Functions

class Employee {
    private:
        string id;
        string name;

    public:
        // Default constructor
        Employee() {
            id = "000";
            name = "Unknown";
        }

        // Parameterized constructor
        Employee(string empId, string empName) {
            id = empId;
            name = empName;
        }

        // Copy constructor (default provided by C++)
        Employee(const Employee &other) {
            id = other.id;
            name = other.name;
        }

        void display() {
            cout << "ID: " << id << ", Name: " << name << endl;
        }
};

int main() {
    Employee e1;                  // Calls default constructor
    Employee e2("E101", "Ramesh"); // Calls parameterized constructor
    Employee e3 = e2;             // Calls copy constructor
    e1.display();                 // Output: ID: 000, Name: Unknown
    e2.display();                 // Output: ID: E101, Name: Ramesh
    e3.display();                 // Output: ID: E101, Name: Ramesh
    return 0;
}

**5.6 Tracing the Execution

Step Action State After Step
1 Employee e1; e1.id = "000", e1.name = "Unknown" (default constructor)
2 Employee e2("E101", "Ramesh"); e2.id = "E101", e2.name = "Ramesh" (parameterized constructor)
3 Employee e3 = e2; e3.id = "E101", e3.name = "Ramesh" (copy constructor)

6. Encapsulation and Data Hiding

0[object Object]1—2[object Object]3—
Encapsulated student records stored in a hash table (h(k) = roll % 4)

6.1 Encapsulation

  • Bundling of data and methods that operate on the data into a single unit (class).
  • Promotes modularity and reusability.

6.2 Data Hiding

  • Restricting access to certain members of a class using private or protected.
  • Prevents unintended interference and misuse of data.

**6.3 Example: Password Class with Data Hiding

class Password {
    private:
        string pass;

    public:
        void setPassword(string p) {
            if (p.length() >= 8) {
                pass = p;
            } else {
                cout << "Password too short!" << endl;
            }
        }

        void displayPassword() {
            cout << "Password: " << string(pass.length(), '*') << endl; // Hide actual password
        }
};

int main() {
    Password p;
    p.setPassword("secure123");
    p.displayPassword(); // Output: Password: ********
    return 0;
}

6.4 Real-World Example: eSewa Wallet

  • Encapsulation: The Wallet class bundles balance, transaction history, and functions like deposit(), withdraw(), and transfer().
  • Data Hiding: The actual PIN is stored as a private member and accessed only via verifyPIN() to prevent unauthorized access.

7. Objects as Arguments and Return Types

7.1 Passing Objects to Functions

Objects can be passed to functions by value or by reference.

7.1.1 Pass by Value
  • A copy of the object is passed.
  • Changes inside the function do not affect the original object.
void displayStudent(Student s) {
    cout << s.getDetails();
}

int main() {
    Student s1;
    s1.setRoll("CS101");
    s1.setName("Sita");
    displayStudent(s1); // Pass by value
    return 0;
}
7.1.2 Pass by Reference
  • The original object is passed.
  • Changes inside the function affect the original object.
void updateMarks(Student &s, float newMarks) {
    s.setMarks(newMarks);
}

int main() {
    Student s1;
    s1.setRoll("CS101");
    s1.setName("Sita");
    s1.setMarks(85.5);
    updateMarks(s1, 90.0); // Pass by reference
    cout << s1.getDetails(); // Output: Marks updated to 90.0
    return 0;
}

7.2 Returning Objects from Functions

Functions can return objects by value or by reference.

7.2.1 Return by Value
  • A copy of the object is returned.
Student createStudent(string roll, string name, float marks) {
    Student s;
    s.setRoll(roll);
    s.setName(name);
    s.setMarks(marks);
    return s;
}

int main() {
    Student s2 = createStudent("CS102", "Gita", 88.5);
    cout << s2.getDetails();
    return 0;
}
7.2.2 Return by Reference
  • The original object is returned (use with caution to avoid dangling references).
Student &getTopStudent(Student s1, Student s2) {
    return (s1.getMarks() > s2.getMarks()) ? s1 : s2;
}

int main() {
    Student s1, s2;
    s1.setMarks(85.5);
    s2.setMarks(90.0);
    Student &top = getTopStudent(s1, s2);
    cout << "Top student: " << top.getDetails();
    return 0;
}

8. Arrays of Objects

Objects can be stored in arrays like any other data type.

**8.1 Example: Student Array

int main() {
    Student students[3]; // Array of 3 Student objects

    // Initialize objects
    students[0].setRoll("CS101");
    students[0].setName("Sita");
    students[0].setMarks(85.5);

    students[1].setRoll("CS102");
    students[1].setName("Gita");
    students[1].setMarks(90.0);

    students[2].setRoll("CS103");
    students[2].setName("Ramesh");
    students[2].setMarks(88.5);

    // Display all students
    for (int i = 0; i < 3; i++) {
        cout << students[i].getDetails() << endl;
    }

    return 0;
}

8.2 Real-World Example: Daraz Order Queue

  • Daraz stores orders as objects in an array or dynamic array.
  • Each Order object contains:
    • orderId, customerId, items, status.
  • Functions like processOrder(), cancelOrder(), and displayOrder() operate on these objects.

9. Pointers to Objects

Pointers can point to objects, enabling dynamic memory allocation.

**9.1 Example: Person Pointer

int main() {
    Person *p = new Person(); // Dynamic allocation
    p->setName("Ram");
    p->setAge(20);
    cout << "Name: " << p->getName() << ", Age: " << p->getAge();

    delete p; // Free memory
    return 0;
}

9.2 Real-World Example: NEPSE Stock Trading

  • Stock quotes are stored as objects dynamically allocated on the heap.
  • Functions like buyStock(), sellStock(), and updatePrice() use pointers to manipulate these objects efficiently.

10. Static Members

Static members belong to the class itself rather than individual objects.

10.1 Static Data Members

  • Shared by all objects of the class.
  • Declared with the static keyword.
  • Accessed using the class name or an object.
class Counter {
    public:
        static int count; // Static data member

        Counter() {
            count++;
        }
};

// Initialize static member
int Counter::count = 0;

int main() {
    Counter c1, c2, c3;
    cout << "Total objects: " << Counter::count << endl; // Output: 3
    return 0;
}

10.2 Static Member Functions

  • Can only access static members.
  • Called using the class name.
class MathUtils {
    public:
        static int add(int a, int b) {
            return a + b;
        }
};

int main() {
    cout << "Sum: " << MathUtils::add(5, 7) << endl; // Output: 12
    return 0;
}

10.3 Real-World Example: Khalti Transaction Counter

  • A static member totalTransactions tracks the total number of transactions across all users.
  • Updated every time a transaction occurs (e.g., pay(), transfer()).

In the Real World

  1. eSewa Wallet:

    • Uses classes to model User, Transaction, and Wallet.
    • Encapsulation: The Wallet class hides the balance and PIN while exposing deposit(), withdraw(), and transfer().
    • Data Hiding: The actual PIN is stored privately and verified via verifyPIN().
  2. Pathao Ride Booking:

    • Uses objects to represent Driver, Passenger, and Ride.
    • Arrays of Objects: Stores active rides in an array of Ride objects.
    • Pointers: Dynamically allocates Ride objects for new bookings.
  3. Ncell Prepaid Plan:

    • Uses classes to model User, Plan, and Call.
    • Static Members: A static variable totalUsers tracks the number of subscribers.
    • Member Functions: recharge(), makeCall(), and checkBalance() operate on User objects.

Exam Tip

  1. Understand the Difference Between Class and Object:

    • A class is a blueprint; an object is an instance.
    • Example: class Car vs. Car myCar;.
  2. Access Specifiers:

    • private: Accessible only within the class.
    • public: Accessible everywhere.
    • protected: Accessible within the class and derived classes.
    • Common Mistake: Forgetting to declare member functions as public leads to compilation errors.
  3. Default Member Functions:

    • If not defined, C++ provides default constructor, copy constructor, assignment operator, and destructor.
    • Example: Employee e1; calls the default constructor.
  4. Passing Objects to Functions:

    • Pass by value: Safe but inefficient for large objects.
    • Pass by reference: Efficient but risky (modifies original object).
    • Example:
      void update(Student &s) { s.setMarks(90); } // Pass by reference
      
  5. Arrays of Objects:

    • Objects can be stored in arrays like Student students[100];.
    • Example: Storing 100 Student records in an exam system.
  6. Pointers to Objects:

    • Use new for dynamic allocation: Person *p = new Person();.
    • Always free memory with delete to avoid leaks.
  7. Static Members:

    • Belong to the class, not objects.
    • Must be initialized outside the class: int Counter::count = 0;.
    • Accessed via class name: Counter::count.
  8. Common Exam Questions:

    • Define a class with private data members and public member functions.
    • Explain encapsulation and data hiding with an example.
    • Write a program to create an array of objects and perform operations.
    • Differentiate between pass by value and pass by reference.

Practice Questions

  1. Define a class Book with private members title, author, and price. Include public member functions to set and get these values. Create an object and display its details.
  2. Write a program to create an array of 5 Student objects and sort them based on their marks.
  3. Explain the concept of data hiding with an example. How does it improve security in OOP?
  4. What is the difference between pass by value and pass by reference? Provide a C++ example for each.
  5. Define a class BankAccount with private members accountNumber and balance. Include public functions deposit(), withdraw(), and displayBalance(). Use a static member to track the total number of accounts.

Summary Table: Key Concepts

Concept Description Example
Class Blueprint for objects class Car { ... };
Object Instance of a class Car myCar;
Encapsulation Bundling data and methods private data + public methods
Data Hiding Restricting access to data private members
Access Specifiers private, public, protected public: void display();
Default Constructor Called when object is created Employee e1;
Copy Constructor Copies one object to another Employee e2 = e1;
Pass by Reference Modifies original object void update(Student &s)
Static Members Shared by all objects static int count;
Pointers to Objects Dynamic allocation of objects Person *p = new Person();

classDiagram
    class Person {
        -string name
        -int age
        +void setName(string n)
        +void setAge(int a)
        +string getName()
        +int getAge()
    }

    class Employee {
        -string employee_id
        +void setEmployeeId(string id)
        +string getEmployeeId()
    }

    class Manager {
        -string department
        +void setDepartment(string dept)
        +string getDepartment()
    }

    Person <|-- Employee
    Employee <|-- Manager

flowchart TD
    A["Start"] --> B["Define Class with Data Members and Member Functions"]
    B --> C["Declare Objects"]
    C --> D["Access Members Using Dot (.) or Arrow (->) Operator"]
    D --> E["Use Objects in Functions or Arrays"]
    E --> F["Free Dynamically Allocated Objects"]
    F --> G["End"]

In the real world

  • eSewa: Uses encapsulation to bundle user account data (balance, transaction history) and methods (transfer, recharge) into a secure UserAccount class. The private balance member hides sensitive financial data from direct access.
  • Pathao Driver App: Implements data hiding by restricting access to driver location (private currentLocation) while exposing public methods like updateLocation() and acceptRide().
  • Nepali Banks (e.g., NMB): Leverages default member functions (constructors/destructors) in Account classes to automatically initialize balances and log transactions when accounts are created/destroyed.

Based on the PU BE Computer (PU) syllabus for Object Oriented Programming in C++, unit 2.

Discussion

Loading…