← Home
Emergency Edition

The Last-Nighter Salvation Guide

Multiple programs + expected outputs + theory + comparison tables + predicted Q&A β€” the complete package.

⚑ Critical Syntax at a Glance β€” Memorize These First
Class Skeleton
class Name {
private: ...
public: ...
}; // semicolon!
Constructor Types
Name() {} // default
Name(int x):x(x){} // param
Name(const Name&n) // copy
Destructor
~Name() {} // no args, no return
virtual ~Name() {} // base class
Operator Overload
Name operator+(const Name& o) {
return Name(x+o.x);
}
Inheritance
class D : public B {};
class D : virtual public B {};
Virtual Function
virtual void f() = 0; // pure
virtual void f(); // regular
void f() override; // derived
Function Template
template <typename T>
T func(T a, T b) { ... }
Class Template
template <typename T>
class Calc { T add(T a,T b); };
Calc<int> c;
Try-Catch
try { throw runtime_error("e"); }
catch(const exception& e) {}
catch(...) {} // LAST
Vector (STL)
vector<int> v;
v.push_back(x); sort(v.begin(),v.end());
v.erase(v.begin()+i);
Map (STL)
map<string,int> m;
m["key"] = val;
m.find("key") != m.end()
Dynamic Memory
int* p = new int(5);
int* arr = new int[n];
delete p; delete[] arr;
Type Casting
static_cast<int>(3.7)
dynamic_cast<D*>(basePtr)
const_cast<int*>(cptr)
File I/O
ifstream fin("f.txt");
ofstream fout("f.txt");
fin >> x; fout << x;
Default Args
void f(int a, int b=10);
// default must be LAST
f(5); // b=10 auto
Const Member Fn
void show() const {}
// cannot modify members
// call on const objects
Stringstream
#include <sstream>
stringstream ss;
ss << x; ss >> y;
1

OOAD & OOP Basics

πŸ“– Core Theory
4 Pillars of OOP

Encapsulation β€” data hiding via access specifiers.
Abstraction β€” show only essential details.
Inheritance β€” reuse base class properties.
Polymorphism β€” same interface, different behavior.

Class vs Object

A class is a blueprint/template.
An object is a real-world instance of that class.
Class does not occupy memory; objects do.

Access Specifiers

private β€” accessible only within the class (default for class).
protected β€” accessible in class + derived classes.
public β€” accessible everywhere (default for struct).

UML & History

UML = Unified Modeling Language (Booch, Rumbaugh, Jacobson).
Alan Kay coined "Object-Oriented Programming".
Simula 67 was the first OOP language.

πŸ”₯ Top MCQ Points
  • UML stands for Unified Modeling Language.
  • Alan Kay developed the concept of Object-Oriented Programming.
  • Encapsulation hides data using access specifiers.
  • Default access in class β†’ private; in struct β†’ public.
  • A class definition must end with }; (semicolon is mandatory).
  • Scope resolution operator is :: β€” used to define functions outside the class.
πŸ’» Program 1 β€” Bank Account with Array of Objects
Classic exam favorite: class + array of objects + deposit/withdraw logic
#include <iostream>
#include <string>
using namespace std;

class BankAccount {
private:
    string owner;
    double balance;

public:
    // Parameterized Constructor
    BankAccount(string name, double bal) : owner(name), balance(bal) {}

    void deposit(double amt) {
        if (amt > 0) balance += amt;
    }

    void withdraw(double amt) {
        if (amt <= balance) balance -= amt;
        else cout << "[ERROR] Insufficient funds for " << owner << endl;
    }

    void display() const {
        cout << "Account: " << owner
             << " | Balance: Rs." << balance << endl;
    }
}; // <-- SEMICOLON IS MANDATORY

int main() {
    BankAccount accounts[3] = {
        BankAccount("Alice", 5000),
        BankAccount("Bob",   3000),
        BankAccount("Carol", 7500)
    };

    accounts[0].deposit(1500);
    accounts[1].withdraw(500);
    accounts[2].withdraw(10000); // triggers error

    for (int i = 0; i < 3; i++)
        accounts[i].display();

    return 0;
}
πŸ–₯️ Expected Output
[ERROR] Insufficient funds for Carol Account: Alice | Balance: Rs.6500 Account: Bob | Balance: Rs.2500 Account: Carol | Balance: Rs.7500
πŸ’» Program 2 β€” Student Class with Scope Resolution Operator
Demonstrates defining member functions outside the class using ::
#include <iostream>
using namespace std;

class Student {
private:
    string name;
    int    rollNo;
    float  marks;

public:
    void setData(string n, int r, float m); // declaration only
    void display();
    char getGrade();
};

// Definition OUTSIDE the class β€” uses :: (scope resolution)
void Student::setData(string n, int r, float m) {
    name = n; rollNo = r; marks = m;
}

void Student::display() {
    cout << "Name: "  << name
         << " | Roll: " << rollNo
         << " | Marks: " << marks
         << " | Grade: " << getGrade() << endl;
}

char Student::getGrade() {
    if (marks >= 90) return 'A';
    if (marks >= 75) return 'B';
    if (marks >= 60) return 'C';
    return 'F';
}

int main() {
    Student s1, s2;
    s1.setData("Dharaksh", 101, 92.5);
    s2.setData("Riya",     102, 74.0);
    s1.display();
    s2.display();
    return 0;
}
πŸ–₯️ Expected Output
Name: Dharaksh | Roll: 101 | Marks: 92.5 | Grade: A Name: Riya | Roll: 102 | Marks: 74 | Grade: C
πŸ’» Program 3 β€” this Pointer + Static Members
Static members are shared across ALL objects β€” very commonly asked in theory + MCQs
#include <iostream>
using namespace std;

class Employee {
private:
    string name;
    int id;
    static int count; // shared by ALL objects β€” declared here

public:
    Employee(string n, int i) : name(n), id(i) {
        count++;        // increments for every new object
    }

    // 'this' pointer: points to the calling object
    Employee& setName(string n) {
        this->name = n;  // 'this->name' disambiguates from param 'n'
        return *this;    // enables method chaining
    }

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

    // Static function β€” can only access static members
    static void showCount() {
        cout << "Total Employees: " << count << endl;
    }
};

// Static member MUST be defined outside the class
int Employee::count = 0;

int main() {
    Employee e1("Alice", 1);
    Employee e2("Bob", 2);
    Employee e3("Carol", 3);

    e1.setName("Alicia"); // using this pointer internally
    e1.display();
    e2.display();

    Employee::showCount(); // called via class name, not object
    return 0;
}
πŸ–₯️ Expected Output
ID: 1 | Name: Alicia ID: 2 | Name: Bob Total Employees: 3
⚠️ Exam Traps
  • Forgetting }; after the class closing brace β€” causes a wall of confusing compile errors.
  • Forgetting ClassName:: when defining functions outside the class.
  • Accessing a private member directly from main() β€” only public methods can be called outside.
  • Static member must be defined outside the class: int ClassName::count = 0; β€” forgetting this causes a linker error.
  • Static member functions cannot use this pointer β€” they have no object context.
2

Constructors, Destructors & Operator Overloading

πŸ“– Core Theory
Types of Constructors

Default β€” no parameters; called automatically.
Parameterized β€” accepts arguments at creation.
Copy β€” ClassName(const ClassName &obj); copies another object.

Destructor Rules

Name = ~ClassName().
Takes no arguments, returns nothing.
Called automatically when object goes out of scope.
Only one destructor per class.

