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.
- 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:
#include <iostream>
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}
Install a compiler or open an online compiler. Copy, paste, compile, and run the "Hello, World!" program. Verify it prints the message correctly.
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 (trueorfalse).
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.
#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;
}
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.
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).
#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;
}
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!
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.
#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;
}
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.
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.
#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;
}
Write a program that sums all odd numbers between 1 and 50 and outputs the final sum to the console.
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.
#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;
}
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.
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`.
#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;
}
Create a std::vector<int>, ask the user to enter numbers until they type 0, and then print the average of the entered numbers.
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.
#include <iostream>
int main() {
int num = 42;
int* ptr = # // 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;
}
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.
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).
#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;
}
Define a class Rectangle with private attributes width and height. Provide a constructor, getter/setter methods, and a public method getArea().
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.
#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;
}
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.
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.
#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;
}
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.
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.
#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;
}
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.
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.
#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;
}
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.
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.
#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;
}
Use std::for_each and a lambda function to double every value in a std::vector<int> and print the results.
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.
#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;
}
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.
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:
- Student Class: Contains private attributes: Name, ID, GPA, and a list of courses. Add public getters/setters.
- Database Class: Manages a collection of Student objects inside a
std::vectororstd::map. - File Persistence: Write database contents to a text file (
records.txt) when saving, and read records on startup. - 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
- Exception safety: Handle cases where duplicate IDs are added or non-numeric grades are entered.
#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
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.