Lecture 1 / 16
Lecture 01 · Basics

Introduction & Setup

What is C++?

C++ is a cross-platform, statically-typed, compiled, general-purpose programming language developed by Bjarne Stroustrup at Bell Labs in 1979 as an extension of the C language ("C with Classes"). It gives programmers a high level of control over system resources and memory.

Key Features of C++
  • Speed & Performance: Being compiled, it is extremely fast and efficient, used for game engines and operating systems.
  • Statically Typed: Variable types are checked at compile-time, catching errors early.
  • Object-Oriented: Full support for encapsulation, inheritance, and polymorphism.
  • Low-level Memory Access: Allows direct address manipulation using pointers.

Setting Up the Compiler

To compile and run C++ code, you need a C++ compiler. Popular options are:

  • GCC / G++: Standard for Linux and Windows (via MinGW).
  • Clang: Modern compiler toolchain standard on macOS.
  • MSVC: Included in Microsoft Visual Studio for Windows.

Structure of a C++ Program

Here is a basic C++ program that prints "Hello, World!" to the screen:

hello.cpp
#include <iostream>

int main() {
    std::cout << "Hello, World!" << std::endl;
    return 0;
}
🎯 Exercise 1

Install a compiler or open an online compiler. Copy, paste, compile, and run the "Hello, World!" program. Verify it prints the message correctly.

Lecture 02 · Basics

Variables & Data Types

Statically-Typed Variables

In C++, you must declare the type of a variable before using it. This is called static typing. Once declared, the type of a variable cannot change.

Primitive Data Types

  • int: Integers (whole numbers), e.g., int age = 20;
  • double / float: Floating-point numbers, e.g., double price = 99.99;
  • char: Single characters in single quotes, e.g., char grade = 'A';
  • bool: Boolean values (true or false).

Console I/O

C++ uses std::cout with the insertion operator (<<) to print data, and std::cin with the extraction operator (>>) to read user input.

variables.cpp
#include <iostream>
#include <string>

int main() {
    int age = 25;
    double score = 95.5;
    std::string name;

    std::cout << "Enter your name: ";
    std::cin >> name;

    std::cout << "Hello " << name << ", you are " << age << ".\n";
    return 0;
}
🎯 Exercise 2

Write a program that prompts the user to enter two decimals (representing length and width of a room), calculates the area, and prints the result.

Lecture 03 · Basics

Operators & Expressions

Standard Operators

C++ supports standard mathematical and logic operators:

  • Arithmetic: +, -, *, / (integer division if both operands are ints), % (modulus).
  • Increment / Decrement: ++x (pre-increment), x++ (post-increment).
  • Relational: ==, !=, <, >, <=, >=.
  • Logical: && (AND), || (OR), ! (NOT).
operators.cpp
#include <iostream>

int main() {
    int a = 10;
    int b = 3;
    
    int div = a / b;     // 3 (integer division)
    int rem = a % b;     // 1 (modulus)
    
    bool condition = (a > 5) && (b < 5); // true
    
    std::cout << "Div: " << div << ", Rem: " << rem << "\n";
    return 0;
}
🎯 Exercise 3

Write a C++ program that takes a temperature in Fahrenheit from the user, converts it to Celsius using the formula C = (F - 32) * 5/9, and prints the result. Make sure division doesn't truncate to 0!

Lecture 04 · Basics

Control Flow

Conditional Branching

C++ uses if, else if, and else statements to branch logic. All conditions must be enclosed in parentheses, and the corresponding code block is wrapped in curly braces {}.

Switch Statement

The switch statement is an alternative to long `if-else` chains. It tests a variable against multiple constant values (cases) and executes code based on the matched value. A break is required at the end of each case to prevent falling through to subsequent cases.

conditionals.cpp
#include <iostream>

int main() {
    int choice = 2;
    switch (choice) {
        case 1:
            std::cout << "Option 1 chosen.\n";
            break;
        case 2:
            std::cout << "Option 2 chosen.\n"; // Runs
            break;
        default:
            std::cout << "Invalid choice.\n";
    }
    return 0;
}
🎯 Exercise 4