Non-Overloadable Operators

:: Scope Resolution
. Member Access
.* Pointer to Member
?: Ternary / Conditional
sizeof and typeid also cannot be overloaded.

Operator Overloading Rule

For +, -, * etc. the function must return a new object, not void.
Syntax: RetType operator+(const ClassName &)

πŸ”₯ Top MCQ Points
  • Operators ::, ., .*, ?: CANNOT be overloaded.
  • Destructor has no arguments, no return type, name = ~ClassName.
  • Copy constructor parameter must be a const reference to avoid infinite recursion.
  • Constructor is called at object creation; destructor at object destruction.
  • this pointer β€” points to the current object inside member functions.
πŸ’» Program 1 β€” All 3 Constructors + Destructor (Complex Number)
#include <iostream>
using namespace std;

class Complex {
private:
    float real, imag;

public:
    // 1. Default Constructor
    Complex() : real(0), imag(0) {
        cout << "Default constructor called\n";
    }

    // 2. Parameterized Constructor
    Complex(float r, float i) : real(r), imag(i) {
        cout << "Parameterized constructor called\n";
    }

    // 3. Copy Constructor
    Complex(const Complex &c) : real(c.real), imag(c.imag) {
        cout << "Copy constructor called\n";
    }

    // Destructor
    ~Complex() {
        cout << "Destructor called for ("
             << real << "+" << imag << "i)\n";
    }

    void display() const {
        cout << real << " + " << imag << "i\n";
    }
};

int main() {
    Complex c1;             // Default
    Complex c2(3.0, 4.0); // Parameterized
    Complex c3(c2);         // Copy

    cout << "c2: "; c2.display();
    cout << "c3: "; c3.display();
    return 0;
    // Destructors called in REVERSE order of creation: c3, c2, c1
}
πŸ–₯️ Expected Output
Default constructor called Parameterized constructor called Copy constructor called c2: 3 + 4i c3: 3 + 4i Destructor called for (3+4i) Destructor called for (3+4i) Destructor called for (0+0i)
πŸ’» Program 2 β€” Operator Overloading (+, -, ==)
Must return object β€” the most commonly asked overloading program
#include <iostream>
using namespace std;

class Complex {
public:
    float real, imag;
    Complex(float r = 0, float i = 0) : real(r), imag(i) {}

    // Overload + : returns a NEW Complex object (NOT void)
    Complex operator+(const Complex &c) const {
        return Complex(real + c.real, imag + c.imag);
    }

    // Overload - 
    Complex operator-(const Complex &c) const {
        return Complex(real - c.real, imag - c.imag);
    }

    // Overload == (returns bool)
    bool operator==(const Complex &c) const {
        return (real == c.real && imag == c.imag);
    }

    void display() const {
        cout << real << " + " << imag << "i\n";
    }
};

int main() {
    Complex a(3, 4), b(1, 2);
    Complex sum  = a + b;
    Complex diff = a - b;

    cout << "Sum:  "; sum.display();
    cout << "Diff: "; diff.display();
    cout << "Equal? " << (a == b ? "Yes" : "No") << endl;
    return 0;
}
πŸ–₯️ Expected Output
Sum: 4 + 6i Diff: 2 + 2i Equal? No
πŸ’» Program 3 β€” Unary Operator Overloading (++ prefix & postfix)
#include <iostream>
using namespace std;

class Counter {
    int count;
public:
    Counter(int c = 0) : count(c) {}

    // Prefix ++c : no int parameter
    Counter& operator++() {
        ++count; return *this;
    }

    // Postfix c++ : dummy int parameter
    Counter operator++(int) {
        Counter tmp(*this);
        count++; return tmp;
    }

    void show() const { cout << "Count = " << count << endl; }
};

int main() {
    Counter c(5);
    ++c; c.show(); // prefix
    c++; c.show(); // postfix
    return 0;
}
πŸ–₯️ Expected Output
Count = 6 Count = 7
πŸ’» Program 4 β€” Dynamic Memory (new/delete) + Friend Function
Friend function has access to private members β€” another classic MCQ/program topic
#include <iostream>
using namespace std;

class Box {
private:
    double length, width, height;

public:
    Box(double l, double w, double h)
        : length(l), width(w), height(h) {}

    // Friend function β€” NOT a member, but can access private data
    friend double getVolume(Box b);

    void display() const {
        cout << "Box(" << length << "x"
             << width << "x" << height << ")" << endl;
    }
};

// Defined outside, but has private access because of 'friend'
double getVolume(Box b) {
    return b.length * b.width * b.height;
}

int main() {
    // --- Static allocation ---
    Box b1(3.0, 4.0, 5.0);
    b1.display();
    cout << "Volume: " << getVolume(b1) << endl;

    // --- Dynamic allocation with new/delete ---
    Box* b2 = new Box(2.0, 2.0, 2.0);
    b2->display();
    cout << "Volume: " << getVolume(*b2) << endl;
    delete b2; // MUST free heap memory

    // --- Dynamic array ---
    int n = 3;
    int* arr = new int[n];
    for (int i = 0; i < n; i++) arr[i] = (i + 1) * 10;
    for (int i = 0; i < n; i++) cout << arr[i] << " ";
    cout << endl;
    delete[] arr; // use delete[] for arrays

    return 0;
}
πŸ–₯️ Expected Output
Box(3x4x5) Volume: 60 Box(2x2x2) Volume: 8 10 20 30
⚠️ Exam Traps
  • Returning void from operator+ β€” must return a new object for expressions like a+b+c to work.
  • Writing copy constructor without & reference β€” causes infinite recursion (endless copying).
  • Destructors are called in reverse order of construction β€” last created = first destroyed.
  • Using delete on an array allocated with new[] β€” must use delete[], not delete, to avoid UB.
  • Friend function is declared inside the class with friend keyword but defined outside without any class prefix.
3

Inheritance & Polymorphism

πŸ“– Core Theory
Types of Inheritance

Single β€” one base, one derived.
Multiple β€” many bases, one derived.
Multilevel — A→B→C chain.
Hierarchical β€” one base, many derived.
Hybrid β€” combination (causes diamond problem).

Virtual Functions

virtual enables runtime (dynamic) polymorphism.
Without virtual, base pointer calls base version.
With virtual, base pointer calls derived version via vtable.

Abstract Class

Contains at least one pure virtual function: virtual void f() = 0;
Cannot be instantiated β€” compile error if you try.
Forces derived classes to implement the function.

Diamond Problem

Occurs in Hybrid Inheritance when two paths lead to the same base class.
Fix: use virtual base class β†’ only one copy of base is maintained.

πŸ”₯ Top MCQ Points
  • Abstract classes cannot be instantiated β€” compile-time error.
  • virtual keyword enables runtime polymorphism.
  • Pure virtual: virtual void func() = 0;
  • Virtual destructor in base class is essential when using base pointers to derived objects.
  • Overriding = same signature in derived class. Overloading = different parameters in same class.
πŸ’» Program 1 β€” Hybrid Inheritance with Virtual Base Class
#include <iostream>
using namespace std;

class Student {
public:
    int rollNo;
    Student(int r = 0) : rollNo(r) {}
};

// virtual inheritance prevents duplicate Student in Result
class Marks : virtual public Student {
public:
    float marks;
    Marks(int r = 0, float m = 0) : Student(r), marks(m) {}
};

