Siksha Sarovar

Siksha Sarovar (sikshasarovar.com) is a free educational web application that helps students in India learn programming and prepare for academic and competitive exams. The platform offers structured coding courses (C, C++, Python, Java, HTML, CSS, PHP, Power BI, AI, Machine Learning, Data Science), complete university curriculum notes for BCA/MCA students with previous year question papers, Class 10 and Class 12 CBSE/HBSE school notes, and dedicated preparation material for SSC, UPSC, Banking, Railway and other government exams. Browsing the site is completely free and requires no account. Users may optionally sign in with Google solely to save their learning progress, quiz scores and personal preferences across devices.

Privacy Policy | Terms of Service | Contact Siksha Sarovar | About Siksha Sarovar

v4.0.9 · PWA
Siksha Sarovar logo
Siksha Sarovar
Your Learning Universe

Siksha Sarovar is a free e-learning platform for coding courses, BCA university notes and competitive exam preparation. Optional Google sign-in saves your learning progress across devices.

Initializing knowledge base…
Compiling modules 0%

2.3 Constructors — Default, Parameterized & Multiple

Lesson 10 of 22 in the free Object Oriented Programming with C++ notes on Siksha Sarovar, written by Rohit Jangra.

2.3 Constructors — Default, Parameterized & Multiple

What is a Constructor?

A constructor is a special member function that is automatically called when an object is created. It is used to initialise the object's data members.

Key properties

PropertyMeaning
NameSame as the class name
No return typeNot even void
Called automaticallyWhen object is created
Can be overloadedMultiple constructors possible
Can have default argumentsYes
Cannot be virtualYes (well, no — except in advanced patterns)
Cannot be inheritedDerived class must define its own
Implicitly inlineIf defined inside the class
Typically public(Private constructors enable singleton pattern)
class Student {
public:
    Student() {                           // constructor
        cout << "Student created" << endl;
    }
};

int main() {
    Student s;                            // automatically calls constructor
    return 0;
}
// Output: Student created

---

Types of Constructors (IPU classification)

The IPU syllabus lists these constructor types:

  1. Default constructor — no parameters
  2. Parameterized constructor — takes arguments
  3. Constructor with default arguments — combines both
  4. Multiple constructors (overloaded) — different signatures
  5. Copy constructor — initialises from existing object (next lesson)

---

1. Default Constructor

A default constructor takes no arguments. If you don't define one, the compiler generates a no-op default constructor automatically (unless you've defined any other constructor).

class Point {
public:
    int x, y;

    Point() {              // default constructor
        x = 0;
        y = 0;
    }

    void display() {
        cout << "(" << x << ", " << y << ")" << endl;
    }
};

int main() {
    Point p;               // calls default constructor
    p.display();           // (0, 0)
    return 0;
}

Modern initialisation styles

// Initializer list (preferred — more efficient)
class Point {
public:
    int x, y;

    Point() : x(0), y(0) {}    // member initialiser list
};

// In-class initialiser (C++11+)
class Point {
public:
    int x = 0;                 // direct initialisation
    int y = 0;

    Point() = default;          // explicitly request compiler-generated
};

When the compiler generates a default constructor

ScenarioCompiler generates?
No constructors definedYES — implicit default
Any constructor definedNO — you must define explicitly
With = defaultYES — explicitly requested
With = deleteNO — explicitly disabled

---

2. Parameterized Constructor

A parameterized constructor takes one or more arguments to initialise the object:

class Point {
public:
    int x, y;

    Point(int a, int b) {       // parameterized
        x = a;
        y = b;
    }
};

int main() {
    Point p1(5, 10);            // pass arguments at construction
    Point p2(3, 7);
    cout << p1.x << "," << p1.y;  // 5,10
    return 0;
}

Using member initialiser list (preferred)

class Point {
public:
    int x, y;

    Point(int a, int b) : x(a), y(b) {}   // initialiser list
};

