LIVE Instructor-Led Courses
Dismiss
Learn C++ from scratch: A complete guide for beginners

25 September 2023

Learn C++ from scratch: A complete guide for beginners

Welcome to this comprehensive guide on learning C++ programming from the ground up! C++ is one of the most widely used programming languages and will provide you with a solid foundation in coding. This tutorial is designed for complete beginners - no prior experience is required.

Over the course of this guide, you will learn fundamental C++ concepts, work through hands-on examples and exercises, and gain the skills needed to start building your own applications. We'll cover everything from installing a compiler and writing your first program, to variables, control structures, functions, classes, and much more. By the end, you will have a good grasp of the C++ language and be ready to continue your programming journey.

In order to fully maximise this guide consider taking our C++ Introduction course 

So let's get started!

What is C++? A Brief History

C++ is a general-purpose, object-oriented programming language that was developed by Bjarne Stroustrup at Bell Labs in the early 1980s. It is an extension of the C programming language and provides additional features like classes, inheritance, strong typing, and exception handling.

The key highlights of C++ include:

  • Statically typed language with a combination of high-level and low-level constructs
  • Supports object-oriented, generic, and procedural programming styles
  • Powerful compile-time polymorphism through templates
  • High performance and closeness to hardware
  • Large standard library for common data structures and algorithms

Over the years, C++ has evolved significantly and added many new features. The latest versions - C++11, C++14, C++17, and C++20 - provide modern capabilities like concurrency, utilities, regular expressions, and concepts. This has further solidified C++'s position as one of the most widely-used programming languages today.

C++ is a mature language with widespread adoption. It is commonly used for:

  • Desktop applications
  • Operating systems
  • Advanced drivers
  • Embedded firmware
  • High performance servers
  • Game engines
  • And much more!

Learning C++ opens up endless coding possibilities across multiple domains. The language itself is very feature-rich, versatile and provides high performance - making it a great choice for all kinds of applications.

Why Learn C++?

Here are some of the key benefits of learning C++ as your first or next programming language:

Powerful and Versatile

C++ gives you access to high-level abstractions like classes as well as low-level hardware manipulation. This versatility allows you to build all kinds of apps and systems.

Fast and Efficient

Thanks to native compilation and low-level control, C++ programs are fast and efficient. They are well-suited for performance-critical applications.

Robust Standard Library

The C++ standard library (STL) provides portable data structures and algorithms for common programming tasks.

Explicit Control

Unlike languages like Java, C++ allows you to take complete control over memory and system resources. This enables optimal utilization.

Available Everywhere

C++ compilers are available on all major platforms like Windows, Mac, Linux, and mobile. C++ code is portable across systems.

Solid Foundation

Mastering C++ core concepts like objects, functions, memory management prepares you for learning other languages.

Great Career Prospects

C++ devs are in high demand and the language will be relevant for many more years. Knowledge of C++ opens many doors.

By gaining expertise in C++, you equip yourself with a skillset that will be useful and sought after for a long time. The concurrency features in modern C++ make it suitable for parallel and asynchronous applications. And C++11/C++14 have made the language much simpler and safer to use.

In summary, C++ is an excellent language to learn for aspiring developers due to its versatility, efficiency, ubiquity and longevity. It's a solid stepping stone to mastering programming.

Setting Up Your C++ Environment

Before we can start coding, we need to setup and configure our C++ development environment. This involves installing a compiler, an editor/IDE, and ensuring we can compile and run a simple C++ program.

Install a C++ Compiler

A C++ compiler is required for translating your code to executable programs. Here are some compiler options:

  • GCC/G++ - The GNU Compiler Collection has C and C++ compilers for Linux, macOS, and Windows Subsystem for Linux (WSL)
  • Visual Studio - Microsoft's full-featured IDE has an excellent C++ toolchain
  • Clang/LLVM - Fast and modular compiler with great diagnostics
  • MinGW - The Minimalist GNU for Windows provides GCC for Windows

If using Visual Studio, you won't need a separate compiler as VS includes it internally. For other options like GCC, follow OS-specific instructions to install the compiler suite. Ensure it is added to your system PATH.

Get an Editor or IDE