Write a program that takes a student's numerical grade (0-100) and prints "Pass" if it is 60 or above, and "Fail" otherwise. Add validation to ensure the score is in the range 0 to 100.

Lecture 05 · Basics

Loops & Iteration

Loop Constructs

  • While Loop: Checks the condition *before* executing loop body.
  • Do-While Loop: Executes loop body *before* checking condition, guaranteeing the loop runs at least once.
  • For Loop: Bundles loop initialization, condition, and increment expression together, ideal for counted iterations.
loops.cpp
#include <iostream>

int main() {
    // For loop
    for (int i = 0; i < 5; i++) {
        if (i == 3) continue; // Skip 3
        std::cout << i << " "; // 0 1 2 4
    }
    std::cout << "\n";

    // While loop
    int count = 0;
    while (count < 3) {
        std::cout << "Count: " << count << "\n";
        count++;
    }
    return 0;
}
🎯 Exercise 5

Write a program that sums all odd numbers between 1 and 50 and outputs the final sum to the console.

Lecture 06 · Basics

Functions & Overloading

Functions

Functions represent reusable sub-procedures. A function must declare a return type, name, and parameters inside parentheses. If a function does not return a value, its return type is declared as void.

Parameters: Value vs. Reference

By default, arguments are passed **by value** (a copy is created). Passing **by reference** (appending & to the type) shares the original variable, allowing the function to modify it directly and avoiding expensive copies.

Function Overloading

C++ allows multiple functions in the same scope to share the same name as long as they have different parameter types or parameter counts.

functions.cpp
#include <iostream>

// Overloaded functions
int add(int x, int y) { return x + y; }
double add(double x, double y) { return x + y; }

// Pass by reference
void increment(int &num) {
    num++;
}

int main() {
    int val = 5;
    increment(val); // val is now 6
    std::cout << add(4, 5) << " and " << add(1.5, 2.5) << "\n";
    return 0;
}
🎯 Exercise 6

Write a function swap(int &a, int &b) that swaps the values of the two integer variables passed to it by reference. Test it inside a main block.

Lecture 07 · Memory & Pointers

Arrays & Vectors

Fixed-Size Arrays

An array is a collection of elements of the same type stored in contiguous memory locations. Arrays in C++ have a fixed size that must be known at compile time.

Dynamic Arrays (std::vector)

The Standard Template Library (STL) provides std::vector, which acts as a dynamic array. It automatically resizes itself when elements are added or deleted, and provides safe element additions via `push_back`.

arrays.cpp
#include <iostream>
#include <vector>

int main() {
    // Fixed array
    int numbers[3] = {10, 20, 30};

    // Dynamic vector
    std::vector<int> dynamic_nums;
    dynamic_nums.push_back(100);
    dynamic_nums.push_back(200);

    std::cout << "Vector size: " << dynamic_nums.size() << "\n";
    return 0;
}
🎯 Exercise 7

Create a std::vector<int>, ask the user to enter numbers until they type 0, and then print the average of the entered numbers.

Lecture 08 · Memory & Pointers

Pointers & References

Pointers

A pointer is a variable that stores the memory address of another variable. We declare pointers using the asterisk (*) syntax, and get memory addresses using the address-of operator (&). To read or write the value at a pointer's address, we **dereference** the pointer using the * operator.

References

A reference acts as an alias (an alternative name) for an existing variable. Once initialized, a reference cannot be bound to a different variable.

pointers.cpp
#include <iostream>

int main() {
    int num = 42;
    int* ptr = &num;      // ptr stores the address of num

    std::cout << ptr << "\n";  // Prints memory address (e.g. 0x7ffeef...)
    std::cout << *ptr << "\n"; // Dereferences ptr to print 42

    *ptr = 100;                // Changes num to 100
    std::cout << num << "\n";  // Prints 100
    return 0;
}
🎯 Exercise 8