class Sports : virtual public Student {
public:
    float sportsScore;
    Sports(int r = 0, float s = 0) : Student(r), sportsScore(s) {}
};

class Result : public Marks, public Sports {
public:
    Result(int r, float m, float s)
        : Student(r), Marks(r, m), Sports(r, s) {}

    void display() {
        cout << "Roll No    : " << rollNo      << endl;
        cout << "Marks      : " << marks       << endl;
        cout << "Sports     : " << sportsScore  << endl;
        cout << "Total      : " << (marks + sportsScore) << endl;
    }
};

int main() {
    Result r(101, 85.5, 9.0);
    r.display();
    return 0;
}
πŸ–₯️ Expected Output
Roll No : 101 Marks : 85.5 Sports : 9 Total : 94.5
πŸ’» Program 2 β€” Runtime Polymorphism with Virtual Functions
Shape area calculator β€” the most classic polymorphism example
#include <iostream>
using namespace std;

class Shape {
public:
    virtual void area() {          // virtual β†’ runtime dispatch
        cout << "Area of generic shape\n";
    }
    virtual ~Shape() {}            // virtual destructor β€” ALWAYS add this
};

class Circle : public Shape {
    float r;
public:
    Circle(float r) : r(r) {}
    void area() override {        // 'override' is good practice
        cout << "Circle Area = " << 3.14 * r * r << endl;
    }
};

class Rectangle : public Shape {
    float l, w;
public:
    Rectangle(float l, float w) : l(l), w(w) {}
    void area() override {
        cout << "Rectangle Area = " << l * w << endl;
    }
};

int main() {
    Shape* shapes[2];          // base class POINTERS
    shapes[0] = new Circle(5);
    shapes[1] = new Rectangle(4, 6);

    for (int i = 0; i < 2; i++)
        shapes[i]->area();       // calls DERIVED version at runtime

    for (int i = 0; i < 2; i++)
        delete shapes[i];

    return 0;
}
πŸ–₯️ Expected Output
Circle Area = 78.5 Rectangle Area = 24
πŸ’» Program 3 β€” Abstract Class with Pure Virtual Function
#include <iostream>
using namespace std;

class Animal {      // Abstract class β€” cannot instantiate directly
public:
    virtual void sound() = 0;  // pure virtual function
    void breathe() {
        cout << "Breathing...\n";
    }
    virtual ~Animal() {}
};

class Dog : public Animal {
public:
    void sound() override { cout << "Dog says: Woof!\n"; }
};

class Cat : public Animal {
public:
    void sound() override { cout << "Cat says: Meow!\n"; }
};

int main() {
    // Animal a; // ERROR: cannot instantiate abstract class
    Animal* a1 = new Dog();
    Animal* a2 = new Cat();

    a1->sound();
    a1->breathe();
    a2->sound();

    delete a1; delete a2;
    return 0;
}
πŸ–₯️ Expected Output
Dog says: Woof! Breathing... Cat says: Meow!
πŸ’» Program 4 β€” Multilevel + Hierarchical Inheritance
Two patterns in one file β€” shows how access modes change down the chain
#include <iostream>
using namespace std;

// ── MULTILEVEL: A β†’ B β†’ C ──
class A {
public:
    void showA() { cout << "Class A\n"; }
};

class B : public A {
public:
    void showB() { cout << "Class B\n"; }
};

class C : public B { // C inherits B which inherits A
public:
    void showC() { cout << "Class C\n"; }
};

// ── HIERARCHICAL: Vehicle β†’ Car, Bike ──
class Vehicle {
public:
    int speed;
    Vehicle(int s) : speed(s) {}
    void show() { cout << "Speed: " << speed << endl; }
};

class Car : public Vehicle {
public:
    int doors;
    Car(int s, int d) : Vehicle(s), doors(d) {}
    void display() { cout << "Car | Doors: " << doors << " | "; show(); }
};

class Bike : public Vehicle {
public:
    Bike(int s) : Vehicle(s) {}
    void display() { cout << "Bike | "; show(); }
};

int main() {
    // Multilevel
    C obj;
    obj.showA(); obj.showB(); obj.showC(); // C has all three
    cout << "---\n";
    // Hierarchical
    Car  car(120, 4);
    Bike bike(80);
    car.display();
    bike.display();
    return 0;
}
πŸ–₯️ Expected Output
Class A Class B Class C --- Car | Doors: 4 | Speed: 120 Bike | Speed: 80
⚠️ Exam Traps
  • No virtual destructor in base class β†’ derived destructor never runs β†’ memory leak.
  • Forgetting virtual on base function β†’ base pointer always calls base version, not derived (static binding).
  • No virtual on base classes in diamond inheritance β†’ ambiguity β€” two copies of the base.
  • In multilevel inheritance, constructors run top-down (Aβ†’Bβ†’C); destructors run bottom-up (Cβ†’Bβ†’A).
  • Using private inheritance hides ALL base members from further subclasses β€” use public for normal IS-A relationships.
4

Templates & Exception Handling

πŸ“– Core Theory
Function vs Class Templates

Function template β€” generic function for any type.
Syntax: template <typename T> before the function.
Class template β€” entire class parameterized by type.
Instantiation: Calculator<int> c;

Exception Handling

try β€” block that might throw.
throw β€” raises an exception.
catch β€” handles the exception.
catch(...) β€” catches everything; must be last.

Exception Hierarchy

You can throw and catch: int, float, string, or objects.
Standard: std::exception β†’ runtime_error, logic_error, etc.
Use e.what() to get the error message string.

Rethrowing

Use bare throw; inside a catch block to rethrow the current exception up the call stack.

πŸ”₯ Top MCQ Points
  • catch(...) catches all exceptions β€” must always be last.
  • Function templates allow generic, type-independent programming.
  • Keyword typename and class are interchangeable inside template<>.
  • If no matching catch is found, std::terminate() is called.
  • throw; (no argument) rethrows the current exception.
πŸ’» Program 1 β€” Class Template: Generic Calculator + Exception Handling
#include <iostream>
using namespace std;

template <typename T>
class Calculator {
public:
    T add     (T a, T b) { return a + b; }
    T subtract(T a, T b) { return a - b; }
    T multiply(T a, T b) { return a * b; }

    T divide(T a, T b) {
        if (b == 0) throw runtime_error("Division by zero!");
        return a / b;
    }
};

int main() {
    Calculator<int>    ic;
    Calculator<double> dc;

    cout << "Add (int)    : " << ic.add(10, 5)       << endl;
    cout << "Mul (double) : " << dc.multiply(3.5, 2.0) << endl;
    cout << "Div (double) : " << dc.divide(7.5, 2.5)  << endl;

    try {
        cout << ic.divide(10, 0);   // will throw
    }
    catch (const runtime_error &e) { // specific β†’ FIRST
        cout << "Caught: " << e.what() << endl;
    }
    catch (...) {                     // catch-all β†’ LAST
        cout << "Unknown error!\n";
    }

    return 0;
}
πŸ–₯️ Expected Output
Add (int) : 15 Mul (double) : 7 Div (double) : 3 Caught: Division by zero!
πŸ’» Program 2 β€” Function Template: Largest of Two + Swap
#include <iostream>
using namespace std;

template <typename T>
T largest(T a, T b) {
    return (a > b) ? a : b;
}

template <typename T>
void swapValues(T &a, T &b) {
    T tmp = a; a = b; b = tmp;
}

