Elective Object Oriented Programming in C++

Object Oriented Programming in C++Unit 38 min read

Constructors & Destructors: Types, Initialization & Cleanup

Unit 3 of Object Oriented Programming in C++ covers constructors (default, parameterized, copy), destructors, initialization lists, and their roles in object lifecycle management, with real-world examples from banking, e-commerce, and system design.

TAKEAWAYS:

  • Constructors initialize objects automatically when created, while destructors clean up resources automatically when objects are destroyed.
  • Default constructors have no parameters, parameterized constructors customize object states, and copy constructors duplicate objects.
  • Destructors release dynamically allocated memory and close files/resources to prevent leaks.
  • Initialization lists (: member(var)) are faster than assignment in constructors.
  • Constructors cannot return values or be inherited, but destructors must be virtual in polymorphic hierarchies.

Core Concepts: Constructors and Destructors

1. What is a Constructor?

A constructor is a special member function of a class that:

  • Has the same name as the class.
  • No return type (not even void).
  • Called automatically when an object is created.
  • Used to initialize object attributes.

Types of Constructors

classDiagram
    class Constructor {
        + Default Constructor
        + Parameterized Constructor
        + Copy Constructor
    }
    class DefaultConstructor {
        + No parameters
        + Initializes with default values
    }
    class ParameterizedConstructor {
        + Takes arguments
        + Customizes object state
    }
    class CopyConstructor {
        + Takes an object of same class
        + Creates a copy
    }
    Constructor --> DefaultConstructor
    Constructor --> ParameterizedConstructor
    Constructor --> CopyConstructor

Example: Bank Account Initialization

#include <iostream>
using namespace std;

class BankAccount {
private:
    string accountHolder;
    double balance;
public:
    // Default Constructor
    BankAccount() {
        accountHolder = "Unnamed";
        balance = 0.0;
    }

    // Parameterized Constructor
    BankAccount(string name, double initialBalance) {
        accountHolder = name;
        balance = initialBalance;
    }

    // Copy Constructor
    BankAccount(const BankAccount &other) {
        accountHolder = other.accountHolder;
        balance = other.balance;
    }

    void display() {
        cout << "Holder: " << accountHolder << ", Balance: $" << balance << endl;
    }
};

Trace: Object Creation

Step Code Execution State After Execution
1 BankAccount acc1; acc1.accountHolder = "Unnamed", balance = 0
2 BankAccount acc2("Ramesh", 5000); acc2.accountHolder = "Ramesh", balance = 5000
3 BankAccount acc3 = acc2; acc3.accountHolder = "Ramesh", balance = 5000 (copy)

In the Real World

  1. eSewa (Nepal’s Digital Payment System)

    • Uses constructors to initialize user accounts with default settings (e.g., zero balance, inactive status).
    • Copy constructors help duplicate transaction records for auditing.
  2. Khalti (Mobile Wallet)

    • Parameterized constructors set up merchant accounts with predefined commission rates and currency types.
    • Destructors ensure temporary session tokens are invalidated after use.
  3. NTC (Nepal Telecom) Billing System

    • Initialization lists efficiently set up customer records with prepaid/postpaid plans, avoiding slow assignments.
    • Destructors release network resources when a call session ends.

2. Constructor Initialization Lists

  • Faster than assignments inside the constructor body.
  • Syntax: : member(var) after the constructor declaration.
  • Mandatory for const and reference members.

Example: Efficient Initialization

class Student {
private:
    const int id;
    int &marks; // Reference member
public:
    Student(int i, int &m) : id(i), marks(m) {} // Initialization list
};

Trace: Initialization vs. Assignment

Method Code Example Performance Use Case
Initialization Student s(101, marksRef) : id(101), marks(marksRef) Faster const, references, objects
Assignment Student s(101, marksRef); s.id = 101; Slower Non-const members

