Constructors, destructors and operator overloading — Unit 2 Notes (Object Oriented Programming with C++)

BCS201 · Unit 2

Constructors, destructors and operator overloading notes — Unit 2

Free unit-wise study notes on constructors, destructors and operator overloading for Object Oriented Programming with C++, Semester 2 of B.Tech — Computer Science & Engineering — key concepts, examples, important questions and a revision checklist for semester exams.

An exhaustive exploration of Object Lifecycle Management and Semantic Extensions. Covers Constructors, Destructors, Copy Semantics, and Operator Overloading to build intuitive, powerful C++ classes.

Notebook — 14 pages

Page 1

Wink Notes

B.Tech CSE — 2nd Semester

Object Oriented Programming with C++

Unit - 2

1. The Object Lifecycle

Just like any physical entity, every object in C++ goes through a definitive lifecycle: Creation, Usage, and Destruction. To manage this lifecycle securely, C++ provides special member functions.

Why do we need special functions?

When you create an integer `int x;`, it contains garbage value. When you create an object `BankAccount acc;`, it also contains garbage. If `balance` is a garbage value, any deposit or withdrawal is invalid. We need a guaranteed mechanism to initialize objects the moment they are created.

Memory Allocation

OS allocates physical RAM for the object's variables.

Initialization (Constructor)

Special function executes automatically to set valid initial states.

Usage

Application calls methods to interact with the object.

Cleanup (Destructor)

Special function executes to release resources before memory is reclaimed.

Deallocation

OS reclaims the physical RAM.

Next — Page 2 — Introduction to Constructors

1 of 14

Page 2

Wink Notes

B.Tech CSE — 2nd Semester

Object Oriented Programming with C++

Unit - 2

2. Introduction to Constructors

A Constructor is a special member function whose task is to initialize the objects of its class. It is special because its name is the EXACT same as the class name.

Strict Rules for Constructors

  • Name Matching: Must have the exact same name as the class itself.
  • No Return Type: Not even `void`. A constructor returns nothing because its job is strictly memory initialization.
  • Automatic Execution: It is invoked automatically when the object is created. You do not call it explicitly.
  • Public Access: They should generally be declared in the `public` section. If private, objects cannot be created from outside the class.
Basic Constructor Implementation
class Server {
    int port;
    string ip;
public:
    // Constructor
    Server() {
        port = 8080;
        ip = "127.0.0.1";
        cout << "Server object initialized!";
    }
};

int main() {
    Server s1; // "Server object initialized!" is printed instantly
}

Next — Page 3 — Types of Constructors

2 of 14

Page 3

Wink Notes

B.Tech CSE — 2nd Semester

Object Oriented Programming with C++

Unit - 2

3. Default Constructor

C++ allows multiple constructors in a single class through Function Overloading. This gives flexibility in how an object can be initialized.

1. The Default Constructor

A constructor that accepts no parameters. If you do not write ANY constructor, the C++ compiler automatically generates a hidden, empty default constructor for you. But if you write ANY constructor with parameters, the compiler STOPS generating the default one.

class Point {
    int x, y;
public:
    // Default Constructor
    Point() {
        x = 0; 
        y = 0;
    }
};

int main() {
    Point p; // Invokes default constructor
    // Point p(); // WARNING: This is a function declaration, not an object!
}

Next — Page 4 — Parameterized Constructors

3 of 14

Page 4

Wink Notes

B.Tech CSE — 2nd Semester

Object Oriented Programming with C++

Unit - 2

4. Parameterized Constructors

2. The Parameterized Constructor

A constructor that takes arguments. It allows you to pass specific initial values when the object is created.

Passing arguments during creation
class Rectangle {
    int length, breadth;
public:
    // Parameterized Constructor
    Rectangle(int l, int b) {
        length = l;
        breadth = b;
    }
};

int main() {
    // Implicit Call
    Rectangle r1(10, 5);
    
    // Explicit Call
    Rectangle r2 = Rectangle(10, 5);
}

Dynamic Initialization

Parameterized constructors are powerful because they allow 'Dynamic Initialization'. You can prompt the user for input at runtime, and only THEN create the object using those specific inputs.

Next — Page 5 — Constructor Overloading & Default Arguments

4 of 14

Page 5

Wink Notes

B.Tech CSE — 2nd Semester

Object Oriented Programming with C++

Unit - 2

5. Constructor Overloading

Because constructors are just functions, they can be overloaded. A class can have a default constructor, multiple parameterized constructors, and a copy constructor, all coexisting.

class Complex {
    float real, imag;
public:
    Complex() { real = 0; imag = 0; } // Default
    Complex(float r) { real = r; imag = 0; } // One parameter
    Complex(float r, float i) { real = r; imag = i; } // Two params
};

int main() {
    Complex c1;         // Calls Default
    Complex c2(5.5);    // Calls One parameter
    Complex c3(2.0, 3.5); // Calls Two params
}