For writing code, you can use any text editor but an integrated development environment (IDE) is highly recommended. Popular choices include:

  • Visual Studio - Excellent for Windows with a full debugger and IntelliSense
  • Xcode - Mac IDE with C++ support out of the box
  • CLion - Cross-platform IDE by JetBrains focused on C/C++
  • Code::Blocks - Open source, cross-platform IDE with good C++ tools
  • Eclipse CDT - Plugin for the Eclipse IDE adding C/C++ support

Set one of these up on your OS. An IDE will improve your programming experience with handy features like debugging, autocompletion, refactoring, and more.

Write Your First C++ Program

Let's create the obligatory "Hello World" program to verify our toolchain is working correctly.

  1. Open your IDE and create a new C++ project/workspace.
  2. Add a source file called main.cpp
  3. Enter this code:
    
    #include <iostream>
    
    int main() {
      std::cout << "Hello World!";
      return 0; 
    }
    
    
  4. Build and run the program. It should display Hello World!

If you don't see the expected output, revisit your environment setup. Ensure the compiler is installed and the IDE/editor configuration is correct.

With the fundamentals set up, we are now ready to understand the C++ language itself. Let's get coding!

Basic C++ Syntax

Like any programming language, C++ has its own grammar, keywords, data types and constructs. Before diving into advanced concepts, we need to familiarize ourselves with the basic syntax.

This section will give you a primer on the structure of a C++ program, variables, data types, operators, input/output, and other building blocks.

Structure of a C++ Program

A C++ program mainly consists of the following:

  • Preprocessor directives - Headers, macros, etc
  • Functions - Reusable code sections, starting with main()
  • Variables - Named memory locations to store values
  • Statements - Instructions that perform actions
  • Comments - Notes ignored by the compiler

Here is a simple program structure:


// Preprocessor directives
#include <iostream>   

// Main function
int main() {

  // Statements 
  std::cout << "Hello World!";
   
  return 0;
}

The source code is processed top-down when compiled. Code must be inside a function - main() is the startup function.

Variables and Data Types

Variables allow you to store data in memory and manipulate it. Each variable has a name and a type - like int num = 5;

C++ is statically typed so each variable must be declared with a type before use. Some key native types include:

  • int - for whole numbers like 3, -200, etc
  • double - for decimals like 3.14, -7.58, etc
  • char - for single characters like 'a', '@' etc
  • string - for text like "Hello World"
  • bool - for true/false values

Here is an example of variables:


int count = 10; // integer variable
double price = 24.95; // double variable
char letter = 'A'; // character variable  
string name = "Alice"; // string variable
bool isValid = true; // boolean variable

Each variable should have a meaningful name and directly relate to the data it represents.

Operators

Operators allow you to perform operations and calculations on variables and values:

  • Arithmetic - +, -, *, /
  • Comparison - >, <, ==
  • Logical - &&, ||, !
  • Bitwise - &, |, ~

For example:


int a = 5;
int b = 3;
int sum = a + b; // 8
bool equal = (a == b); // false  

Learn more about the different C++ operators here.

Input/Output

The iostream header in C++ provides input/output functionality.

  • cin allows accepting input from the keyboard into variables
  • cout allows printing output to the screen

For example:


#include <iostream>

int main() {

  int age;
  std::cout << "Enter your age: ";  
  std::cin >> age;

  std::cout << "Your age is: " << age;

  return 0;  
} 

This allows creating interactive programs. We will learn more I/O operations in later sections.

These are the fundamentals of C++ syntax - enough to write simple programs. Next we'll look at control structures and functions to make the code more modular.

Control Flow in C++

All programs need the ability to control the flow of execution - only executing code selectively based on runtime conditions.

C++ provides the following control flow statements:

  • if statements
  • switch statements
  • for loops
  • while loops
  • do while loops
  • break and continue

Let's understand each construct.

The If Statement

The if statement allows executing code only when some condition is true:

  
int x = 5;

if (x > 0) {
  // Code to execute if condition is true
}

  • The condition goes inside parentheses
  • Code is inside curly braces
  • Use else for the condition being false

For example:


int score = 65;

if (score >= 50) {
  std::cout << "Passed!";
}
else {
  std::cout << "Failed!"; 
}

This prints "Passed!" since the condition is true.