3. Destructors: Cleaning Up Resources

  • Called automatically when an object goes out of scope or is deleted.
  • No parameters, no return type.
  • Used to free memory, close files, or release locks.
  • Virtual in base classes for polymorphic destruction.

Example: Dynamic Memory Release

class DynamicArray {
private:
    int *arr;
    int size;
public:
    DynamicArray(int s) { arr = new int[s]; size = s; }
    ~DynamicArray() { delete[] arr; } // Frees memory
};

Trace: Destructor Execution

sequenceDiagram
    participant Main
    participant obj
    Main->>obj: DynamicArray arr(100);
    Main->>obj: arr goes out of scope
    obj->>obj: ~DynamicArray() called
    obj->>System: delete[] arr

4. Copy Constructor: Deep vs. Shallow Copy

Feature Shallow Copy Deep Copy
Definition Copies pointer addresses Copies actual data pointed to
Risk Dangling pointers if original is destroyed Safe
Syntax Default copy constructor Manual implementation with new
Example Student s2 = s1; (default) Custom copy constructor with new

Example: Deep Copy in Linked List

class Node {
public:
    int data;
    Node *next;
    Node(int val) : data(val), next(nullptr) {}
    Node(const Node &other) { // Deep Copy Constructor
        data = other.data;
        next = new Node(*other.next); // Recursive deep copy
    }
    ~Node() { delete next; }
};
head102030NULL
Original linked list (shallow copy shares nodes)

Trace: Shallow vs. Deep Copy

Original List: A -> B -> C
Shallow Copy: A' -> B' -> C' (points to same memory as original!)
After delete original: A' -> B' -> C' (now dangling!)
Deep Copy: A'' -> B'' -> C'' (independent memory)

5. Constructor Overloading and Default Arguments

  • Multiple constructors with different parameters.
  • Default arguments allow flexible calls.

Example: Rectangle Area Calculator

class Rectangle {
private:
    double length, width;
public:
    Rectangle() : length(1.0), width(1.0) {} // Default
    Rectangle(double l) : length(l), width(l) {} // Square
    Rectangle(double l, double w) : length(l), width(w) {} // Rectangle
    double area() { return length * width; }
};

Trace: Constructor Calls

Call Behavior
Rectangle r1; length=1.0, width=1.0
Rectangle r2(5.0); Square: length=5.0, width=5.0
Rectangle r3(4, 6); Rectangle: length=4, width=6

6. Constructor and Destructor in Inheritance

  • Derived class constructors call base class constructors (implicitly or explicitly).
  • Destructors execute in reverse order (derived → base).

Example: Vehicle Hierarchy

class Vehicle {
public:
    Vehicle() { cout << "Vehicle Constructor" << endl; }
    ~Vehicle() { cout << "Vehicle Destructor" << endl; }
};

class Car : public Vehicle {
public:
    Car() { cout << "Car Constructor" << endl; }
    ~Car() { cout << "Car Destructor" << endl; }
};

Trace: Execution Order

Car obj;

Output:

Vehicle Constructor
Car Constructor

When obj is destroyed:

Car Destructor
Vehicle Destructor

Exam Tip

  1. Always explain the purpose of constructors/destructors (initialization vs. cleanup).
  2. Draw state diagrams for object creation/destruction (show memory allocation).
  3. Compare shallow vs. deep copy in exams—always prefer deep copy for dynamic memory.
  4. Mention initialization lists for const/reference members (high-weight point).
  5. For inheritance questions, state the order of constructor/destructor calls.
  6. Code traces are worth marks—show step-by-step variable changes.

Practice Question: Write a program for a BankAccount class with:

  • A parameterized constructor to set account number and balance.
  • A copy constructor that performs a deep copy of transaction history (use vector<string>).
  • A destructor to print "Account closed: [account number]". Trace the execution when:
  1. An object is created.
  2. A copy is made.
  3. The original is destroyed.

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

Discussion

Loading…