Why initialiser list?

  • More efficient (direct initialisation, no default-then-assign)
  • Required for const, reference, and base-class members
  • Initialisation order follows declaration order (not list order)
class Bad {
    const int x;            // const must be in initialiser list
    int& y;                 // reference must be in initialiser list

public:
    Bad(int a, int& b) : x(a), y(b) {}    // OK
    // Bad(int a, int& b) { x = a; y = b; }   // ERROR
};

---

3. Constructor with Default Arguments

Combines parameterized + default — fewer overloads needed:

class Point {
public:
    int x, y;

    Point(int a = 0, int b = 0) : x(a), y(b) {}
};

int main() {
    Point p1;                  // (0, 0)
    Point p2(5);               // (5, 0)
    Point p3(5, 10);           // (5, 10)
    return 0;
}

This single constructor handles three cases. Equivalent without default arguments:

Point() : x(0), y(0) {}
Point(int a) : x(a), y(0) {}
Point(int a, int b) : x(a), y(b) {}

Important rule

If you have:

Point() : x(0), y(0) {}
Point(int a = 0, int b = 0) : x(a), y(b) {}   // also default-arg version

Calling Point p; is ambiguous — compiler error. Don't mix the two.

---

4. Multiple Constructors (Overloading)

A class can have multiple constructors with different parameter lists:

class Time {
private:
    int hours, minutes, seconds;

public:
    Time() : hours(0), minutes(0), seconds(0) {}                       // default
    Time(int h) : hours(h), minutes(0), seconds(0) {}                  // 1-arg
    Time(int h, int m) : hours(h), minutes(m), seconds(0) {}           // 2-arg
    Time(int h, int m, int s) : hours(h), minutes(m), seconds(s) {}    // 3-arg
    Time(int totalSeconds) {                                            // ambiguous!
        hours = totalSeconds / 3600;
        minutes = (totalSeconds % 3600) / 60;
        seconds = totalSeconds % 60;
    }
};

⚠ The last constructor with one int parameter is ambiguous with the 1-arg Time(int h) — both have signature Time(int). Won't compile.

Solving the ambiguity — use different types or explicit factory

class Time {
public:
    Time() : hours(0), minutes(0), seconds(0) {}
    Time(int h, int m, int s) : hours(h), minutes(m), seconds(s) {}

    static Time fromSeconds(int total) {       // named constructor pattern
        Time t;
        t.hours = total / 3600;
        t.minutes = (total % 3600) / 60;
        t.seconds = total % 60;
        return t;
    }
};

Time t = Time::fromSeconds(7325);   // intent clear

---

Constructor Initialisation Order

1. Member variables in declaration order (NOT list order)

class A {
    int x;
    int y;
public:
    A(int a, int b) : y(b), x(y + 1) {}   // x initialised FIRST (declaration order)
    // x uses y, but y not yet initialised — UB!
};
Rule: Write initialiser list in the same order as declarations to avoid surprises.

2. Base class first, then members

For inheritance (Unit III), the base class constructor runs before any member initialiser.

3. Static members initialised before main

Static members are initialised once at program start, before any constructor runs.

---

Constructor Initialiser List — When Required

Member typeWhy list is required
const memberCannot be assigned after construction
Reference memberCannot be reseated
Base classNo way to call base constructor in body
Member without default constructorNo way to construct in body
const ref memberSame reasons
class A {
    const int id;
    int& ref;
public:
    A(int i, int& r) : id(i), ref(r) {}   // MUST use list
};

---

Constructor in Heap Allocation

class Student {
public:
    Student(int id, string n) {
        cout << "Constructing " << id << endl;
    }
};

Student* s = new Student(101, "Rohit");   // constructor called
delete s;                                  // destructor called (next lesson)

---

Initialisation Styles — C++ Versions