Write a program that declares an integer, a pointer to that integer, and a pointer to that pointer. Print the value of the integer using the double pointer.

Lecture 09 · Advanced Concepts

OOP: Classes & Objects

Classes and Access Specifiers

A class is a user-defined blueprint for creating objects. It contains members (attributes and functions) grouped under access specifiers:

  • public: Members are accessible from outside the class.
  • private: Members are accessible only within the class itself (encapsulation).

Constructors and Destructors

A constructor initializes class instances, and a destructor performs cleanup when objects are destroyed (out of scope or deleted).

oop_basics.cpp
#include <iostream>
#include <string>

class Student {
private:
    std::string name;
    int roll;

public:
    // Constructor
    Student(std::string n, int r) : name(n), roll(r) {}

    void display() {
        std::cout << "Student: " << name << ", Roll: " << roll << "\n";
    }
};

int main() {
    Student s1("Alice", 101);
    s1.display();
    return 0;
}
🎯 Exercise 9

Define a class Rectangle with private attributes width and height. Provide a constructor, getter/setter methods, and a public method getArea().

Lecture 10 · Advanced Concepts

OOP: Inheritance & Poly

Inheritance

Inheritance lets subclass definitions inherit members from parent base classes. Classes in C++ inherit publicly by default when using class inheritance notation: class Derived : public Base.

Virtual Functions and Polymorphism

To enable runtime polymorphism (method overriding), we mark the base class method as virtual. This ensures C++ invokes the derived version of the method when accessed through pointers or references to the base class.

polymorphism.cpp
#include <iostream>

class Animal {
public:
    virtual void speak() {
        std::cout << "Generic sound.\n";
    }
};

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

int main() {
    Animal* my_animal = new Dog();
    my_animal->speak(); // Outputs: Woof!
    delete my_animal;
    return 0;
}
🎯 Exercise 10

Create a base class Printer with a virtual method print(). Create subclasses LaserPrinter and InkJetPrinter that override the print method. Call them using base pointers.

Lecture 11 · Advanced Concepts

File Streams (I/O)

File Input and Output

C++ uses stream classes inside the <fstream> library to manipulate files:

  • std::ofstream: Write stream to create and write data to files.
  • std::ifstream: Read stream to read data from files.
  • std::fstream: Combined file stream to read and write.
files.cpp
#include <iostream>
#include <fstream>
#include <string>

int main() {
    // Write
    std::ofstream out("log.txt");
    out << "C++ File Handling\n";
    out.close();

    // Read
    std::ifstream in("log.txt");
    std::string line;
    if (in.is_open()) {
        while (std::getline(in, line)) {
            std::cout << line << "\n";
        }
        in.close();
    }
    return 0;
}
🎯 Exercise 11

Write a program that opens a file called numbers.txt, writes the numbers 1 to 10 in it (one per line), closes the file, and then reopens it to read and sum all the values.

Lecture 12 · Advanced Concepts

Exception Handling

Throw, Try, and Catch

Errors at runtime are handled using C++ exception handling keywords:

  • throw: Signals an error condition (throws an object or primitive).
  • try: Surrounds code blocks that could fail.
  • catch: Catches thrown exceptions and handles them.
exceptions.cpp
#include <iostream>
#include <stdexcept>

double divide(double a, double b) {
    if (b == 0.0) {
        throw std::runtime_error("Division by zero!");
    }
    return a / b;
}

int main() {
    try {
        double result = divide(10, 0);
        std::cout << result << "\n";
    } catch (const std::runtime_error &e) {
        std::cerr << "Error caught: " << e.what() << "\n";
    }
    return 0;
}
🎯 Exercise 12

Write a program that takes an age from the user. Throw an invalid argument exception if the age is negative or greater than 150, and handle it gracefully.

Lecture 13 · Advanced Concepts

Smart Pointers

Memory Management and smart pointers