int main() {
    cout << "Largest int    : " << largest(12, 45)       << endl;
    cout << "Largest double : " << largest(3.14, 2.71)   << endl;
    cout << "Largest char   : " << largest('Z', 'A')       << endl;

    int x = 10, y = 20;
    swapValues(x, y);
    cout << "After swap: x=" << x << " y=" << y << endl;

    return 0;
}
πŸ–₯️ Expected Output
Largest int : 45 Largest double : 3.14 Largest char : Z After swap: x=20 y=10
πŸ’» Program 3 β€” Multiple Catch Blocks + Custom Exception Class
#include <iostream>
using namespace std;

// Custom exception class
class AgeException : public exception {
public:
    const char* what() const noexcept override {
        return "Age cannot be negative!";
    }
};

void checkAge(int age) {
    if (age < 0)  throw AgeException();
    if (age < 18) throw string("Underage: access denied");
    cout << "Access granted. Age: " << age << endl;
}

int main() {
    int ages[] = {25, 15, -3};

    for (int age : ages) {
        try {
            checkAge(age);
        }
        catch (const AgeException &e) {    // most specific first
            cout << "AgeException: " << e.what() << endl;
        }
        catch (const string &s) {
            cout << "String error: " << s << endl;
        }
        catch (...) {                         // always LAST
            cout << "Unknown exception!\n";
        }
    }
    return 0;
}
πŸ–₯️ Expected Output
Access granted. Age: 25 String error: Underage: access denied AgeException: Age cannot be negative!
πŸ’» Program 4 β€” Stack using Class Template + Exception Safety
Full data structure using a class template β€” high-value long-answer question
#include <iostream>
using namespace std;

class StackUnderflow : public exception {
public:
    const char* what() const noexcept override {
        return "Stack Underflow: pop on empty stack!";
    }
};

template <typename T, int SIZE = 5> // non-type template param!
class Stack {
private:
    T data[SIZE];
    int top;

public:
    Stack() : top(-1) {}

    void push(T val) {
        if (top == SIZE - 1) { cout << "Stack Full!\n"; return; }
        data[++top] = val;
    }

    T pop() {
        if (top == -1) throw StackUnderflow();
        return data[top--];
    }

    T peek() const {
        if (top == -1) throw StackUnderflow();
        return data[top];
    }

    bool isEmpty() const { return top == -1; }
    int  size()    const { return top + 1; }
};

int main() {
    Stack<int> s;
    s.push(10); s.push(20); s.push(30);

    cout << "Peek: "  << s.peek() << endl;
    cout << "Pop:  "  << s.pop()  << endl;
    cout << "Size: "  << s.size() << endl;

    try {
        Stack<int> empty;
        empty.pop(); // throws!
    } catch (const StackUnderflow& e) {
        cout << "Caught: " << e.what() << endl;
    }

    // Stack of strings β€” same template, different type
    Stack<string, 3> ss;
    ss.push("Hello"); ss.push("World");
    cout << "String peek: " << ss.peek() << endl;

    return 0;
}
πŸ–₯️ Expected Output
Peek: 30 Pop: 30 Size: 2 Caught: Stack Underflow: pop on empty stack! String peek: World
⚠️ Exam Traps
  • Placing catch(...) before specific catch blocks β€” it swallows everything; specific blocks become dead code.
  • Forgetting template <typename T> before each function definition when defined outside the class.
  • Catching by value when you should catch by const reference β€” expensive copy + slicing for class exceptions.
  • Templates are not compiled until instantiated β€” syntax errors may not appear until you create a Stack<int>.
  • noexcept on what() β€” std::exception's signature requires it; omitting causes a warning or compiler mismatch.
5

STL β€” Standard Template Library

πŸ“– Core Theory
3 Components of STL

Containers β€” store data (vector, list, map, set, stack, queue).
Algorithms β€” process data (sort, find, count, reverse).
Iterators β€” access elements like generalized pointers.

Container Quick Reference

vector β€” dynamic array, random access O(1).
list β€” doubly linked list, no random access.
map β€” sorted key-value pairs, unique keys.
set β€” sorted unique elements.
stack/queue β€” LIFO / FIFO adapters.

sort() Constraint

std::sort() needs random-access iterators.
Works on: vector, array, deque.
Does NOT work on: list, map, set.
For list: use lst.sort() (member function).

Iterator Types

begin() β€” iterator to first element.
end() β€” iterator past the last element.
auto keyword simplifies iterator declarations.
Range-for: for(auto x : container)

πŸ”₯ Top MCQ Points
  • map stores key-value pairs in sorted key order; all keys unique.
  • vector is a dynamic array β€” grows automatically; supports random access.
  • STL = Containers + Algorithms + Iterators.
  • std::sort() requires random-access iterators β€” cannot be used directly on list.
  • push_back() β€” adds to end; push_front() β€” adds to front (list/deque only).
πŸ’» Program 1 β€” Vector Full Operations
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> v = {50, 10, 40, 20, 30};

    v.push_back(60);                 // add to end
    v.insert(v.begin() + 2, 99);   // insert 99 at index 2

    cout << "Before sort: ";
    for (int x : v) cout << x << " ";

    sort(v.begin(), v.end());       // sort ascending

    cout << "\nAfter sort:  ";
    for (int x : v) cout << x << " ";

    v.erase(v.begin() + 1);        // erase element at index 1

    cout << "\nAfter erase: ";
    for (int x : v) cout << x << " ";

    cout << "\nSize: " << v.size() << endl;
    return 0;
}
πŸ–₯️ Expected Output
Before sort: 50 10 99 40 20 30 60 After sort: 10 20 30 40 50 60 99 After erase: 10 30 40 50 60 99 Size: 6
πŸ’» Program 2 β€” List (.sort() member) + Map (key-value)
#include <iostream>
#include <list>
#include <map>
using namespace std;

int main() {
    // ---- LIST ----
    list<int> lst = {5, 2, 8, 1, 9};
    lst.push_back(3);
    lst.push_front(0);

    lst.sort();  // member function β€” std::sort() won't work on list!

    cout << "List (sorted): ";
    for (int x : lst) cout << x << " ";
    cout << endl;

    lst.remove(5);   // remove all occurrences of 5
    cout << "After remove(5): ";
    for (int x : lst) cout << x << " ";
    cout << endl;

    // ---- MAP ----
    map<string, int> scores;
    scores["Alice"] = 95;
    scores["Bob"]   = 88;
    scores["Carol"] = 91;
    scores.insert({"Dave", 78});

    cout << "\nMap (sorted by key):\n";
    for (auto &p : scores)
        cout << "  " << p.first << " -> " << p.second << endl;

    // Check if key exists
    if (scores.find("Bob") != scores.end())
        cout << "Bob's score: " << scores["Bob"] << endl;

    return 0;
}
πŸ–₯️ Expected Output
List (sorted): 0 1 2 3 5 8 9 After remove(5): 0 1 2 3 8 9 Map (sorted by key): Alice -> 95 Bob -> 88 Carol -> 91 Dave -> 78 Bob's score: 88
πŸ’» Program 3 β€” Set + STL Algorithms (find, reverse, count)
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;