You can chain multiple if/else together:

  
if (score >= 90) {
  grade = 'A'; 
}
else if (score >= 80) {
  grade = 'B';   
}
else if (score >= 70) {
  grade = 'C';
}
else {
  grade = 'F';
}

The first true condition's block executes.

The Switch Statement

The switch statement executes code based on an exact value match:


int day = 2;

switch (day) {
  case 1:
    std::cout << "Monday"; 
    break;
  case 2:
    std::cout << "Tuesday";
    break;
  // ...
}

  • day is compared to each case
  • When matches, that case code runs
  • break stops further cases

switch is useful for enum-like values.

For Loops

for loops repeat code a fixed number of times:

  
for (int i = 0; i < 5; i++) {
  std::cout << i << "\n";
}

  • Initialization first
  • Condition to check each iteration
  • Increment step after body

This prints numbers 0 to 4.

While Loops

while loops repeat code until a condition becomes false:


int i = 0;
while (i < 5) {
  std::cout << i << "\n";
  i++;   
}

  • Condition checked first
  • Executes repeatedly if true
  • Use increment to eventually exit

Prints out 0 to 4 like a for loop

 

Do While Loops

The do while loop executes code once and then repeats conditionally:

  int i = 0; do { std::cout << i << "\n"; i++; } while (i < 5);  
  • Body executed first unconditionally
  • Condition checked at end to repeat

Do while loops are useful to run code at least once.

Learn these control structures well as they form the basis of writing complex C++ programs. You will come across them frequently in any code.

Next let's see how to organize code into reusable modules called functions.

Functions in C++

Functions are reusable sections of code that implement specific logic in a program. They are a key way to decompose complex problems into smaller logical units.