Traditional C++ uses raw pointers via new and delete, which easily leads to memory leaks if delete calls are missed. Modern C++ (C++11+) introduces smart pointers in the <memory> header to handle deletion automatically:

  • std::unique_ptr: Owns dynamically allocated memory uniquely; cannot be copied, only moved.
  • std::shared_ptr: Keeps a reference count; deletes memory when the last shared_ptr goes out of scope.
smart_pointers.cpp
#include <iostream>
#include <memory>

class Resource {
public:
    Resource() { std::cout << "Resource acquired.\n"; }
    ~Resource() { std::cout << "Resource released.\n"; }
};

int main() {
    {
        // Automatically deleted when block scope ends
        std::unique_ptr<Resource> ptr = std::make_unique<Resource>();
    } // Outputs: Resource released here.
    return 0;
}
🎯 Exercise 13

Convert a program that allocates an array of 5 integers dynamically using raw pointers to use a std::unique_ptr<int[]> instead. Verify that no delete is required.

Lecture 14 · Advanced Concepts

Modern C++ Features

Modern Syntax features

Modern C++ introduces syntactic sugar and performance improvements:

  • auto: Automatic type deduction, letting the compiler infer types.
  • Range-Based For Loops: Iterates easily over containers (like python's syntax).
  • Lambda Expressions: Anonymous functions defined directly inside expressions.
modern_cpp.cpp
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> nums = {1, 2, 3};

    // auto type inference & range loop
    for (auto num : nums) {
        std::cout << num << " ";
    }
    std::cout << "\n";

    // Lambda expression
    auto square = [](int x) { return x * x; };
    std::cout << "Square of 5: " << square(5) << "\n";
    return 0;
}
🎯 Exercise 14

Use std::for_each and a lambda function to double every value in a std::vector<int> and print the results.

Lecture 15 · Advanced Concepts

STL Containers & Algo

Associative Containers

  • std::map: Key-value container implemented as a balanced BST (sorted keys).
  • std::set: Container representing a sorted collection of unique values.

Algorithms

The <algorithm> header provides generic operations for search, sort, count, and manipulation of ranges.

stl.cpp
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>

int main() {
    // Map usage
    std::map<std::string, int> ages;
    ages["Bob"] = 21;
    ages["Alice"] = 20;

    // Sorting a vector
    std::vector<int> vals = {4, 1, 3, 2};
    std::sort(vals.begin(), vals.end()); // sorts to {1, 2, 3, 4}

    std::cout << "Sorted first: " << vals[0] << "\n";
    return 0;
}
🎯 Exercise 15

Create a program that takes names and scores for 5 students, saves them in a std::map<std::string, int>, and displays the student with the highest score.

Lecture 16 · Advanced Concepts

Final Capstone Project

Project: OOP Student Records Database

Apply everything you have learned in this course to build a C++ Student Database CLI Application. The project requires files, exceptions, STL classes, vectors, and encapsulation.

Project Requirements:

  1. Student Class: Contains private attributes: Name, ID, GPA, and a list of courses. Add public getters/setters.
  2. Database Class: Manages a collection of Student objects inside a std::vector or std::map.
  3. File Persistence: Write database contents to a text file (records.txt) when saving, and read records on startup.
  4. Interactive Menu: Provide options to:
    • Add new student record
    • Display all student records
    • Search student record by ID
    • Delete student record
    • Save data and Exit
  5. Exception safety: Handle cases where duplicate IDs are added or non-numeric grades are entered.
project_stub.cpp
#include <iostream>
#include <vector>
#include <string>

class Student {
private:
    std::string name;
    int id;
    double gpa;

public:
    Student(std::string n, int i, double g) : name(n), id(i), gpa(g) {}
    int getId() const { return id; }
    void print() const {
        std::cout << "ID: " << id << " | " << name << " (GPA: " << gpa << ")\n";
    }
};

// Implement Database and main menu loop
🎯 Final Challenge

Write the complete application in a file named records.cpp. Compile, run, and test it, verifying records are correctly loaded from and saved to the text file.