Point p1;                  // default-initialise (uninitialised for built-in types)
Point p2();                // FUNCTION DECLARATION — common gotcha
Point p3{};                // uniform initialisation (C++11) — zero-init
Point p4(5, 10);           // direct initialisation
Point p5{5, 10};           // uniform initialisation (C++11)
Point p6 = {5, 10};        // copy-list initialisation
Point p7 = Point(5, 10);   // copy initialisation
Best practice: Use Point p{5, 10}; (uniform braces) in modern code — works for all cases, prevents narrowing.

---

Common Mistakes

1. Using parentheses for default constructor (gotcha)

Point p();   // declares a FUNCTION named p returning Point — NOT an object!
Point p;     // correct — calls default constructor
Point p{};   // also correct — uniform init

2. Forgetting to initialise members

class Bad {
    int x;           // uninitialised — garbage value
public:
    Bad() {}         // didn't initialise x
    int getX() { return x; }   // undefined behaviour
};

3. Assignment in body instead of initialiser list

class Slow {
    string name;
public:
    Slow(string n) { name = n; }   // works but creates empty string first, then assigns
    // Better: Slow(string n) : name(n) {}
};

---

A Complete Example — Date Class

class Date {
private:
    int day, month, year;

public:
    // Default constructor
    Date() : day(1), month(1), year(2000) {}

    // Parameterized
    Date(int d, int m, int y) : day(d), month(m), year(y) {}

    // With default arguments
    // (Would conflict with above — don't add a 4th)

    void display() const {
        cout << day << "/" << month << "/" << year << endl;
    }
};

int main() {
    Date d1;                  // 1/1/2000
    Date d2(15, 8, 1947);     // 15/8/1947

    d1.display();
    d2.display();
    return 0;
}

---

Study deep

  1. Initializer list is more than syntax — it's faster. Members declared in the list are constructed once with the given value. In the body, they're default-constructed then assigned. For int it doesn't matter; for string or vector it does.
  1. The Rule of Three / Five / Zero. If you define one of (destructor, copy constructor, copy assignment), you almost certainly need to define the other two. C++11 added move ctor + move assignment → Rule of Five. The Rule of Zero says: design so you don't need any of them.
  1. Delegating constructors (C++11). One constructor can call another:
Date(int d, int m, int y) : day(d), month(m), year(y) {}
Date() : Date(1, 1, 2000) {}   // delegate to 3-arg constructor
  1. Explicit constructors. A single-argument constructor doubles as a conversion. Use explicit to disable:
class Distance {
public:
    explicit Distance(int meters) { /* ... */ }
};

Distance d = 5;        // ERROR (good!) — would be silent conversion otherwise
Distance d(5);          // OK
  1. Constructors run on object creation; destructors run on destruction. Local objects: stack scope. Heap objects: delete. Static objects: before/after main. Global objects: before main in undefined order across translation units (static initialisation order fiasco).

Key Terms — Lesson 2.3

The terms below cover constructors — every PYQ on object creation, initialisation, or constructor types expects fluent use.

Constructor — A special member function with the same name as the class that is automatically called when an object is created. Its job is to initialise the object's data members and establish class invariants. Constructors have no return type (not even void), can be overloaded, and can have default arguments.

Default Constructor — A constructor that takes no arguments (or all arguments have defaults). Called when an object is created without explicit constructor arguments: Student s;. If a class has no user-defined constructor, the compiler synthesises a trivial default constructor; once any constructor is defined, the synthesis stops.

Parameterised Constructor — A constructor that takes one or more arguments to initialise the object's state with caller-supplied values. Student(int id, string name); is parameterised; called as Student s(101, "Rohit");.

Constructor with Default Arguments — A parameterised constructor where some or all parameters have default values, letting one constructor serve where multiple overloads might otherwise be needed. Student(int id = 0, string name = ""); covers Student s;, Student s(101);, and Student s(101, "Rohit"); in one declaration.

Multiple / Overloaded Constructors — A class can have multiple constructors with different parameter lists, just like function overloading. The compiler picks the right one based on the constructor call. Example: Date(), Date(int d, int m, int y), Date(string s).