Constructors with Default Arguments

Instead of overloading multiple constructors, you can write a single constructor with default arguments to achieve the same result.

class Complex {
    float real, imag;
public:
    // Covers 0, 1, or 2 parameters!
    Complex(float r = 0, float i = 0) {
        real = r; imag = i;
    }
};

Next — Page 6 — The Initializer List

5 of 14

Page 6

Wink Notes

B.Tech CSE — 2nd Semester

Object Oriented Programming with C++

Unit - 2

6. The Initializer List

In C++, assigning values inside the constructor body is actually 'assignment', not 'initialization'. True initialization happens BEFORE the body executes. For peak performance, C++ offers the Initializer List.

Syntax of Initializer List
class Entity {
    int id;
    const string name;
public:
    // Initializer list comes after a colon
    Entity(int i, string n) : id(i), name(n) {
        // Body can be empty!
    }
};

When is the Initializer List MANDATORY?

  • Constant Data Members: `const` variables must be initialized at creation. They cannot be assigned inside the body.
  • Reference Members: References (`&`) must be bound to a variable immediately upon creation.
  • Base Class Constructors: To pass arguments to a parent class constructor, you MUST use the initializer list in the derived class.
  • Object Members without Default Constructors: If your class contains another object as a member, and that object lacks a default constructor, you must initialize it here.

Next — Page 7 — The Copy Constructor

6 of 14

Page 7

Wink Notes

B.Tech CSE — 2nd Semester

Object Oriented Programming with C++

Unit - 2

7. The Copy Constructor

3. The Copy Constructor

A copy constructor is used to declare and initialize an object from another existing object of the SAME class. It essentially clones the object.

Syntax of Copy Constructor
class Document {
    int id;
public:
    Document(int i) : id(i) {} // Parameterized
    
    // Copy Constructor (MUST pass by const reference)
    Document(const Document &source) {
        id = source.id;
        cout << "Copy created!";
    }
};

int main() {
    Document doc1(101);
    Document doc2 = doc1; // Invokes Copy Constructor
    Document doc3(doc1);  // Invokes Copy Constructor
}

Next — Page 8 — Shallow vs Deep Copy

7 of 14

Page 8

Wink Notes

B.Tech CSE — 2nd Semester

Object Oriented Programming with C++

Unit - 2

8. Shallow vs Deep Copy

If you don't write a copy constructor, C++ provides a default one. This default copy constructor performs a Shallow Copy (a literal bit-by-bit copy of the variables).

The Danger of Shallow Copies

If your class contains pointers to dynamically allocated memory on the heap, a shallow copy is disastrous. Both the original and the copied object will have pointers pointing to the EXACT SAME memory address.

Object A [ ptr ] ---> [ Heap Memory Block ]
Object B [ ptr ] -------^ (Points to same block!)
Shallow Copy Crash Scenario

If Object A is destroyed, it frees the heap memory. Object B's pointer now points to freed memory (a dangling pointer). If Object B tries to free it again, the program crashes (Double Free Error).

The Deep Copy Solution

To fix this, you MUST write your own custom Copy Constructor to perform a Deep Copy. You allocate brand new heap memory for the clone, and then copy the data over.

String(const String &source) {
    int len = strlen(source.str);
    str = new char[len + 1]; // Allocate NEW memory
    strcpy(str, source.str); // Copy data
}

Next — Page 9 — Destructors

8 of 14

Page 9

Wink Notes

B.Tech CSE — 2nd Semester

Object Oriented Programming with C++

Unit - 2

9. Destructors

Just as constructors prepare an object for use, Destructors clean up an object before its memory is destroyed.

Rules for Destructors

  • Name Matching: It has the exact same name as the class, prefixed by a tilde `~`.
  • No Parameters & No Return Type: It takes no arguments and returns nothing.
  • Cannot be Overloaded: Because it takes no arguments, there can be ONLY ONE destructor per class.
  • Automatic Execution: It is automatically called when the object goes out of scope (e.g., function ends, or `delete` is called on a pointer).
Destructor Implementation
class NetworkSocket {
    int socketId;
public:
    NetworkSocket() {
        cout << "Opening connection...";
    }
    ~NetworkSocket() {
        cout << "Closing connection cleanly...";
    }
};

Destructors are critical for Resource Acquisition Is Initialization (RAII). Whenever an object acquires a resource (memory, file handle, network port, database lock), the destructor MUST release it to prevent resource leaks.

Next — Page 10 — Operator Overloading Basics

9 of 14

Page 10

Wink Notes

B.Tech CSE — 2nd Semester

Object Oriented Programming with C++

Unit - 2

10. Operator Overloading Basics

Operator Overloading is one of C++'s most powerful features. It allows you to redefine how standard operators (`+`, `-`, `*`, `==`) work when applied to user-defined objects.

