๐ Search Course Content
C++ Programming
Complete Course
Basics ยท OOP ยท STL ยท Data Structures ยท Advanced Concepts โ Complete Guide in Easy English
๐ Table of Contents โ 15 Units
Introduction to C++ Programming
Understanding C++ language, its history, features, and basic program structure
What is C++?
C++ is a powerful, high-performance programming language that supports both procedural and object-oriented programming (OOP). It was developed by Bjarne Stroustrup at Bell Labs in 1979 as an extension of the C programming language.
History of C++
- 1979: Bjarne Stroustrup starts work on "C with Classes"
- 1983: Renamed to C++
- 1985: First commercial release
- 1998: C++98 (First ISO Standard)
- 2011: C++11 (Major update with modern features)
- 2014: C++14 (Bug fixes & improvements)
- 2017: C++17 (New features)
- 2020: C++20 (Latest standard with modules, concepts)
Features of C++
Detailed Features:
- Object-Oriented: Supports classes, objects, inheritance, polymorphism, encapsulation
- Fast & Efficient: Compiles to machine code, no runtime overhead
- Portable: Write once, compile anywhere (with recompilation)
- Rich Standard Library: STL (containers, algorithms, iterators)
- Pointers: Direct memory access & manipulation
- Multi-paradigm: Procedural, OOP, Generic, Functional programming
- Case-Sensitive:
Variableandvariableare different
Advantages of C++
| Advantage | Explanation |
|---|---|
| High Performance | Compiles to native code, no interpreter overhead, close to hardware |
| Memory Control | Manual memory management with new/delete, pointers for precise control |
| OOP Support | Code reusability, modularity, easier maintenance through classes & objects |
| Large Community | Extensive resources, libraries, frameworks, help available |
| Industry Standard | Used in game dev, system software, embedded systems, competitive programming |
| Backward Compatible | Most C code works in C++, easy migration |
| STL | Ready-made data structures & algorithms (vectors, maps, sort, search) |
Disadvantages of C++
| Disadvantage | Explanation |
|---|---|
| Complex Syntax | Steeper learning curve than Python, Java due to pointers, templates, multiple paradigms |
| Manual Memory Management | Programmer must handle memory allocation/deallocation, risk of memory leaks |
| No Garbage Collection | Unlike Java/C#, no automatic memory cleanup (modern C++ has smart pointers) |
| Security Issues | Buffer overflows, pointer errors can cause crashes or security vulnerabilities |
| Longer Compilation | Large projects take time to compile compared to interpreted languages |
| Platform-Specific Code | Some features are OS-dependent, need recompilation for different platforms |
C vs C++
| Feature | C | C++ |
|---|---|---|
| Paradigm | Procedural | Procedural + OOP + Generic |
| Focus | Functions | Classes & Objects |
| OOP Support | โ No | โ Yes (classes, inheritance, polymorphism) |
| Data Security | Less (no encapsulation) | More (private/public access control) |
| Overloading | โ No function overloading | โ Function & operator overloading |
| References | โ No | โ Yes |
| Exception Handling | โ No (use error codes) | โ try-catch blocks |
| Templates | โ No | โ Generic programming |
| STL | โ No | โ Rich library (vector, map, etc.) |
| File Extension | .c | .cpp, .cc, .cxx |
Applications of C++
- Operating Systems: Windows, Linux, macOS (parts written in C++)
- Game Development: Unreal Engine, Unity (backend), AAA games
- Web Browsers: Chrome (V8 engine), Firefox, Safari
- Database Systems: MySQL, PostgreSQL, MongoDB
- Embedded Systems: IoT devices, automotive software, medical devices
- Graphics & Animation: Adobe products, Autodesk Maya, 3D rendering
- Compilers: GCC, Clang (written in C++)
- Scientific Computing: Simulation software, numerical analysis
- Financial Systems: Trading platforms, banking software (speed critical)
- Competitive Programming: Codeforces, LeetCode, ACM ICPC
Basic C++ Program Structure
// My First C++ Program #include <iostream> // Preprocessor directive (include header file) using namespace std; // Use standard namespace int main() { // Main function - program entry point cout << "Hello, World!"; // Output to console return 0; // Return 0 indicates successful execution }
Line-by-Line Explanation:
#include <iostream>: Includes input/output stream library for cin, coutusing namespace std;: Tells compiler to use standard namespace (so we can writecoutinstead ofstd::cout)int main(): Main function where program execution begins. Returns integer (0 = success)cout << "Hello, World!";: Prints text to console.<<is insertion operatorreturn 0;: Returns 0 to operating system (indicates program ran successfully)- Semicolon (;): Statement terminator in C++
- Curly Braces { }: Define code blocks (function body)
Compilation Process
C++ is a compiled language. Your code goes through multiple stages:
Compilation Process Flow Source Code (.cpp) โ Preprocessing (#include, #define expanded) โ Compilation (converts to assembly code) โ Assembly (converts to machine code .obj/.o) โ Linking (links with libraries, creates .exe) โ Executable File (.exe on Windows, no extension on Linux)
Common Compilers:
- GCC (g++): GNU Compiler Collection (Linux, macOS, Windows via MinGW)
- Clang: LLVM-based compiler (faster compilation, better error messages)
- MSVC: Microsoft Visual C++ (Windows, Visual Studio)
- Intel C++: Optimized for Intel processors
Compiling from Command Line:
// Compile with g++ g++ program.cpp -o program.exe // Run the program ./program.exe (Windows) ./program (Linux/Mac)
Input & Output in C++
Output using cout:
#include <iostream> using namespace std; int main() { cout << "Hello World"; // Print text cout << "Welcome to C++"; // On same line cout << endl; // New line // Multiple outputs cout << "Name: " << "Ali" << endl; cout << "Age: " << 20 << endl; // Using \n for new line cout << "Line 1\n"; cout << "Line 2\n"; return 0; }
Input using cin:
#include <iostream> using namespace std; int main() { int age; string name; cout << "Enter your name: "; cin >> name; // Input operator cout << "Enter your age: "; cin >> age; cout << "Name: " << name << endl; cout << "Age: " << age << endl; return 0; }
Comments in C++
// Single-line comment (use // for one line) /* Multi-line comment Use /* ... */ for multiple lines Everything between /* and */ is ignored by compiler */ int x = 10; // You can add comments after code too // Comments are important for: // 1. Code documentation // 2. Explaining complex logic // 3. Temporarily disabling code during testing
C++ IDEs & Text Editors
| Tool | Type | Platform | Best For |
|---|---|---|---|
| Visual Studio | IDE | Windows | Professional development, debugging |
| VS Code | Editor | All | Lightweight, extensions, modern UI |
| Code::Blocks | IDE | All | Beginners, free, simple |
| CLion | IDE | All | Professional, paid, intelligent code completion |
| Dev-C++ | IDE | Windows | Beginners (outdated but simple) |
| Eclipse CDT | IDE | All | Large projects, Java devs familiar |
| Sublime Text | Editor | All | Fast, lightweight, customizable |
| Vim/Neovim | Editor | All | Advanced users, terminal-based |
Writing Your First Program
Example: Simple Calculator
#include <iostream> using namespace std; int main() { int num1, num2, sum; cout << "Enter first number: "; cin >> num1; cout << "Enter second number: "; cin >> num2; sum = num1 + num2; cout << "Sum = " << sum << endl; return 0; }
Output:
Enter first number: 15 Enter second number: 25 Sum = 40
Data Types & Variables
Understanding different types of data and how to store them in memory
What is a Variable?
A variable is a named storage location in memory that holds a value. Think of it as a labeled box where you can store data and retrieve it later.
int age = 25; // Variable 'age' stores integer 25 string name = "Ali"; // Variable 'name' stores string "Ali"
Variable Naming Rules:
- Must start with letter (a-z, A-Z) or underscore (_)
- Can contain letters, digits (0-9), underscores
- Cannot use C++ keywords (int, if, while, etc.)
- Case-sensitive (
Ageandageare different) - No spaces allowed
- Good Practice: Use meaningful names (age, studentName) not (a, x, temp)
Valid vs Invalid Variable Names:
| Valid โ | Invalid โ | Reason |
|---|---|---|
| age | 2age | Cannot start with digit |
| student_name | student-name | Hyphen not allowed |
| _temp | temp value | Space not allowed |
| total123 | int | 'int' is a keyword |
| myVar | my$Var | $ not allowed |
Data Types in C++
Data types specify what kind of value a variable can hold and how much memory it occupies.
1. Fundamental (Built-in) Data Types:
| Type | Size (bytes) | Range | Example |
|---|---|---|---|
| int | 4 | -2,147,483,648 to 2,147,483,647 | int age = 25; |
| short | 2 | -32,768 to 32,767 | short marks = 95; |
| long | 4 or 8 | Very large integers | long population = 220000000; |
| long long | 8 | -9 quintillion to 9 quintillion | long long big = 9000000000; |
| float | 4 | ยฑ3.4 ร 1038 (6-7 digits precision) | float pi = 3.14f; |
| double | 8 | ยฑ1.7 ร 10308 (15-16 digits) | double price = 1599.99; |
| char | 1 | -128 to 127 (or 0 to 255 unsigned) | char grade = 'A'; |
| bool | 1 | true (1) or false (0) | bool isStudent = true; |
Type Modifiers
Modifiers change the range and behavior of data types:
- signed: Can store positive and negative (default for int, char)
- unsigned: Only positive values (doubles the positive range)
- short: Reduces size (short int)
- long: Increases size (long int, long double)
unsigned int rollNo = 12345; // Only positive, 0 to 4,294,967,295 signed int temperature = -10; // Can be negative long long bigNumber = 9876543210; // Very large number unsigned char letter = 255; // 0 to 255 range
Integer Types Examples
#include <iostream> using namespace std; int main() { int age = 20; short marks = 95; long population = 220000000; unsigned int rollNo = 12345; cout << "Age: " << age << endl; cout << "Marks: " << marks << endl; cout << "Population: " << population << endl; cout << "Roll No: " << rollNo << endl; return 0; }
Floating-Point Types
| Type | Precision | When to Use |
|---|---|---|
| float | 6-7 digits | Graphics, games (less precision needed, saves memory) |
| double | 15-16 digits | Scientific calculations, financial data (default choice) |
| long double | 18-19 digits | Very high precision calculations |
float pi = 3.14159f; // Note the 'f' suffix for float double price = 1599.99; // More precise long double precise = 3.141592653589793238; cout << "Pi (float): " << pi << endl; // 3.14159 cout << "Price (double): " << price << endl; // 1599.99
Character Type (char)
Stores single character in single quotes.
char grade = 'A'; char symbol = '$'; char digit = '5'; // Character '5', not integer 5 cout << grade << endl; // Output: A // Characters are stored as ASCII values (integers) cout << (int)grade << endl; // Output: 65 (ASCII of 'A')
Common ASCII Values:
- 'A' to 'Z': 65 to 90
- 'a' to 'z': 97 to 122
- '0' to '9': 48 to 57
- Space: 32
- Newline '\n': 10
Boolean Type (bool)
Stores logical values: true or false.
bool isStudent = true; bool hasPassed = false; bool isAdult = (age >= 18); // Result of comparison cout << isStudent << endl; // Output: 1 (true = 1, false = 0) cout << hasPassed << endl; // Output: 0 // Use boolalpha to print true/false instead of 1/0 cout << boolalpha << isStudent << endl; // Output: true
String Type
Stores sequence of characters (text). Not a fundamental type, it's a class from C++ Standard Library.
#include <iostream> #include <string> // Must include string header using namespace std; int main() { string name = "Ali Ahmed"; string city = "Lahore"; cout << "Name: " << name << endl; cout << "City: " << city << endl; // String concatenation string fullInfo = name + " from " + city; cout << fullInfo << endl; // Ali Ahmed from Lahore return 0; }
Type Conversion (Casting)
1. Implicit Conversion (Automatic):
int x = 10; double y = x; // int automatically converted to double (10.0) float a = 3.14f; int b = a; // float to int (data loss: b = 3)
2. Explicit Conversion (Manual Casting):
// C-style cast double pi = 3.14159; int intPi = (int)pi; // intPi = 3 // C++ style cast (preferred) int intPi2 = static_cast<int>(pi); // More readable, safer // Character to integer char ch = 'A'; int ascii = (int)ch; // ascii = 65
Type Conversion Rules:
- Widening (Safe): char โ int โ long โ float โ double (no data loss)
- Narrowing (Risky): double โ float โ long โ int โ char (data loss possible)
- Integer Division: 7/2 = 3 (not 3.5), use 7.0/2 or cast one operand to double
Constants
Values that cannot be changed after initialization.
// Using const keyword const int MAX_AGE = 100; const double PI = 3.14159; // Using #define (preprocessor directive - old style) #define MAX_SIZE 1000 #define TAX_RATE 0.16 // Trying to change const gives error // MAX_AGE = 50; // ERROR: Cannot modify const
const vs #define:
| Feature | const | #define |
|---|---|---|
| Type Safety | โ Type-checked by compiler | โ No type checking (text replacement) |
| Scope | โ Follows scope rules | โ Global (file-wide) |
| Debugging | โ Easier to debug | โ Harder (preprocessor replaces text) |
| Memory | Occupies memory | No memory (text substitution) |
| Recommendation | โ Use this (modern C++) | โ Avoid (legacy) |
sizeof() Operator
Returns size of data type or variable in bytes.
#include <iostream> using namespace std; int main() { cout << "Size of int: " << sizeof(int) << " bytes" << endl; cout << "Size of double: " << sizeof(double) << " bytes" << endl; cout << "Size of char: " << sizeof(char) << " bytes" << endl; cout << "Size of bool: " << sizeof(bool) << " bytes" << endl; int arr[10]; cout << "Size of array: " << sizeof(arr) << " bytes" << endl; // 40 bytes (10ร4) return 0; }
Control Structures
Decision making and flow control using if-else, switch, and loops
What are Control Structures?
Control structures determine the order in which statements are executed. They allow programs to make decisions, repeat actions, and choose different paths based on conditions.
Types:
- Sequential: Statements execute one after another (default)
- Selection/Decision: if, if-else, nested if, switch
- Iteration/Loops: for, while, do-while
- Jump: break, continue, goto, return
1. if Statement
Executes code block only if condition is true.
int age = 20; if (age >= 18) { cout << "You are an adult" << endl; } // If condition false, this block is skipped
2. if-else Statement
int marks = 55; if (marks >= 50) { cout << "Pass" << endl; } else { cout << "Fail" << endl; }
3. if-else if-else Ladder
int marks = 75; if (marks >= 80) { cout << "Grade: A" << endl; } else if (marks >= 70) { cout << "Grade: B" << endl; } else if (marks >= 60) { cout << "Grade: C" << endl; } else if (marks >= 50) { cout << "Grade: D" << endl; } else { cout << "Grade: F (Fail)" << endl; }
4. Nested if
int age = 25; bool hasLicense = true; if (age >= 18) { if (hasLicense) { cout << "You can drive" << endl; } else { cout << "Get a license first" << endl; } } else { cout << "You are too young to drive" << endl; }
Relational Operators
| Operator | Meaning | Example | Result |
|---|---|---|---|
| == | Equal to | 5 == 5 | true |
| != | Not equal to | 5 != 3 | true |
| > | Greater than | 5 > 3 | true |
| < | Less than | 5 < 3 | false |
| >= | Greater than or equal | 5 >= 5 | true |
| <= | Less than or equal | 5 <= 3 | false |
Logical Operators
| Operator | Meaning | Example | Result |
|---|---|---|---|
| && | AND (both must be true) | true && false | false |
| || | OR (at least one true) | true || false | true |
| ! | NOT (inverts boolean) | !true | false |
int age = 25; bool isStudent = true; // AND: Both conditions must be true if (age >= 18 && isStudent) { cout << "Adult student discount available" << endl; } // OR: At least one condition must be true if (age < 18 || age > 60) { cout << "Special discount" << endl; } // NOT: Inverts the condition if (!isStudent) { cout << "Regular price" << endl; }
5. switch Statement
Multi-way branch based on value of expression. Cleaner than long if-else ladder for checking single variable against multiple values.
int day = 3; switch (day) { case 1: cout << "Monday" << endl; break; case 2: cout << "Tuesday" << endl; break; case 3: cout << "Wednesday" << endl; break; case 4: cout << "Thursday" << endl; break; case 5: cout << "Friday" << endl; break; case 6: cout << "Saturday" << endl; break; case 7: cout << "Sunday" << endl; break; default: cout << "Invalid day" << endl; }
switch vs if-else:
| Feature | switch | if-else |
|---|---|---|
| Use Case | Single variable, multiple exact values | Complex conditions, ranges |
| Performance | Faster (jump table) | Slower (checks each condition) |
| Readability | Cleaner for many values | Better for complex logic |
| Data Types | int, char, enum only | Any type, any comparison |
| Ranges | โ Cannot check ranges | โ Can check ranges (age > 18) |
Loops (Iteration)
Repeat a block of code multiple times.
1. for Loop
Used when number of iterations is known.
// Print numbers 1 to 10 for (int i = 1; i <= 10; i++) { cout << i << " "; } cout << endl; // Output: 1 2 3 4 5 6 7 8 9 10 // Syntax: for (initialization; condition; increment/decrement)
for Loop Explained:
- Initialization:
int i = 1(executed once at start) - Condition:
i <= 10(checked before each iteration) - Increment:
i++(executed after each iteration)
// Print even numbers from 2 to 20 for (int i = 2; i <= 20; i += 2) { cout << i << " "; } // Print numbers in reverse for (int i = 10; i >= 1; i--) { cout << i << " "; }
2. while Loop
Repeats while condition is true. Condition checked before each iteration.
int i = 1; while (i <= 5) { cout << i << " "; i++; } // Output: 1 2 3 4 5
3. do-while Loop
Executes at least once, then repeats while condition is true. Condition checked after each iteration.
int i = 1; do { cout << i << " "; i++; } while (i <= 5); // Output: 1 2 3 4 5 // Executes at least once even if condition false int x = 10; do { cout << "This prints once" << endl; } while (x < 5); // Condition false, but body executed once
Loop Comparison:
| Loop | When to Use | Condition Check |
|---|---|---|
| for | Known iterations (print 1-10, iterate array) | Before each iteration |
| while | Unknown iterations (read until EOF, user says "quit") | Before each iteration |
| do-while | Must execute at least once (menu, input validation) | After each iteration |
Nested Loops
Loop inside another loop.
// Print multiplication table (1 to 5) for (int i = 1; i <= 5; i++) { for (int j = 1; j <= 10; j++) { cout << i << " x " << j << " = " << (i*j) << endl; } cout << endl; } // Print pattern /* * ** *** **** ***** */ for (int i = 1; i <= 5; i++) { for (int j = 1; j <= i; j++) { cout << "*"; } cout << endl; }
break Statement
Exits the loop immediately.
// Find first number divisible by 7 and 3 for (int i = 1; i <= 100; i++) { if (i % 7 == 0 && i % 3 == 0) { cout << "Found: " << i << endl; break; // Exit loop } } // Output: Found: 21
continue Statement
Skips current iteration, continues with next.
// Print odd numbers from 1 to 10 for (int i = 1; i <= 10; i++) { if (i % 2 == 0) { continue; // Skip even numbers } cout << i << " "; } // Output: 1 3 5 7 9
Functions in C++
Modular programming using functions for code reusability and organization
What is a Function?
A function is a self-contained block of code that performs a specific task. It can be called multiple times, making code reusable, organized, and easier to maintain.
Advantages of Functions
Function Syntax
// Function Definition returnType functionName(parameters) { // Function body (code to execute) return value; // Optional (not needed for void) } // Example: int add(int a, int b) { int sum = a + b; return sum; }
Components:
- Return Type: Data type of value returned (int, float, void, etc.)
- Function Name: Identifier (follow variable naming rules)
- Parameters: Input values (optional). Also called formal parameters
- Function Body: Code inside { }
- return Statement: Returns value to caller (not needed for void)
Types of Functions
1. No Arguments, No Return Value
void greet() { cout << "Hello, World!" << endl; } int main() { greet(); // Function call return 0; }
2. No Arguments, With Return Value
int getRandomNumber() { return 42; } int main() { int num = getRandomNumber(); cout << "Number: " << num << endl; return 0; }
3. With Arguments, No Return Value
void printSum(int a, int b) { cout << "Sum: " << (a + b) << endl; } int main() { printSum(5, 10); // Output: Sum: 15 return 0; }
4. With Arguments, With Return Value
int multiply(int a, int b) { return a * b; } int main() { int result = multiply(4, 5); cout << "Result: " << result << endl; // Output: 20 return 0; }
Function Declaration vs Definition
Declaration (Prototype): Tells compiler about function (name, return type, parameters)
Definition: Actual implementation of function
#include <iostream> using namespace std; // Function Declaration (Prototype) - placed before main int add(int, int); // Parameter names optional in declaration int main() { int result = add(5, 3); cout << "Sum: " << result << endl; return 0; } // Function Definition - can be placed after main int add(int a, int b) { return a + b; }
Function Call
Three ways to pass arguments to functions:
1. Call by Value (Default)
Copies value to function. Original variable unchanged.
void increment(int x) { x = x + 1; cout << "Inside function: " << x << endl; // 11 } int main() { int num = 10; increment(num); cout << "Outside function: " << num << endl; // Still 10 (unchanged) return 0; }
2. Call by Reference
Passes address of variable. Changes affect original variable.
void increment(int &x) { // & means reference x = x + 1; cout << "Inside function: " << x << endl; // 11 } int main() { int num = 10; increment(num); cout << "Outside function: " << num << endl; // 11 (changed!) return 0; }
3. Call by Pointer
void increment(int *x) { // * means pointer *x = *x + 1; cout << "Inside function: " << *x << endl; // 11 } int main() { int num = 10; increment(&num); // Pass address cout << "Outside function: " << num << endl; // 11 (changed!) return 0; }
| Method | Syntax | Changes Original? | Use When |
|---|---|---|---|
| Call by Value | int x | โ No | Small data, don't need to modify original |
| Call by Reference | int &x | โ Yes | Need to modify original, avoid copying large data |
| Call by Pointer | int *x | โ Yes | Dynamic memory, arrays, null checking needed |
Default Arguments
Provide default values for parameters. If argument not passed, default used.
int power(int base, int exp = 2) { // exp defaults to 2 int result = 1; for(int i = 0; i < exp; i++) { result *= base; } return result; } int main() { cout << power(5) << endl; // 25 (5^2, uses default) cout << power(5, 3) << endl; // 125 (5^3, overrides default) return 0; }
Rules:
- Default arguments must be rightmost parameters
- Once a parameter has default value, all right parameters must also have defaults
- Defaults specified in declaration, not definition (if separate)
Function Overloading
Multiple functions with same name but different parameters (number, type, or order).
int add(int a, int b) { return a + b; } double add(double a, double b) { return a + b; } int add(int a, int b, int c) { return a + b + c; } int main() { cout << add(5, 3) << endl; // Calls first (int version): 8 cout << add(5.5, 3.2) << endl; // Calls second (double version): 8.7 cout << add(1, 2, 3) << endl; // Calls third (3 params): 6 return 0; }
Overloading Rules:
- Parameters must differ in number, type, or order
- Return type alone cannot differentiate overloaded functions
- Compiler chooses function based on arguments passed
Inline Functions
Request compiler to insert function code at call site (instead of jumping to function). Reduces function call overhead for small functions.
inline int square(int x) { return x * x; } int main() { cout << square(5) << endl; // Compiler replaces with: cout << 5 * 5; return 0; }
Advantages: Faster execution (no function call overhead)
Disadvantages: Increases code size if function called many times
Use for: Small, frequently called functions (getters, setters)
Recursion
Function calling itself. Useful for problems that can be broken into similar subproblems.
// Factorial using recursion int factorial(int n) { if (n == 0 || n == 1) { return 1; // Base case } return n * factorial(n - 1); // Recursive call } int main() { cout << factorial(5) << endl; // 120 (5! = 5ร4ร3ร2ร1) return 0; }
Recursion Requirements:
- Base Case: Condition to stop recursion (avoid infinite loop)
- Recursive Case: Function calls itself with modified parameter
- Progress: Each call moves toward base case
Example: Fibonacci Series
int fibonacci(int n) { if (n == 0) return 0; // Base case 1 if (n == 1) return 1; // Base case 2 return fibonacci(n-1) + fibonacci(n-2); // Recursive } int main() { for(int i = 0; i < 10; i++) { cout << fibonacci(i) << " "; } // Output: 0 1 1 2 3 5 8 13 21 34 return 0; }
Recursion vs Iteration:
| Aspect | Recursion | Iteration (Loop) |
|---|---|---|
| Code | Shorter, elegant | Longer sometimes |
| Readability | Natural for tree/graph problems | Better for simple repetition |
| Memory | More (stack frames for each call) | Less |
| Speed | Slower (function call overhead) | Faster |
| Stack Overflow | Risk if too many calls | No risk |
| Use When | Tree traversal, divide & conquer, mathematical functions | Simple repetition, performance critical |
Object-Oriented Programming (OOP) Basics
Understanding classes, objects, encapsulation, and constructors/destructors
What is OOP?
Object-Oriented Programming (OOP) is a programming paradigm based on the concept of "objects" that contain data (attributes) and code (methods). It models real-world entities as objects.
OOP vs Procedural Programming
| Aspect | Procedural (C) | Object-Oriented (C++) |
|---|---|---|
| Focus | Functions/procedures | Objects (data + functions together) |
| Data Security | Less (global data accessible) | More (encapsulation, private data) |
| Reusability | Limited | High (inheritance, polymorphism) |
| Real-world Modeling | Difficult | Easy (objects represent real entities) |
| Maintenance | Harder for large projects | Easier (modularity) |
| Example | C language | C++, Java, Python |
Four Pillars of OOP
Class & Object
Class: Blueprint/template for creating objects. Defines structure and behavior.
Object: Instance of a class. Actual entity created from class blueprint.
// Class Definition class Car { public: // Access specifier // Data members (attributes/properties) string brand; string model; int year; // Member functions (methods/behaviors) void displayInfo() { cout << "Brand: " << brand << endl; cout << "Model: " << model << endl; cout << "Year: " << year << endl; } }; int main() { // Creating objects (instances of class) Car car1; // Object 1 Car car2; // Object 2 // Accessing members using dot operator car1.brand = "Toyota"; car1.model = "Corolla"; car1.year = 2023; car2.brand = "Honda"; car2.model = "Civic"; car2.year = 2022; car1.displayInfo(); car2.displayInfo(); return 0; }
Analogy:
- Class = Cookie Cutter: Design/template
- Object = Cookie: Actual item created from template
- One cookie cutter (class) can make many cookies (objects)
Access Specifiers
Control visibility of class members (data & functions).
| Specifier | Access From Class | Access From Outside | Access From Derived Class |
|---|---|---|---|
| public | โ Yes | โ Yes | โ Yes |
| private | โ Yes | โ No | โ No |
| protected | โ Yes | โ No | โ Yes |
class Student { private: // Accessible only within class int rollNo; string name; public: // Accessible from anywhere // Setter methods (to set private data) void setData(int r, string n) { rollNo = r; name = n; } // Getter methods (to get private data) void displayData() { cout << "Roll No: " << rollNo << endl; cout << "Name: " << name << endl; } }; int main() { Student s1; // s1.rollNo = 101; // ERROR: rollNo is private s1.setData(101, "Ali"); // Use public method to set private data s1.displayData(); return 0; }
Why private members?
- Data Hiding: Protect data from accidental modification
- Validation: Control how data is set (e.g., age can't be negative)
- Flexibility: Change internal implementation without affecting outside code
Encapsulation
Wrapping data (variables) and code (methods) together as a single unit. Achieved using classes.
class BankAccount { private: double balance; // Hidden from outside public: // Constructor BankAccount(double initialBalance) { balance = initialBalance; } // Controlled access through methods void deposit(double amount) { if(amount > 0) { balance += amount; cout << "Deposited: " << amount << endl; } } void withdraw(double amount) { if(amount > 0 && amount <= balance) { balance -= amount; cout << "Withdrawn: " << amount << endl; } else { cout << "Insufficient balance!" << endl; } } void checkBalance() { cout << "Balance: " << balance << endl; } }; int main() { BankAccount acc(1000); // Initial balance 1000 acc.deposit(500); acc.withdraw(200); acc.checkBalance(); // 1300 // Can't directly access balance: acc.balance = 0; (ERROR) return 0; }
Constructors
Special member function automatically called when object is created. Used to initialize object.
Types of Constructors:
1. Default Constructor (No parameters)
class Box { public: int length; // Default Constructor Box() { length = 0; cout << "Default Constructor called" << endl; } }; int main() { Box b1; // Constructor called automatically cout << "Length: " << b1.length << endl; // 0 return 0; }
2. Parameterized Constructor
class Rectangle { private: int length, width; public: // Parameterized Constructor Rectangle(int l, int w) { length = l; width = w; } int area() { return length * width; } }; int main() { Rectangle r1(10, 5); // Pass values to constructor cout << "Area: " << r1.area() << endl; // 50 return 0; }
3. Copy Constructor
Creates object by copying another object of same class.
class Point { public: int x, y; // Parameterized Constructor Point(int a, int b) { x = a; y = b; } // Copy Constructor Point(const Point &p) { x = p.x; y = p.y; cout << "Copy Constructor called" << endl; } }; int main() { Point p1(10, 20); Point p2 = p1; // Copy constructor called cout << "p2: (" << p2.x << ", " << p2.y << ")" << endl; // (10, 20) return 0; }
Constructor Rules:
- Same name as class
- No return type (not even void)
- Automatically called when object created
- Can be overloaded (multiple constructors with different parameters)
- If no constructor defined, compiler provides default constructor
Destructor
Special member function automatically called when object is destroyed. Used to release resources (memory, files, etc.).
class Demo { public: // Constructor Demo() { cout << "Constructor called" << endl; } // Destructor (~ before class name) ~Demo() { cout << "Destructor called" << endl; } }; int main() { Demo d1; // Constructor called cout << "Inside main" << endl; return 0; // Destructor called when d1 goes out of scope } /* Output: Constructor called Inside main Destructor called */
Destructor Rules:
- Same name as class with ~ (tilde) prefix
- No parameters, no return type
- Only one destructor per class (cannot be overloaded)
- Automatically called when object destroyed
Inheritance & Access Specifiers
Code reusability through parent-child class relationships
What is Inheritance?
Inheritance is mechanism where new class (derived/child) acquires properties and behaviors of existing class (base/parent). Promotes code reusability.
// Base Class (Parent) class Animal { public: void eat() { cout << "Eating..." << endl; } }; // Derived Class (Child) - inherits from Animal class Dog : public Animal { public: void bark() { cout << "Barking..." << endl; } }; int main() { Dog d; d.eat(); // Inherited from Animal d.bark(); // Own method }
Types of Inheritance
- Single: One base, one derived (A โ B)
- Multiple: One derived, multiple bases (A, B โ C)
- Multilevel: Chain (A โ B โ C)
- Hierarchical: One base, multiple derived (A โ B, C, D)
- Hybrid: Combination of above
Polymorphism & Virtual Functions
Same interface, different implementations - function/operator overloading, virtual functions
Polymorphism Types
1. Compile-time (Static): Function Overloading, Operator Overloading
2. Runtime (Dynamic): Virtual Functions, Function Overriding
// Virtual Function Example class Shape { public: virtual void draw() { // Virtual function cout << "Drawing Shape" << endl; } }; class Circle : public Shape { public: void draw() override { // Override cout << "Drawing Circle" << endl; } }; int main() { Shape* s = new Circle(); // Base pointer, derived object s->draw(); // Calls Circle's draw (Runtime polymorphism) delete s; }
Pointers & Dynamic Memory
Memory addresses, pointer operations, new/delete operators
Pointer Basics
int x = 10; int* ptr = &x; // Pointer stores address of x cout << *ptr << endl; // Dereferencing: prints value (10) // Dynamic Memory int* p = new int(25); // Allocate memory on heap cout << *p << endl; // 25 delete p; // Free memory
Arrays & Strings
Collection of elements and string manipulation
Arrays
int arr[5] = {10, 20, 30, 40, 50}; for(int i=0; i<5; i++) cout << arr[i] << " "; // 2D Array int matrix[3][3] = {{1,2,3}, {4,5,6}, {7,8,9}};
Strings
string s = "Hello"; cout << s.length() << endl; // 5 s += " World"; // Concatenation cout << s.substr(0, 5) << endl; // "Hello"
File Handling
Reading from and writing to files
File Operations
#include <fstream> // Writing to file ofstream outfile("data.txt"); outfile << "Hello File!" << endl; outfile.close(); // Reading from file ifstream infile("data.txt"); string line; while(getline(infile, line)) { cout << line << endl; } infile.close();
Exception Handling
Handling runtime errors gracefully using try-catch
try-catch Block
try { int x = 10, y = 0; if(y == 0) throw "Division by zero!"; cout << x/y; } catch(const char* msg) { cout << "Error: " << msg << endl; }
Templates & Generic Programming
Write code that works with any data type
Function Templates
template <typename T> T add(T a, T b) { return a + b; } int main() { cout << add(5, 3) << endl; // int version cout << add(5.5, 3.2) << endl; // double version }
Class Templates
template <typename T> class Pair { T first, second; public: Pair(T a, T b) : first(a), second(b) {} T getMax() { return (first > second) ? first : second; } };
Standard Template Library (STL)
Pre-built containers, algorithms, and iterators
STL Containers
#include <vector> #include <map> // Vector (Dynamic Array) vector<int> v = {10, 20, 30}; v.push_back(40); // Add element // Map (Key-Value pairs) map<string, int> ages; ages["Ali"] = 20; ages["Sara"] = 22;
Data Structures in C++
Implementing fundamental data structures
Common Data Structures
- Stack: LIFO (Last In First Out) - push, pop operations
- Queue: FIFO (First In First Out) - enqueue, dequeue
- Linked List: Dynamic size, non-contiguous memory
- Binary Tree: Hierarchical structure, each node has max 2 children
- Graph: Nodes connected by edges
#include <stack> stack<int> s; s.push(10); s.push(20); cout << s.top() << endl; // 20 s.pop();
Advanced C++ Topics
Modern C++ features and best practices
C++11/14/17/20 Features
- auto keyword: Automatic type deduction
- Range-based for:
for(auto x : vector) - Lambda expressions: Anonymous functions
- Smart pointers: unique_ptr, shared_ptr (automatic memory management)
- Move semantics: Efficient resource transfer
- constexpr: Compile-time constants
// Modern C++ Examples auto x = 10; // auto deduces type as int vector<int> v = {1, 2, 3, 4, 5}; for(auto num : v) { // Range-based for cout << num << " "; } // Lambda function auto add = [](int a, int b) { return a + b; }; cout << add(5, 3) << endl; // 8
Best Practices
๐ Congratulations!
You've completed C++ Programming course! You now have solid foundation in C++ - from basics to advanced OOP, STL, and modern features. Keep practicing and building projects! ๐ป๐