int main() {
    // SET: unique + sorted automatically
    set<int> s = {5, 1, 3, 5, 2, 1}; // duplicates dropped
    cout << "Set: ";
    for (int x : s) cout << x << " ";
    cout << endl;

    // VECTOR ALGORITHMS
    vector<int> v = {3, 1, 4, 1, 5, 9, 2, 6};

    // find
    auto it = find(v.begin(), v.end(), 5);
    if (it != v.end())
        cout << "Found 5 at index: " << (it - v.begin()) << endl;

    // count
    cout << "Count of 1: " << count(v.begin(), v.end(), 1) << endl;

    // reverse
    reverse(v.begin(), v.end());
    cout << "Reversed: ";
    for (int x : v) cout << x << " ";
    cout << endl;

    return 0;
}
πŸ–₯️ Expected Output
Set: 1 2 3 5 Found 5 at index: 4 Count of 1: 2 Reversed: 6 2 9 5 1 4 1 3
πŸ’» Program 4 β€” Stack, Queue + More Algorithms (accumulate, max_element)
Container adapters + numeric algorithms β€” frequently asked in short questions
#include <iostream>
#include <stack>
#include <queue>
#include <vector>
#include <numeric>   // for accumulate
#include <algorithm>
using namespace std;

int main() {
    // ── STACK (LIFO) ──
    stack<int> st;
    st.push(1); st.push(2); st.push(3);
    cout << "Stack (LIFO): ";
    while (!st.empty()) {
        cout << st.top() << " ";
        st.pop();
    }
    cout << endl;

    // ── QUEUE (FIFO) ──
    queue<int> q;
    q.push(10); q.push(20); q.push(30);
    cout << "Queue (FIFO): ";
    while (!q.empty()) {
        cout << q.front() << " ";
        q.pop();
    }
    cout << endl;

    // ── NUMERIC ALGORITHMS ──
    vector<int> v = {5, 3, 8, 1, 9, 2};

    int sum = accumulate(v.begin(), v.end(), 0);
    auto maxIt = max_element(v.begin(), v.end());
    auto minIt = min_element(v.begin(), v.end());

    cout << "Sum:     " << sum    << endl;
    cout << "Max:     " << *maxIt << endl;
    cout << "Min:     " << *minIt << endl;

    // Sort descending using comparator lambda
    sort(v.begin(), v.end(), [](
        int a, int b){ return a > b; });
    cout << "Sorted desc: ";
    for (int x : v) cout << x << " ";
    cout << endl;

    return 0;
}
πŸ–₯️ Expected Output
Stack (LIFO): 3 2 1 Queue (FIFO): 10 20 30 Sum: 28 Max: 9 Min: 1 Sorted desc: 9 8 5 3 2 1
⚠️ Exam Traps
  • std::sort(lst.begin(), lst.end()) on a list will not compile β€” lists have no random-access iterators. Always use lst.sort().
  • Accessing a map key with [] that doesn't exist creates that key with default value 0 β€” use .find() to safely check.
  • Forgetting headers: include <vector>, <list>, <map>, <set>, <algorithm> separately.
  • stack uses .top() to peek; queue uses .front(). Mixing them up is the #1 runtime mistake.
  • accumulate is in <numeric>, NOT <algorithm> β€” forgetting this causes a compile error.
B1

File I/O β€” fstream, ifstream, ofstream, stringstream

#include <fstream> #include <sstream> ifstream ofstream fstream open() close() is_open() eof() getline()
πŸ“– Core Theory
ifstream β€” Read

Input file stream β€” reads from file.
ifstream fin("file.txt");
fin >> var; or getline(fin, str);

ofstream β€” Write

Output file stream β€” writes to file (creates if absent, overwrites by default).
ofstream fout("out.txt");
fout << "Hello";

fstream β€” Read+Write

Combines both. Must specify mode:
fstream f("a.txt", ios::in | ios::out);
Modes: ios::app (append), ios::trunc (overwrite), ios::binary

stringstream

String-based stream β€” useful for type conversion and parsing.
stringstream ss;
ss << 42; string s = ss.str();
int to string, string to int β€” no atoi needed.

πŸ”₯ MCQ Points
  • ifstream is used for reading; ofstream for writing; fstream for both.
  • ios::app opens file in append mode β€” does NOT erase existing content.
  • eof() returns true when end-of-file is reached.
  • getline(fin, str) reads an entire line including spaces; fin >> x stops at whitespace.
  • Always call close() after file operations to flush and release the resource.
πŸ’» Program 1 β€” Write & Read a File + Append Mode
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() {
    // ── WRITE to file ──
    ofstream fout("students.txt");
    if (!fout) { cout << "Cannot open file!\n"; return 1; }
    fout << "Alice 92\n";
    fout << "Bob   85\n";
    fout << "Carol 78\n";
    fout.close();
    cout << "File written.\n";

    // ── READ from file ──
    ifstream fin("students.txt");
    string line;
    cout << "--- File Contents ---\n";
    while (getline(fin, line))   // reads line by line
        cout << line << endl;
    fin.close();

    // ── APPEND to file ──
    ofstream fapp("students.txt", ios::app);
    fapp << "Dave  91\n";
    fapp.close();

    // ── READ again to verify ──
    ifstream fin2("students.txt");
    cout << "--- After Append ---\n";
    while (getline(fin2, line))
        cout << line << endl;
    fin2.close();

    return 0;
}
πŸ–₯️ Expected Output
File written. --- File Contents --- Alice 92 Bob 85 Carol 78 --- After Append --- Alice 92 Bob 85 Carol 78 Dave 91
πŸ’» Program 2 β€” stringstream: Type Conversion + Parsing
#include <iostream>
#include <sstream>
#include <string>
using namespace std;

int main() {
    // int β†’ string
    int num = 42;
    stringstream ss;
    ss << num;
    string s = ss.str();
    cout << "int to string: \"" << s << "\"\n";

    // string β†’ int
    string token = "2024";
    stringstream ss2(token);
    int year;
    ss2 >> year;
    cout << "string to int: " << year + 1 << endl;

    // Parsing CSV-like string
    string data = "Alice 95 A";
    stringstream ss3(data);
    string name, grade;
    int marks;
    ss3 >> name >> marks >> grade;
    cout << "Name: " << name
         << " Marks: " << marks
         << " Grade: " << grade << endl;

    return 0;
}
πŸ–₯️ Expected Output
int to string: "42" string to int: 2025 Name: Alice Marks: 95 Grade: A
⚠️ Exam Traps
  • Opening a file without checking if (!fin) β€” if the file doesn't exist, all reads silently fail and produce garbage.
  • Using fin >> str to read a line with spaces β€” it stops at whitespace. Use getline(fin, str) for full lines.
  • Forgetting fout.close() β€” buffer may not flush; last few writes can be lost.
  • ofstream with default mode truncates existing file. Use ios::app to preserve content.
B2

Type Casting β€” C++ Style Casts (Exam Favourite)

πŸ“– Core Theory
static_cast

Compile-time cast. Safe for related types.
double d = static_cast<double>(5);
Use for: int↔double, base↔derived (when safe), enum↔int.

dynamic_cast

Runtime cast. For polymorphic (virtual) hierarchies only.
D* d = dynamic_cast<D*>(bPtr);
Returns nullptr on failure (pointers) or throws on references. Requires RTTI.

const_cast

Adds or removes const qualifier.
const_cast<int*>(cptr);
Only legal cast to remove const β€” modifying original const object = UB.

reinterpret_cast

Low-level bit-level reinterpretation. Unsafe.
int* p = reinterpret_cast<int*>(addr);
Use for: pointer↔integer, casting to void*. Avoid unless doing hardware/system programming.

