Learn C++ from Scratch Complete Course with Examples

Learn C++ learn from scratch with a complete tutorial covering setup, syntax, I/O, loops, functions, OOP, STL, files, templates, and a mini project.

1. Install & Setup (Windows / macOS / Linux)

Windows

  1. Install VS Code + the “C/C++” extension
  2. Install MinGW-w64 (provides g++)
  3. In Terminal: g++ --version (should print a version)

macOS

  • Run: xcode-select --install
  • Install VS Code + C/C++ extension
  • Check: g++ --version

Ubuntu/Debian

sudo apt update
sudo apt install build-essential
g++ --version

2. Your First Program (Hello World)

#include <iostream>          // (1)
using namespace std;         // (2)

int main() {                 // (3)
    cout << "Hello, World!\n"; // (4)
    return 0;                // (5)
}

How it works

  1. Loads the standard input/output library so cout is available.
  2. Lets you write cout instead of std::cout (convenience).
  3. Program starts executing from main(). It returns an int status to the OS.
  4. Sends the string to standard output; \n moves the cursor to the next line.
  5. 0 means “success”. (Non-zero usually signals an error.)

3. Program Structure Essentials

  • Includes (#include <...>) bring in libraries.
  • Namespaces avoid long names (e.g., std::cout).
  • main is the entry point.
  • Return code (0 success, nonzero error).

4. Variables & Data Types

#include <iostream>
#include <string>
using namespace std;

int main() {
    int age = 21;                 // (1)
    double price = 999.99;        // (2)
    char grade = 'A';             // (3)
    bool isPass = true;           // (4)
    const double PI = 3.14159;    // (5)
    string name = "Alice";        // (6)

    cout << name << " " << age << " " << price << " " << grade << " " << isPass << "\n"; // (7)
}

How it works

  1. int stores whole numbers.
  2. double stores floating-point (decimal) numbers.
  3. char stores a single character (single quotes).
  4. bool stores logical values (true/false); printing shows 1/0.
  5. const makes the variable read-only (cannot change after initialization).
  6. string holds text.
  7. The stream insertion operator << chains multiple values to print in one line.

5. Operators & Expressions

  • Arithmetic: + - * / %
  • Relational: == != < > <= >=
  • Logical: && || !
  • Increment/Decrement: ++a, a++, --a, a--

6. Input/Output (cin, cout, getline)

#include <iostream>
#include <string>
using namespace std;

int main() {
    string fullName;
    int year;

    cout << "Enter your full name: ";
    getline(cin, fullName);           // (1)

    cout << "Enter your birth year: ";
    cin >> year;                      // (2)

    cout << "Hi " << fullName << "! You were born in " << year << ".\n"; // (3)
}

How it works

  1. getline reads the entire line (including spaces) into fullName.
  2. cin >> year reads the next “token” (stops at the first space/newline).
  3. Concatenates the captured inputs and prints a friendly sentence.

Tip: If you mix cin >> and getline in the other order, consume the leftover newline with cin.ignore() before calling getline.

7. Control Flow (if/else, switch, loops)

if/else

int n; 
cin >> n;
if (n % 2 == 0) cout << "Even\n";
else            cout << "Odd\n";

How it works: % gets the remainder; even numbers give 0 when divided by 2.

switch

int op; cin >> op;
switch (op) {
  case 1: cout << "Start\n"; break;   // (a)
  case 2: cout << "Stop\n";  break;   // (b)
  default: cout << "Invalid\n";       // (c)
}

How it works:
(a)(b) When a case matches, that block runs. break prevents falling into the next case.
(c) default runs if no case matches.

loops

for (int i=1; i<=5; i++) cout << i << " ";  // (1) 1..5
int x=3; while (x>0) { cout << x-- << " "; } // (2) 3 2 1
int y=0; do { cout << y << " "; } while (++y<3); // (3) 0 1 2

How it works:

  1. for has initialization, condition, increment perfect for counted loops.
  2. while repeats while the condition stays true.
  3. do..while runs the body once before checking the condition.

8. Functions (parameters, overloading, recursion)

int add(int a, int b) { return a + b; }            // (A)
double add(double a, double b) { return a + b; }   // (B)
long long fact(int n) {                             // (C)
    if (n <= 1) return 1;                          // base case
    return n * fact(n - 1);                        // recursive step
}

How it works

  • (A) and (B) share the same name add but accept different types the compiler picks the correct one based on the arguments (this is function overloading).
  • (C) fact multiplies n by fact(n-1) until it hits the base case n <= 1, which returns 1 and stops further recursion.

9. Arrays, std::string, std::vector

int a[3] = {10,20,30};      // (1)

#include <vector>
vector<int> v = {1,2,3};    // (2)
v.push_back(4);             // v = 1,2,3,4

#include <string>
string s = "Hello";         // (3)
s += " C++";                // "Hello C++"

How it works

  1. Raw array with fixed size (index from 0..2).
  2. vector is a dynamic array: grows/shrinks at runtime; push_back appends.
  3. string supports concatenation via +=.

10. Pointers & References

int x = 10;
int* p = &x;     // (1)
*p = 20;         // (2)

int y = 5;
int& r = y;      // (3)
r = 7;           // (4)

How it works

  1. &x takes the memory address of x; p stores that address.
  2. *p dereferences the pointer (reaches into x) and changes its value to 20.
  3. r is a reference (an alias) to y it must refer to a valid object at initialization and cannot be reseated.
  4. Assigning to r actually assigns to y.

11. Dynamic Memory & Smart Pointers

Raw (manual avoid in new code):

int* p = new int(42);   // (1)
cout << *p << "\n";
delete p;               // (2)

How it works

  1. new allocates an int on the heap and returns its address.
  2. delete frees that memory; forgetting leads to memory leaks.

Modern approach

#include <memory>
auto up = std::make_unique<int>(42);         // (A)
auto sp = std::make_shared<std::string>("Hi"); // (B)

How it works

  • (A) unique_ptr owns the object exclusively and deletes it automatically when it goes out of scope.
  • (B) shared_ptr keeps a reference count; when the last copy is destroyed, the object is freed.

12. Structs & Enums

struct Student {
    std::string name; 
    int score;
};

enum class Color { Red, Green, Blue };  // strongly-typed enum

How it works

  • struct groups related fields.
  • enum class avoids accidental conversions and name clashes.

13. OOP Classes, Constructors, Inheritance, Polymorphism

Classes & Inheritance

#include <iostream>
#include <string>
using namespace std;

class Person {
    string name;  // private
    int age;
public:
    Person(string n, int a): name(n), age(a) {}  // ctor (init list)
    void greet() const { cout << "Hi, I'm " << name << "\n"; }
};

class Employee : public Person {     // inherits Person
    double salary;
public:
    Employee(string n,int a,double s): Person(n,a), salary(s) {}
    void greet() const { cout << "Employee says hello!\n"; } // hides Person::greet
};

How it works

  • Person holds state (name, age) and behavior (greet). The constructor initializes members using an initializer list.
  • Employee extends Person and adds salary. Its greet hides the base method because the base method is not virtual.

Polymorphism (runtime)

class Base { 
public: 
    virtual void speak(){ cout << "Base\n"; } // (1)
};
class Der : public Base {
public:
    void speak() override { cout << "Der\n"; } // (2)
};

Base* b = new Der(); // (3)
b->speak();          // prints "Der"
delete b;

How it works

  1. virtual enables dynamic dispatch (decide the function at runtime by actual object type).
  2. override tells the compiler we intend to override a virtual function.
  3. A base pointer can point to a derived object; with virtual, the derived method runs.

Safer modern style: std::unique_ptr<Base> b = std::make_unique<Der>(); (no manual delete).

Object Oriented Programming

14. Exceptions (try/catch)

#include <iostream>
#include <stdexcept>
using namespace std;

double safeDiv(double a, double b){
    if (b == 0) throw runtime_error("Divide by zero"); // (1)
    return a / b;
}

int main(){
    try {                                     // (2)
        cout << safeDiv(10, 0);
    } catch (const exception& e) {            // (3)
        cerr << "Error: " << e.what() << "\n";
    }
}

How it works

  1. Detect a problem and throw an exception object with a message.
  2. Put risky code in a try block.
  3. catch handles the error; e.what() prints the message.

15. Files & Streams (read/write)

#include <fstream>
#include <vector>
#include <string>
#include <iostream>
using namespace std;

int main(){
    ofstream out("data.txt");                 // (1)
    out << "Alice 90\nBob 85\n";              // (2)
    out.close();                               // (3)

    ifstream in("data.txt");                  // (4)
    string name; int score;
    vector<pair<string,int>> rec;

    while (in >> name >> score)               // (5)
        rec.push_back({name, score});

    for (auto &p : rec)                       // (6)
        cout << p.first << ": " << p.second << "\n";
}

How it works

  1. ofstream opens a file for writing (creates it if missing).
  2. Write two “name score” lines.
  3. Close the output stream (flush buffers).
  4. ifstream opens the same file for reading.
  5. The extraction operator >> reads values until EOF; each pair is pushed into the vector.
  6. Iterate the vector and print each record.

Robustness tip: check out/in with if(!out) or if(!in) to catch open failures.

16. Templates & STL (algorithms + lambdas)

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

#include <vector>
#include <map>
#include <algorithm>   // sort, find
#include <numeric>     // accumulate
#include <iostream>
using namespace std;

int main(){
    vector<int> v = {5,2,9,1};
    sort(v.begin(), v.end());                 // (2) 1 2 5 9

    auto it = find(v.begin(), v.end(), 5);    // (3)
    if (it != v.end()) cout << "Found 5\n";

    map<string,int> mp;                       // (4)
    mp["Alice"]=90; mp["Bob"]=85;

    int sum = accumulate(v.begin(), v.end(), 0, // (5)
                [](int a,int b){ return a+b; }); // lambda
    cout << "Sum=" << sum << "\n";
}

How it works

  1. A function template works for many types (as long as > exists for them).
  2. sort reorders the vector (ascending by default).
  3. find searches linearly; returns an iterator to the found element (or v.end() if not found).
  4. map stores key→value pairs in sorted order by key.
  5. accumulate folds values with a lambda that adds two numbers.

17. Organizing Code (headers + multiple files)

  • Put class/struct declarations in *.hpp (or *.h) and definitions in *.cpp.
  • Include headers where needed; compile all .cpp files together.
  • Keep functions small and focused; use meaningful names; document tricky parts.

Mini Project Student Score Manager (end-to-end)

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
#include <numeric>
using namespace std;

struct Student {                   // (1)
    string name; 
    int score;
};

class Database {                   // (2)
    vector<Student> data;          // holds all records
public:
    void add(const string& n, int s){ data.push_back({n,s}); } // (3)

    void load(const string& file){  // (4)
        ifstream in(file);
        string n; int s; 
        data.clear();
        while (in >> n >> s) data.push_back({n,s});
    }

    void save(const string& file) const {   // (5)
        ofstream out(file);
        for (auto &st: data) out << st.name << " " << st.score << "\n";
    }

    void report() const {                    // (6)
        if (data.empty()){ cout<<"No data\n"; return; }

        int best = max_element(data.begin(), data.end(),
                    [](const Student& a, const Student& b){
                        return a.score < b.score;
                    })->score;

        double avg = accumulate(data.begin(), data.end(), 0.0,
                     [](double acc, const Student& s){ return acc + s.score; })
                     / data.size();

        cout << "Students: " << data.size() << "\n";
        cout << "Average: " << avg << "\n";
        cout << "Top scorers:\n";
        for (auto &s: data)
            if (s.score == best) cout << " - " << s.name << " (" << s.score << ")\n";
    }
};

int main(){                                  // (7)
    Database db;
    db.add("Alice",90); db.add("Bob",85); db.add("Carol",90);

    db.save("students.txt");                 // write
    Database db2;
    db2.load("students.txt");                // read back
    db2.report();                            // print summary
}

How it works

  1. Student groups related fields (name + score).
  2. Database encapsulates storage + operations (clean API, single responsibility).
  3. add appends a record to the in-memory vector.
  4. load clears in-memory data, then reads pairs from a file into the vector.
  5. save writes all records to a file (one per line).
  6. report
    • Finds the highest score using max_element with a custom comparator.
    • Computes average using accumulate.
    • Prints students who match the best score (handles ties).
  7. main demonstrates a real workflow: create → save → load → report.

Extensions to try: validate input ranges, handle empty/bad files, sort by score, or export CSV.

Practice Tasks (to lock in learning)

  1. Temperature converter (C↔F) with a switch menu and separate functions.
  2. Factorial + Fibonacci using both loops and recursion.
  3. Read integers from a file into vector<int>, then sort + min/max/median/average.
  4. BankAccount class (deposit/withdraw, print statement to file, basic validations).
  5. Word-frequency counter using map<string,int> on a text file.

Common Errors & Debugging Tips

  • 'g++' not recognized → fix PATH or reopen terminal.
  • Missing ; or braces → pay attention to compiler line numbers.
  • = vs == in conditions → use == for comparison.
  • Out-of-bounds indexes → stay within [0, size).
  • Prefer smart pointers over raw new/delete.
  • Add checks for file opens: if (!in) { /* handle */ }

Summary

You’ve seen the end-to-end path: compile your first program, master variables, decisions, loops, functions, arrays/strings/vectors, pointers and memory, OOP and polymorphism, exceptions, files, templates, and core STL algorithms then put it together in a practical mini-project. If you publish this as a single article, add internal links to future problem sets, project galleries, and interview tips to maximize SEO and student engagement.

The approach followed at E Lectures reflects both academic depth and easy-to-understand explanations.

People also ask:

Is C++ beginner-friendly?

Yes if you go step-by-step with clear examples (like this article) and practice regularly.

Should I learn raw pointers?

Understand them conceptually, but use smart pointers (unique_ptr, shared_ptr) in modern code.

Why is STL important?

It offers optimized containers and algorithms, accelerating development and reducing bugs.

What IDE/editor do you recommend?

VS Code + C/C++ extension is light and popular. You can try full IDEs later.

How do I get faster at problem solving?

Master loops, functions, arrays/vectors, maps/sets, sorting, binary search, and practice daily.

Leave a Reply

Your email address will not be published. Required fields are marked *