C++ functions have the following format:

  returnType name(parameters) { // logic return value; }  
  • returnType - The data type returned
  • name - A descriptive name for the function
  • parameters - Variables passed to the function
  • return - Returns a value back to the caller

For example, a function to add two numbers:

  int add(int a, int b) { int sum = a + b; return sum; }  

This function:

  • Takes two int parameters
  • Calculates the sum
  • Returns an int result

To use a function:

  int result = add(2, 3); // Call function  

The major benefits of functions are code reuse and organization.

  • Reusable logic abstracted into functions
  • Main program is structured by calling functions

Functions also enable separation of concerns - different functions handle different tasks.

Next we will use functions to structure object-oriented programs.

Classes and Objects in C++

Object oriented programming (OOP) is a programming paradigm centered around objects that contain data and associated behavior.

C++ supports OOP via classes and objects. A class is like a blueprint while an object is an instance created from that blueprint.

For example, a Car class:

  class Car { public: string make; string model; int year; void start(); void stop(); };  

This car class has:

  • Attributes - make, model, year
  • Methods - start(), stop()

We can create Car objects like:

  Car sedan; sedan.make = "Toyota"; sedan.model = "Camry"; sedan.year = 2022;  

This sedan object has its own data. We can call methods like:

  sedan.start(); sedan.stop();  

Class Syntax

C++ classes have the following syntax:

  class ClassName { // Members public: // Access specifier // Attributes // Methods };  
  • ClassName - Descriptive name like Car, Student, etc
  • Members - Attributes and methods (functions)
  • public - Makes members accessible

Multiple access levels like private also exist. We will cover that next.

Creating Objects

To create an object instance from a class:

  ClassName objectName;  

This allocates memory for the object. We can access members:

  objectName.attribute = "value"; objectName.method();  

Objects encapsulate data + functions together.

Access Modifiers

Class members can have different access levels:

  • public - Accessible from anywhere
  • private - Accessible only within class
  • protected - Accessible to class + subclasses

For example:

  class Room { public: int length; private: int width; protected: int height; }; Room room1; room1.length = 100; // OK room1.width = 50; // Error!  

private and protected enforce encapsulation - hiding data from outside misuse. This is a key OOP concept.

We will learn more advanced object-oriented concepts like inheritance and polymorphism next.

More OOP: Inheritance, Polymorphism, Abstraction

In the previous section we learned basics of classes and objects. Now let's understand some more advanced object-oriented concepts:

  • Inheritance
  • Polymorphism
  • Abstraction

These concepts help write modular, extensible, and reusable code.

Inheritance

Inheritance allows a class to derive attributes and methods from a parent class.

For example:

  class Vehicle { public: int maxSpeed; void start(); void stop(); }; class Car: public Vehicle { public: int numDoors; void openDoors(); };  

Here Car inherits from Vehicle:

  • Car gets maxSpeed, start() and stop() from Vehicle
  • It can also have its own members like numDoors and openDoors()

This models an is-a relationship - a Car is a Vehicle.

Polymorphism

Polymorphism means having multiple forms. In OOP, it allows a derived class object to be treated like its base class object.

For example:

  class Shape { public: virtual double area() = 0; }; class Circle: public Shape { public: double radius; double area() { return 3.14 * radius * radius; } }; class Square: public Shape { public: double side; double area() { return side * side; } };  

A Shape pointer can refer to a Circle or Square object:

  Shape* shape = new Circle(); shape->radius = 5.0; shape->area(); // invokes Circle's area()  

Even though shape is a Shape pointer, the appropriate derived class method is called based on the actual object. This runtime resolution is polymorphism.

Abstraction

Abstraction focuses on essential qualities rather than the implementation details. Classes allow related data and methods to be encapsulated together achieving abstraction.

For example, Car class abstracts:

  • Attributes like make, model, etc
  • Methods like start, stop, etc

A user of Car doesn't need to know how an engine starts internally - just that they can call start(). This separates what from how.

Abstract base classes take this further by only defining an interface. Derived classes implement the details.

Together, inheritance, polymorphism and abstraction enable building robust class hierarchies reflecting real-world relationships.

Next, we will cover more advanced topics like memory management and the C++ standard template library (STL).

Pointers and Memory Management

C++ gives developers direct control over memory. This helps optimize performance and resource usage in applications like game engines and OS kernels.

Understanding memory management in C++ revolves around:

  • Pointers - Variables that store memory addresses
  • References - Aliases to existing variables
  • The stack and the heap - Methods of memory allocation
  • Smart pointers - Automatic garbage collection

Let's go through each concept.

Pointers

A pointer variable stores a memory address pointing to data rather than containing the data itself. The address gives the pointer variable access to the data.

For example:

  int value = 5; // Normal integer int* ptr = &value; // Pointer to value std::cout << ptr; // Prints memory address std::cout << *ptr; // Prints value  
  • & before a variable returns its address
  • * declares a pointer variable
  • *ptr dereferences to access the pointed value

Common pointer operations:

  • Get address of variable with &var
  • Declare pointer int* ptr
  • Assign address ptr = &var
  • Dereference *ptr to access value
  • Reassign to point elsewhere ptr = &otherVar

Pointers enable lower-level control and efficiency. But misuse can lead to bugs - pointer errors are infamous!

References

References are aliases to existing variables. Once initialized, they refer to that variable directly.

  int x = 5; int& y = x; std::cout << x; // 5 std::cout << y; // 5 x++; std::cout << y; // 6  
  • Declared with & after type - int& y
  • Must be initialized
  • Any change affects original variable

References are safer and less error-prone than pointers. Use them to pass function arguments efficiently.

The Stack and the Heap

Variables declared normally occupy space on the stack:

  int x = 5; // Stack  
  • Stack space is managed automatically
  • Variables destroyed when they go out of scope
  • Fixed maximum size per thread

The heap allows allocating memory dynamically:

  int* ptr = new int; // Heap *ptr = 7;  
  • Allocated and freed manually
  • Exists until explicitly freed
  • Much more memory available

Overuse of heap can waste resources. Stack is better for local variables.

Smart Pointers

Managing dynamic memory properly is hard. Smart pointers do it automatically by freeing heap-allocated objects when no longer used.

For example:

  #include <memory> std::unique_ptr<int> ptr(new int);  
  • unique_ptr deallocates object on leaving scope
  • Other types like shared_ptr use reference counting

Smart pointers prevent leaks and dangling pointer bugs. Prefer them over normal pointers.

Understanding pointers and dynamic memory gives you more control as a C++ programmer. Use smart pointers as much as possible to minimize issues.

Next we'll explore C++'s powerful standard template library (STL) for common data structures and algorithms.

The Standard Template Library (STL)

The C++ standard library provides a wealth of reusable data structures, algorithms, and functions. This STL helps avoid reinventing the wheel.

Some major components include:

  • Containers - Data structures like vectors, sets, maps
  • Algorithms - Functions like sort, find, count
  • Iterators - Generalized pointers for containers
  • Utilities - Smart pointers, time, I/O operations

Let's look at some commonly used parts of the STL.

Vectors

The std::vector class provides a dynamic array implementation.

  #include <vector> std::vector<int> nums {1, 2, 3}; nums.push_back(4); // Add element nums.size(); // Number of elements for (int n : nums) { std::cout << n << "\n"; // Prints elements }  
  • Insert with push_back()
  • Random access with []
  • Iterate with range-based for loop

Vectors grow efficiently as elements are added.

Maps

std::map stores key-value pairs. Elements are sorted by key.</

 

  #include <map> std::map<string, int> ages { {"Raj", 25}, {"Sarah", 34} }; ages["Mike"] = 40; // Insert new ages["Raj"] = 30; // Update ages.at("Sarah"); // 34 - fetch value for (auto itr = ages.begin(); itr != ages.end(); ++itr) { std::cout << itr->first << " - " << itr->second << "\n"; }  
  • Subscript notation [key] to access elements
  • .at(key) also fetches, throws exception if missing
  • .find(key) returns end iterator if not found

Maps provide fast lookup by key.

Iterators

Iterators are generalized pointers for sequentially accessing STL containers.

All containers provide iterators for looping through elements:

  std::vector<string> names {"John", "Jane"}; for (std::vector<string>::iterator itr = names.begin(); itr != names.end(); itr++) { std::cout << *itr << "\n"; // Dereference }  
  • container::iterator is the iterator type
  • begin() points to first element
  • end() points to after last element
  • ++itr moves to next element

Learning to use iterators allows working with all STL containers uniformly.

The STL is vast with many more useful classes and functions. Mastering it will boost your C++ productivity.

Exception Handling

Exceptions provide a standard way to react to and handle runtime errors in applications.

For example, a function to divide two numbers:

  int divide(int a, int b) { if (b == 0) { throw std::invalid_argument("Divide by zero error"); } return a / b; }  
  • throw an exception on error condition
  • Causes immediate unwinding of the call stack
  • Execution jumps to appropriate catch block

To handle exceptions:

  try { int result = divide(5, 0); } catch (std::invalid_argument& e) { std::cout << e.what(); }  
  • try block contains code that may throw
  • catch block handles the error
  • Multiple catch blocks can be chained

This separates error handling from normal program flow.

Exception Classes

C++ defines various standard exception classes in <exception>:

  • std::exception - Base class
  • std::invalid_argument - Invalid arguments
  • std::out_of_range - Index out of range
  • std::runtime_error - Recoverable runtime issue
  • std::logic_error - Logic bug in code

Derive custom exception classes from std::exception.

Stack Unwinding

When an exception occurs:

  1. The stack is unwound back to the nearest catch block
  2. Objects are properly destroyed along the way
  3. Execution resumes in the catch block

This automatic stack unwinding ensures proper cleanup before handling the exception.

Proper use of exceptions and catch blocks makes programs more robust and fault-tolerant. Multiple errors can be handled uniformly.

Concurrency in C++

Modern systems involve multiple things happening at once or concurrently. C++ provides features for concurrent and parallel programming:

  • Threads - Independent sequences of execution
  • Mutexes - Mechanism for thread synchronization
  • Atomics - Thread-safe programming primitives
  • async - Asynchronous function execution

Let's go through the basics of concurrency in C++.

Threads

The <thread> header provides thread management functionality. New threads can be spawned like:

  #include <thread> void func() { // Task for thread } int main() { std::thread t(func); // spawn thread t.join(); // Wait for completion return 0; }  
  • std::thread takes a function to execute concurrently
  • Multiple threads execute simultaneously
  • .join() blocks until thread finish

Threads facility task parallelism in applications.

Synchronizing Threads

With multiple threads, situations like data races can occur when accessing shared state.

Mutexes provide mutual exclusion primitives for synchronization:

  #include <mutex> std::mutex m; void task() { m.lock(); // Critical section m.unlock(); }  
  • std::mutex protects shared data
  • m.lock() begins synchronized section
  • m.unlock() ends it

Only one thread can lock the mutex at a time. This prevents concurrent access issues.

Atomic Operations

Atomic types provide thread-safe programming:

  #include <atomic> std::atomic<int> counter; void incCounter() { counter.fetch_add(1); // Atomically increment }  
  • std::atomic<T> provides atomic variables
  • Methods like fetch_XXX are atomic
  • Synchronizes safely with threads

Prefer atomics for primitive types instead of mutexes.

C++ concurrency takes advantage of modern multi-core processors. Concurrent code can improve performance but requires careful programming.

We have now covered the major language features as well as memory management, the STL, exceptions and concurrency in C++. Next let's briefly look at some advanced topics.

Advanced C++ Topics

We've covered the most essential C++ concepts so far. This section will briefly introduce some more advanced C++ capabilities:

  • Templates - Generic programming
  • Networking - Sockets programming
  • File I/O - Reading and writing files
  • Multithreading - Advanced thread controls
  • Regular expressions - Text pattern matching
  • Metaprogramming - Compile-time code generation
  • Graphics - 2D and 3D graphics

Let's summarise each topic:

Templates

Templates enable generic programming in C++. Functions and classes can operate on different data types using templates:

  template <typename T> T getMax(T a, T b) { return (a > b) ? a : b; } getMax<int>(5, 10); // Call with int getMax<double>(5.5, 10.5); // Call with double  
  • template specifies parameters like T
  • Compiler generates specialized code

Templates work for any valid type while reusing common logic.

Network Programming

C++ supports network programming via sockets. TCP and UDP connections can be established:

  #include <sys/socket.h> int socket(int domain, int type, int protocol); socket(AF_INET, SOCK_STREAM, 0); // TCP socket socket(AF_INET, SOCK_DGRAM, 0); // UDP socket  

Sockets are used to build TCP servers, UDP clients, and other network apps in C++.

File I/O

The standard I/O streams provide file handling capabilities:

  #include <fstream> std::ifstream in("file.txt"); // Input stream std::ofstream out("data.txt"); // Output stream out << "Hello"; // Write to file string line; in >> line; // Read line from file  

Ifstreams, ofstreams, and fstreams allow reading and writing files in C++.

And much more advanced topics to continue mastering this powerful language!

Exercises

To retain what you have learned so far, try building some simple C++ programs:

  • A number guessing game
  • A simple calculator
  • A tic-tac-toe game
  • A text editor
  • A to-do list manager

Some things to practice:

  • Loops and control structures
  • Functions and modular design
  • Classes to model data
  • File I/O for saving data
  • STL data structures like vectors

These exercises will help reinforce core C++ concepts and show how they come together in a complete application.

Start simple and gradually build up to more complex programs. The problem-solving process and debugging skills are equally important.

Conclusion

Congratulations, you have reached the end of this comprehensive introduction to C++ programming!

We started from the basics of compilers, variables, functions and went all the way to OOP, memory management and the STL. You learned about key constructs like:

  • Control structures - branch program flow
  • Functions - reusable logic blocks
  • Classes and objects - encapsulate data and methods
  • Inheritance and polymorphism - extend classes
  • Smart pointers and RAII - automatic memory management
  • Containers and algorithms - standard data structures

With this foundation, you are now ready to start building your own C++ projects for desktop, web, mobile, games or embedded systems. The language has vast depth - keep practicing and learning more.

C++ gives you raw power combined with high-level abstractions. You can develop fast, efficient and safe systems with C++. Check out our article on The Most Essential C++ Advice for Beginners

We want you to go forth and build something awesome with your new C++ skills! so the perfect follow up to this article would be our C++ Introduction course which will leave you fully equipped to use C++ 

Or consider one of JBI Trainings other courses 

CONTACT
+44 (0)20 8446 7555

[email protected]

SHARE

 

Copyright © 2023 JBI Training. All Rights Reserved.
JB International Training Ltd  -  Company Registration Number: 08458005
Registered Address: Wohl Enterprise Hub, 2B Redbourne Avenue, London, N3 2BS

Modern Slavery Statement & Corporate Policies | Terms & Conditions | Contact Us

POPULAR

Rust training course                                                                          React training course

Threat modelling training course   Python for data analysts training course

Power BI training course                                   Machine Learning training course

Spring Boot Microservices training course              Terraform training course

Kubernetes training course                                                            C++ training course

Power Automate training course                               Clean Code training course