πŸ”₯ MCQ Points
  • static_cast is checked at compile time; dynamic_cast at runtime.
  • dynamic_cast works only with polymorphic classes (at least one virtual function).
  • const_cast is the only cast that can remove const.
  • Old C-style cast (int)x is equivalent to a combination of all four β€” avoid in C++.
  • dynamic_cast to pointer returns nullptr on failure; to reference throws std::bad_cast.
πŸ’» Program β€” All 4 C++ Casts Demonstrated
#include <iostream>
using namespace std;

class Base { public: virtual void f() { cout << "Base\n"; } };
class Derived : public Base { public: void f() { cout << "Derived\n"; } };

int main() {
    // 1. static_cast β€” compile-time, safe related types
    double pi = 3.14159;
    int iPi = static_cast<int>(pi);  // truncates decimal
    cout << "static_cast: " << iPi << endl;

    // 2. dynamic_cast β€” runtime, polymorphic classes only
    Base* b = new Derived();
    Derived* d = dynamic_cast<Derived*>(b);
    if (d) cout << "dynamic_cast: success β€” "; d->f();

    Base* b2 = new Base();
    Derived* d2 = dynamic_cast<Derived*>(b2);
    cout << "dynamic_cast fail: " << (d2 ? "ok" : "nullptr") << endl;

    // 3. const_cast β€” remove const qualifier
    const int cx = 100;
    int* px = const_cast<int*>(&cx);
    cout << "const_cast: " << *px << endl; // reading is OK

    // 4. reinterpret_cast β€” low-level pointer interpretation
    long addr = reinterpret_cast<long>(b);
    cout << "reinterpret_cast addr: " << addr << endl;

    delete b; delete b2;
    return 0;
}
πŸ–₯️ Expected Output
static_cast: 3 dynamic_cast: success β€” Derived dynamic_cast fail: nullptr const_cast: 100 reinterpret_cast addr: [some memory address]
⚠️ Exam Traps
  • Using dynamic_cast on a class with no virtual functions β†’ compile error. The base must be polymorphic.
  • static_cast between unrelated classes compiles but causes undefined behavior at runtime.
  • Modifying a truly const variable via const_cast β†’ undefined behavior (only use const_cast to pass const data to legacy non-const APIs).
B3

Advanced OOP β€” Default Args, Shallow/Deep Copy, explicit, const, mutable

πŸ“– Core Theory
Default Arguments

Parameters with default values β€” must be rightmost.
void f(int a, int b = 10, int c = 20);
f(5); β†’ a=5, b=10, c=20.
Default values go in the declaration, not definition.

Shallow vs Deep Copy

Shallow Copy (default) β€” copies pointer values; both objects share the same heap memory β†’ double-free bug on destruction.
Deep Copy β€” allocates new memory and copies actual data. Must write a custom copy constructor when class has pointer members.

explicit Keyword

Prevents implicit type conversion via single-argument constructors.
Without explicit: MyClass obj = 5; compiles silently.
With explicit: must write MyClass obj(5);

const & mutable

const member function: void f() const {} β€” cannot modify any member variable; can be called on const objects.
mutable: mutable int count; β€” allows modification even inside a const function. Used for caching/logging.

πŸ”₯ MCQ Points
  • Default arguments must always be on the rightmost parameters β€” putting them on the left is a compile error.
  • Shallow copy uses the default copy constructor; causes issues when the class has pointer members.
  • Deep copy requires a custom copy constructor that allocates new memory.
  • explicit keyword on a constructor disables implicit conversion β€” forces direct initialization.
  • A const member function cannot call a non-const member function on the same object.
  • mutable members can be modified even in const functions β€” exception to the const rule.
πŸ’» Program 1 β€” Shallow vs Deep Copy (Classic Pointer Problem)
#include <iostream>
#include <cstring>
using namespace std;

class ShallowDemo {
public:
    int* data;
    ShallowDemo(int v) { data = new int(v); }
    // Default copy constructor = shallow: both share same pointer!
    ~ShallowDemo() { delete data; } // double-free bug!
};

class DeepDemo {
public:
    int* data;

    DeepDemo(int v) { data = new int(v); }

    // Deep copy constructor β€” allocates NEW memory
    DeepDemo(const DeepDemo& other) {
        data = new int(*other.data); // new allocation, copied value
        cout << "Deep copy performed\n";
    }

    ~DeepDemo() { delete data; } // safe: each object owns its memory
};

int main() {
    DeepDemo d1(99);
    DeepDemo d2(d1);          // triggers deep copy

    *d1.data = 200;           // modify d1
    cout << "d1: " << *d1.data << endl; // 200
    cout << "d2: " << *d2.data << endl; // still 99 β€” independent!

    return 0;
}
πŸ–₯️ Expected Output
Deep copy performed d1: 200 d2: 99
πŸ’» Program 2 β€” Default Args + explicit + const + mutable
#include <iostream>
using namespace std;

class Config {
private:
    string host;
    int port;
    mutable int accessCount; // modifiable even in const functions

public:
    // Default arguments β€” rightmost MUST have defaults
    explicit Config(string h, int p = 8080)
        : host(h), port(p), accessCount(0) {}

    // const member function β€” cannot modify host/port
    void display() const {
        accessCount++; // OK: mutable
        cout << host << ":" << port
             << " [accessed " << accessCount << " time(s)]\n";
    }

    void setPort(int p) { port = p; } // non-const: can modify
};

int main() {
    // explicit prevents: Config c = "localhost"; (implicit conversion)
    Config c1("localhost");         // port defaults to 8080
    Config c2("example.com", 443); // explicit port

    c1.display(); c1.display();
    c2.display();

    const Config cc("secure.io", 9000);
    cc.display(); // const object β†’ can only call const functions
    // cc.setPort(1234); // ERROR: can't call non-const on const object

    return 0;
}
πŸ–₯️ Expected Output
localhost:8080 [accessed 1 time(s)] localhost:8080 [accessed 2 time(s)] example.com:443 [accessed 1 time(s)] secure.io:9000 [accessed 1 time(s)]
⚠️ Exam Traps
  • Shallow copy with pointer members β†’ destructor of one object frees memory still used by the other β†’ crash / undefined behavior.
  • Default arguments in the definition (not declaration) β€” if prototype is in header, defaults must be in the header.
  • Calling a non-const member function from a const function β†’ compile error. Mark helper functions const too.
  • Forgetting explicit on single-arg constructors β€” silent implicit conversion can cause very subtle bugs.
B4

Advanced STL β€” priority_queue, unordered_map, lower_bound, make_pair, Template Specialization

πŸ“– Core Theory
priority_queue

Max-heap by default β€” top() always gives the largest element.
priority_queue<int> pq;
Min-heap: priority_queue<int, vector<int>, greater<int>> pq;

unordered_map