Member Initialiser List — The syntax that initialises data members before the constructor body runs: Student(int i, string n) : id(i), name(n) {}. The list is required for const members, references, base classes, and members without a default constructor. It is more efficient than assigning in the body — members are constructed once with the right value rather than default-constructed then assigned.

Initialisation vs Assignment — Two different operations. Initialisation sets a member's first value during construction (via initialiser list). Assignment changes an existing value (via the assignment operator). For built-in types the difference is minor; for class-type members the difference can be a major performance gap.

Constructor Properties / Rules — (1) The constructor's name is identical to the class name. (2) It has no return type (not even void). (3) It is automatically invoked at object creation. (4) Constructors can be overloaded. (5) Constructors can have default arguments. (6) Constructors cannot be virtual (the object's type is not yet known). (7) Constructors cannot be inherited (but can be invoked from derived constructors).

Synthesised (Implicitly Generated) Constructor — A constructor the compiler generates automatically if you don't write one. Specifically: a default constructor is synthesised only if no other constructor is defined; copy constructor, move constructor, copy assignment, move assignment, and destructor are synthesised on demand unless suppressed by certain class features (covered in Lesson 2.4).

Constructor Delegation (C++11) — A constructor can call another constructor of the same class in its initialiser list: Date() : Date(1, 1, 2000) {}. Avoids duplicating initialisation code. Each chain must eventually reach a non-delegating constructor.

explicit Constructor — A constructor declared with explicit that prevents implicit conversions: explicit Distance(int meters); blocks Distance d = 5; (which would silently call the constructor). Use explicit for any single-argument constructor where implicit conversion isn't desired.

Conversion Constructor — A single-argument constructor that doubles as a type conversion from the argument type to the class type. Distance(int meters) (without explicit) lets Distance d = 5; compile by implicitly constructing a Distance from 5. Useful but error-prone; modern style is to mark conversion constructors explicit unless conversion is genuinely desired.

Order of Member Initialisation — Members are initialised in declaration order in the class, not in the order they appear in the initialiser list. This is the source of subtle bugs when one member depends on another: declare them in the right order. Compilers (with -Wreorder) warn when initialiser-list order differs from declaration order.

Constructor for Heap Objects — When new allocates an object, new calls the constructor automatically as part of allocation. new Student(101, "Rohit") allocates memory and constructs the Student in one step.

Constructor for Array of Objects — When an array of objects is declared (Student class[40];), the default constructor is called for each element. If the class has no accessible default constructor, the declaration fails to compile.

Constructor for Static Objects — Static and global objects' constructors run before main() (in undefined order across translation units — the famous static initialisation order fiasco). Their destructors run after main() in reverse construction order.

Static Initialisation Order Fiasco — A C++ pitfall: the order in which global/static objects in different translation units are constructed is undefined. If one depends on another, the result may be undefined behaviour. Workarounds: the construct-on-first-use idiom (return a local static from a function).

Inline Constructor — Constructors defined inside the class body are implicitly inline. Helps the compiler optimise small constructors away.

= default and = delete (C++11) — Modern tools for controlling synthesised special members. = default asks the compiler to generate the default version explicitly (Class() = default;). = delete suppresses a special member (Class(const Class&) = delete; — copy not allowed).

Brace Initialisation ({}) (C++11) — A uniform initialisation syntax: Student s{101, "Rohit"};. Works for class types, arrays, aggregates, and prohibits narrowing conversions (assigning a double to an int through {} is an error, where () would silently truncate).

---

PYQ pattern (very common): "What is a constructor? Explain different types of constructors with examples." — Define + 7 properties; list 5 types (default, parameterized, with default args, multiple/overloaded, copy); code example for each.
PYQ pattern: "Explain constructor with example and rules." — Define; rules (name = class, no return type, auto-called, can be overloaded, default-generated if none defined); code example with 2 overloaded constructors.
PYQ pattern: "What is constructor initialisation list? When is it required?" — Show syntax; explain efficiency benefit; list 4 cases where it's required (const, reference, base class, members without default ctor).