The Goal of Overloading

To make custom classes behave like built-in types. Instead of writing `c3 = c1.add(c2);` for complex numbers, we want to write `c3 = c1 + c2;`.

Syntax of Operator Overloading

We use the special `operator` keyword followed by the symbol we want to overload.

Return_Type operator SYMBOL (Parameters) { ... }
class Complex {
    float real, imag;
public:
    Complex(float r, float i) : real(r), imag(i) {}
    
    // Overloading the + operator
    Complex operator+(const Complex &other) {
        return Complex(real + other.real, imag + other.imag);
    }
};

int main() {
    Complex c1(1, 2), c2(3, 4);
    Complex c3 = c1 + c2; // Calls c1.operator+(c2)
}

Next — Page 11 — Overloading Unary Operators

10 of 14

Page 11

Wink Notes

B.Tech CSE — 2nd Semester

Object Oriented Programming with C++

Unit - 2

11. Overloading Unary Operators

Unary operators operate on a single operand (e.g., `-x`, `++x`, `!x`). When overloaded as a member function, they take NO arguments, because the calling object itself is the operand.

Overloading the Unary Minus (-)
class Vector3D {
    int x, y, z;
public:
    Vector3D(int a, int b, int c) : x(a), y(b), z(c) {}
    
    // Unary minus reverses the vector
    void operator-() {
        x = -x;
        y = -y;
        z = -z;
    }
};

int main() {
    Vector3D v(10, -5, 3);
    -v; // Invokes v.operator-()
}

Prefix vs Postfix Increment (++)

To distinguish between `++obj` (prefix) and `obj++` (postfix), C++ introduces a dummy `int` parameter for the postfix version.

void operator++() { ... }    // Prefix (++obj)
void operator++(int) { ... } // Postfix (obj++)

Next — Page 12 — Overloading Binary Operators

11 of 14

Page 12

Wink Notes

B.Tech CSE — 2nd Semester

Object Oriented Programming with C++

Unit - 2

12. Overloading Binary Operators

Binary operators operate on two operands (e.g., `A + B`). When overloaded as a member function, they take EXACTLY ONE argument. The calling object is the left operand, and the argument is the right operand.

Expression: `A + B` ====> translates to ====> `A.operator+(B)`

Overloading the Equality (==) Operator
class String {
    char str[100];
public:
    bool operator==(const String &other) {
        if (strcmp(this->str, other.str) == 0)
            return true;
        return false;
    }
};

int main() {
    String s1("Hello"), s2("Hello");
    if(s1 == s2) cout << "Strings match!";
}

Next — Page 13 — Overloading using Friend Functions

12 of 14

Page 13

Wink Notes

B.Tech CSE — 2nd Semester

Object Oriented Programming with C++

Unit - 2

13. Overloading via Friends

There are situations where overloading via a member function is impossible. For instance, what if the left operand is NOT an object of your class?

The Integer Multiplication Problem

For a Vector class, `Vector v2 = v1 5;` translates to `v1.operator(5)`. This works perfectly as a member function. BUT what about `Vector v2 = 5 v1;`? This translates to `5.operator(v1)`, which is illegal because `5` is a primitive integer, not an object!

To fix this, we overload the operator using a Friend Function. A friend function takes BOTH operands as explicit arguments.

Using Friend Functions for Commutativity
class Vector {
    int val;
public:
    Vector(int v) : val(v) {}
    // Friend declaration takes two args
    friend Vector operator*(int scalar, const Vector &v);
};

// Definition outside
Vector operator*(int scalar, const Vector &v) {
    return Vector(scalar * v.val);
}

int main() {
    Vector v1(10);
    Vector v2 = 5 * v1; // Now this works perfectly!
}

Next — Page 14 — Unit 2 Revision Checklist

13 of 14

Page 14

Wink Notes

B.Tech CSE — 2nd Semester

Object Oriented Programming with C++

Unit - 2

14. Unit 2 Revision Checklist

End-of-Unit Verification

  • Explain the exact moment a constructor is called and list its 4 main rules.
  • Write the syntax for a parameterized constructor and explain dynamic initialization.
  • Identify the 'Vexing Parse' error when trying to create an object with a default constructor.
  • Explain why a Copy Constructor MUST take its argument by reference (`&`).
  • Draw the memory diagram showing the catastrophic difference between Shallow Copy and Deep Copy.
  • List the 4 scenarios where an Initializer List is absolutely mandatory.
  • Explain RAII and the role of Destructors in preventing memory leaks.
  • Write the syntax to overload the `++` operator in both Prefix and Postfix forms.
  • List the 5 operators in C++ that cannot be overloaded.
  • Explain why overloading the stream operators (`<<` and `>>`) MUST be done using Friend functions, not member functions.

14 of 14

Continue in this subject