Hash-based map β€” O(1) average lookup (vs map's O(log n)).
No guaranteed order of keys.
unordered_map<string, int> um;

lower_bound / upper_bound

Binary search on sorted containers.
lower_bound(v.begin(), v.end(), x) β†’ iterator to first element β‰₯ x.
upper_bound(..., x) β†’ iterator to first element > x.

make_pair & Template Specialization

make_pair(a, b) creates a pair<T1,T2> β€” used in maps, sorting tuples.

Template Specialization: provide a specific implementation for one type.
template<> void f<int>() { ... }

πŸ”₯ MCQ Points
  • priority_queue is a max-heap by default β€” largest element at top().
  • unordered_map gives O(1) average access; map gives O(log n).
  • lower_bound requires the container to be sorted first β€” returns iterator to first element β‰₯ key.
  • pair stores two values: accessed via .first and .second.
  • Template specialization uses template<> (empty angle brackets) before the function/class.
πŸ’» Program 1 β€” priority_queue + unordered_map + make_pair
#include <iostream>
#include <queue>
#include <unordered_map>
#include <vector>
#include <utility>   // make_pair
using namespace std;

int main() {
    // ── MAX-HEAP priority_queue ──
    priority_queue<int> pq;
    pq.push(30); pq.push(10); pq.push(50); pq.push(20);
    cout << "Max-heap order: ";
    while (!pq.empty()) { cout << pq.top() << " "; pq.pop(); }
    cout << endl;

    // ── MIN-HEAP ──
    priority_queue<int, vector<int>, greater<int>> minPQ;
    minPQ.push(30); minPQ.push(10); minPQ.push(50);
    cout << "Min-heap order: ";
    while (!minPQ.empty()) { cout << minPQ.top() << " "; minPQ.pop(); }
    cout << endl;

    // ── UNORDERED_MAP (O(1) lookup) ──
    unordered_map<string, int> freq;
    string words[] = {"apple", "banana", "apple", "cherry", "banana", "apple"};
    for (auto& w : words) freq[w]++;
    cout << "Word frequencies:\n";
    for (auto& p : freq)
        cout << "  " << p.first << ": " << p.second << endl;

    // ── MAKE_PAIR ──
    vector<pair<int, string>> students;
    students.push_back(make_pair(92, "Alice"));
    students.push_back(make_pair(85, "Bob"));
    students.push_back({97, "Carol"});  // brace init also works
    sort(students.begin(), students.end()); // sorts by first (score)
    cout << "Sorted students: ";
    for (auto& s : students)
        cout << s.second << "(" << s.first << ") ";
    cout << endl;

    return 0;
}
πŸ–₯️ Expected Output
Max-heap order: 50 30 20 10 Min-heap order: 10 30 50 Word frequencies: cherry: 1 banana: 2 apple: 3 Sorted students: Bob(85) Alice(92) Carol(97)
πŸ’» Program 2 β€” lower_bound / upper_bound + Template Specialization
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

// ── TEMPLATE: generic print ──
template <typename T>
void printInfo(T val) {
    cout << "Generic: " << val << endl;
}

// ── TEMPLATE SPECIALIZATION for bool ──
template<>
void printInfo<bool>(bool val) {
    cout << "Bool specialization: " << (val ? "TRUE" : "FALSE") << endl;
}

int main() {
    // Template specialization demo
    printInfo(42);        // uses generic
    printInfo(3.14);      // uses generic
    printInfo(true);      // uses bool specialization

    // lower_bound / upper_bound (requires SORTED vector)
    vector<int> v = {10, 20, 30, 40, 50, 60};

    auto lo = lower_bound(v.begin(), v.end(), 30); // first >= 30
    auto hi = upper_bound(v.begin(), v.end(), 30); // first > 30

    cout << "lower_bound(30) index: " << (lo - v.begin()) << endl;
    cout << "upper_bound(30) index: " << (hi - v.begin()) << endl;
    cout << "Value at lower: "       << *lo << endl;

    // Binary search
    bool found = binary_search(v.begin(), v.end(), 40);
    cout << "40 in vector: " << (found ? "Yes" : "No") << endl;

    return 0;
}
πŸ–₯️ Expected Output
Generic: 42 Generic: 3.14 Bool specialization: TRUE lower_bound(30) index: 2 upper_bound(30) index: 3 Value at lower: 30 40 in vector: Yes
⚠️ Exam Traps
  • lower_bound / upper_bound / binary_search only work correctly on sorted containers β€” calling on unsorted data gives wrong results without error.
  • priority_queue does NOT have begin()/end() β€” you can only access top() and must pop() to iterate.
  • unordered_map has no guaranteed key order β€” if the question says "sorted output", use map instead.
  • Template specialization uses template<> with empty brackets β€” missing them or writing template<bool> is wrong.

πŸ“Š High-Value Comparison Tables

Class vs Struct vs Union
Featureclassstructunion
Default Accessprivatepublicpublic
Inheritanceβœ… Supportedβœ… Supported❌ Not supported
MemorySum of membersSum of membersLargest member only
Use caseOOP with data hidingSimple data groupingMemory-saving type pun
Compile-time vs Runtime Polymorphism
FeatureCompile-time (Static)Runtime (Dynamic)
MechanismFunction / Operator OverloadingVirtual Functions + Pointers
Resolved atCompile timeRuntime (via vtable)
SpeedFasterSlight overhead
KeywordNone neededvirtual
FlexibilityLess flexibleMore flexible
STL Container Quick Comparison
ContainerAccessOrdered?Duplicates?Use when
vectorRandom O(1)Insertion orderβœ… YesDynamic array, most common
listSequentialInsertion orderβœ… YesFrequent insert/delete at middle
mapKey lookup O(log n)Sorted by key❌ Unique keysKey-value store
setKey lookup O(log n)Sorted❌ NoUnique sorted elements
stackTop onlyLIFOβœ… YesUndo, recursion simulation
queueFront/backFIFOβœ… YesTask scheduling, BFS
Constructor Types at a Glance
TypeSignatureCalled when
DefaultName()Name obj;
ParameterizedName(int x)Name obj(5);
CopyName(const Name& o)Name b = a; or passing by value
Destructor~Name()Object goes out of scope / delete
Inheritance Access Table β€” What the derived class can see
Base Memberpublic inheritanceprotected inheritanceprivate inheritance
public in Basepublic in Derivedprotected in Derivedprivate in Derived
protected in Baseprotected in Derivedprotected in Derivedprivate in Derived
private in Base❌ Not accessible❌ Not accessible❌ Not accessible
map vs unordered_map
Featuremapunordered_map
OrderingSorted by keyNo order guaranteed
LookupO(log n)O(1) average
ImplementationRed-Black TreeHash Table
Key requirementComparable (<)Hashable
Use whenNeed sorted keysSpeed is priority
4 C++ Type Casts
CastWhen to useChecked atSafety
static_castRelated types (int↔double)Compileβœ… Safe
dynamic_castPolymorphic class hierarchiesRuntimeβœ… Safe (nullptr on fail)
const_castRemove/add const qualifierCompile⚠️ UB if original is const
reinterpret_castLow-level pointer reinterpretCompile❌ Unsafe
Shallow Copy vs Deep Copy
FeatureShallow CopyDeep Copy
HowDefault copy constructorCustom copy constructor
What's copiedPointer address (same memory)New allocation + data copied
ProblemDouble-free crash on destructionNo issue
When neededNo pointer members (safe)Class has pointer/heap members

🎯 Predicted Exam Q&A β€” MCQ + Short + Long

MCQ Which operators CANNOT be overloaded in C++?
Answer: :: (scope), . (member access), .* (pointer to member), ?: (ternary), sizeof, typeid.
Memory trick: "SD???" β€” Scope, Dot, pointer-to-member, ternary, Sizeof.
MCQ What is the output when a derived object is deleted via a base pointer without a virtual destructor?
Answer: Undefined Behavior β€” the derived class destructor is never called, causing a memory leak. Always declare base class destructors as virtual ~Base() {}.
MCQ What does catch(...) do, and where must it appear?
Answer: catch(...) catches all exception types regardless of what was thrown. It must appear last in a sequence of catch blocks β€” placing it before specific handlers makes them unreachable.
MCQ Why can't std::sort() be used on std::list?
Answer: std::sort() requires random-access iterators (ability to jump to any element in O(1)). std::list only provides bidirectional iterators. Use lst.sort() instead β€” it's a member function that uses a merge sort internally.
Short What is the difference between function overloading and function overriding?
Overloading: Multiple functions with the same name but different parameters in the same class. Resolved at compile time (static polymorphism).

Overriding: A derived class redefines a base class virtual function with the same signature. Resolved at runtime via vtable (dynamic polymorphism).
Short What is the difference between a copy constructor and an assignment operator?
Copy Constructor β€” creates a new object as a copy: Name b(a); or Name b = a; (at declaration).

Assignment Operator (=) β€” copies data into an already existing object: b = a; (b was created earlier).
Signature: Name& operator=(const Name& o) { ... return *this; }
Short What is a virtual function? Why is it needed?
A virtual function is a member function declared with the virtual keyword in the base class. When called through a base class pointer or reference, it ensures the derived class version is invoked at runtime (dynamic dispatch via vtable).

Without it: Base* p = new Derived(); p->f(); calls Base::f().
With it: same code calls Derived::f(). This is the foundation of runtime polymorphism.
Short What is the diamond problem? How is it solved?
When two classes B and C both inherit from A, and D inherits from both B and C β€” D ends up with two copies of A's members, causing ambiguity.

Fix: Declare B and C as virtual public A. Virtual inheritance ensures only one shared copy of A exists in D, eliminating the ambiguity.
Long Explain templates in C++ with examples of both function and class templates. What are their advantages?
Templates allow writing generic, type-independent code. The compiler generates specific versions at instantiation.

Function Template:
template <typename T> T largest(T a, T b) { return (a > b) ? a : b; }
Works for int, double, char β€” one definition covers all.

Class Template:
template <typename T> class Calc { T add(T a, T b) { return a+b; } };
Instantiated as Calc<int> c; or Calc<double> c;

Advantages: Code reuse, type safety, no code duplication, basis of entire STL.
Long Explain exception handling in C++ with syntax, flow, and a program.
Purpose: Handle runtime errors gracefully without crashing.

Keywords: try β€” wraps risky code. throw β€” raises an exception. catch β€” handles it.

Flow: Code in try executes β†’ if throw is reached, execution jumps immediately to the matching catch β†’ remaining try code is skipped β†’ if no match, std::terminate() is called.

Rules to remember:
1. Most specific catch first.
2. catch(...) always last.
3. Catch by const reference to avoid slicing.
4. Custom exceptions should inherit from std::exception and override what().
Long What is STL? Explain its three components with examples.
The Standard Template Library (STL) is a collection of generic C++ classes and functions.

1. Containers β€” store data:
vector, list, map, set, stack, queue, deque

2. Algorithms β€” process data (work via iterators):
sort(), find(), count(), reverse(), accumulate(), max_element()

3. Iterators β€” abstract pointers to elements:
begin(), end(), auto it = v.begin(); ++it;

Iterators decouple algorithms from containers β€” sort() works on any container that provides random-access iterators without knowing the container type.
MCQ What is the difference between map and unordered_map?
map is implemented as a Red-Black tree β€” keys are always sorted, lookup is O(log n). unordered_map is a hash table β€” no order, but average O(1) lookup. Use map when you need sorted keys; use unordered_map for raw speed.
MCQ What is the difference between shallow copy and deep copy?
Shallow copy (default copy constructor) copies pointer addresses β€” both objects point to the same heap memory, causing a double-free crash on destruction. Deep copy allocates new memory and copies the actual data, so each object owns its own memory independently.
Short What is explicit keyword? Why use it?
explicit prevents a constructor from being used for implicit type conversion. Without it, MyClass obj = 5; silently converts 5 into a MyClass object, which can cause subtle bugs. With explicit, only direct initialization MyClass obj(5); is allowed. Best practice: mark all single-argument constructors explicit unless conversion is intentional.
Short What is File I/O in C++? Explain with types.
C++ provides file I/O through the <fstream> header with three classes:

ifstream β€” input (read) from file. ifstream fin("a.txt"); fin >> x;
ofstream β€” output (write) to file. ofstream fout("b.txt"); fout << x;
fstream β€” both read and write.

Key file modes: ios::in, ios::out, ios::app (append), ios::binary.
Always call close() after operations to flush the buffer.
Short Explain the four C++ casting operators.
static_cast β€” compile-time cast for related types (int↔double, base↔derived safely).
dynamic_cast β€” runtime cast for polymorphic hierarchies; returns nullptr on failure.
const_cast β€” only cast that can remove const; UB if you write to a truly const object.
reinterpret_cast β€” low-level bit reinterpretation; unsafe, used for hardware-level code.
Long What is template specialization? Explain with example.
Template specialization lets you provide a custom implementation of a template for a specific type, while the generic template handles all other types.

Full specialization syntax: template<> (empty angle brackets) before the function.

Example: A generic printInfo<T> prints any type, but the bool specialization prints "TRUE"/"FALSE" instead of 1/0.

Why useful: Lets you optimize or correct behavior for specific types without writing entirely separate functions or classes. The entire STL uses specialization heavily (e.g., vector<bool> is a specialization that packs bits).
Long Describe the complete OOP concept of Encapsulation with real-world analogy, program, and advantages.
Definition: Encapsulation is the bundling of data (variables) and the functions that operate on that data within a single unit (class), with controlled access via access specifiers.

Real-world analogy: A car's engine is hidden under the hood. You interact with it only via the steering wheel, pedals, and gear β€” you can't directly touch the pistons. The interface (public methods) is exposed; the implementation (private data) is hidden.

Implementation: Declare members private; provide public getter/setter methods.

Advantages:
1. Data security β€” prevents unauthorized direct access.
2. Maintainability β€” internal implementation can change without affecting outside code.
3. Controlled access β€” validation logic inside setters.
4. Modularity β€” class is a self-contained unit.
⏱️ 30-Minute Survival Strategy
1

4 Pillars first. Write Encapsulation, Abstraction, Inheritance, Polymorphism at the top of every theory answer.

2

Semicolon }; after every class. Non-negotiable. One missing semicolon = cascade of errors.

3

virtual = runtime polymorphism. Base pointer + derived object + virtual function = correct derived method called.

4

Virtual destructor ALWAYS. If you have a base class with pointers to derived, make the destructor virtual.

5

catch(...) is LAST. Specific catches come first. catch-all is always the final safety net.

6

lst.sort() NOT std::sort(lst). Lists lack random access β€” they must use their own member sort.

7

Operator+ must return object, not void. Return type is the class itself so chaining works.

8

template <typename T> before EVERY function. When defined outside the class, repeat it for each function.

9

Shallow copy = danger with pointers. Any class with a raw pointer member MUST have a custom copy constructor doing deep copy.

10

File I/O: always check + always close. if (!fin) after opening. fin.close() at the end. Use getline() for lines with spaces.

11

dynamic_cast needs virtual functions. No virtual function in base = compile error. It returns nullptr on failure β€” always null-check it.

12

Default args: rightmost only. f(int a, int b=5) is valid. f(int a=5, int b) is a compile error.

13

priority_queue top = largest. For min-heap use greater<int> as third template arg. Never use begin()/end() on it.

14

lower_bound needs sorted data. Always sort before calling lower_bound, upper_bound, or binary_search.

🚀 Live C++ Compiler