25 September 2023
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!
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:
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:
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.
Here are some of the key benefits of learning C++ as your first or next programming language:
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.
Thanks to native compilation and low-level control, C++ programs are fast and efficient. They are well-suited for performance-critical applications.
The C++ standard library (STL) provides portable data structures and algorithms for common programming tasks.
Unlike languages like Java, C++ allows you to take complete control over memory and system resources. This enables optimal utilization.
C++ compilers are available on all major platforms like Windows, Mac, Linux, and mobile. C++ code is portable across systems.
Mastering C++ core concepts like objects, functions, memory management prepares you for learning other languages.
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.
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.
A C++ compiler is required for translating your code to executable programs. Here are some compiler options:
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.
For writing code, you can use any text editor but an integrated development environment (IDE) is highly recommended. Popular choices include:
Set one of these up on your OS. An IDE will improve your programming experience with handy features like debugging, autocompletion, refactoring, and more.
Let's create the obligatory "Hello World" program to verify our toolchain is working correctly.
main.cpp
#include <iostream>
int main() {
std::cout << "Hello World!";
return 0;
}
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!
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.
A C++ program mainly consists of the following:
main()
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 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, etcdouble
- for decimals like 3.14, -7.58, etcchar
- for single characters like 'a', '@' etcstring
- for text like "Hello World"bool
- for true/false valuesHere 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 allow you to perform operations and calculations on variables and values:
+
, -
, *
, /
>
, <
, ==
&&
, ||
, !
&
, |
, ~
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.
The iostream
header in C++ provides input/output functionality.
cin
allows accepting input from the keyboard into variablescout
allows printing output to the screenFor 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.
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
statementsswitch
statementsfor
loopswhile
loopsdo while
loopsbreak
and continue
Let's understand each construct.
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
}
else
for the condition being falseFor 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 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
break
stops further casesswitch
is useful for enum-like values.
for
loops repeat code a fixed number of times:
for (int i = 0; i < 5; i++) {
std::cout << i << "\n";
}
This prints numbers 0 to 4.
while
loops repeat code until a condition becomes false:
int i = 0;
while (i < 5) {
std::cout << i << "\n";
i++;
}
Prints out 0 to 4 like a for
loop
The do while
loop executes code once and then repeats conditionally:
int i = 0; do { std::cout << i << "\n"; i++; } while (i < 5);
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 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 returnedname
- A descriptive name for the functionparameters
- Variables passed to the functionreturn
- Returns a value back to the callerFor example, a function to add two numbers:
int add(int a, int b) { int sum = a + b; return sum; }
This function:
int
parametersint
resultTo use a function:
int result = add(2, 3); // Call function
The major benefits of functions are code reuse and organization.
Functions also enable separation of concerns - different functions handle different tasks.
Next we will use functions to structure object-oriented programs.
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:
make
, model
, year
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();
C++ classes have the following syntax:
class ClassName { // Members public: // Access specifier // Attributes // Methods };
ClassName
- Descriptive name like Car, Student, etcMembers
- Attributes and methods (functions)public
- Makes members accessibleMultiple access levels like private
also exist. We will cover that next.
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.
Class members can have different access levels:
public
- Accessible from anywhereprivate
- Accessible only within classprotected
- Accessible to class + subclassesFor 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.
In the previous section we learned basics of classes and objects. Now let's understand some more advanced object-oriented concepts:
These concepts help write modular, extensible, and reusable code.
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
numDoors
and openDoors()
This models an is-a relationship - a Car is a Vehicle.
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 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:
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).
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:
Let's go through each concept.
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 valueCommon pointer operations:
&var
int* ptr
ptr = &var
*ptr
to access valueptr = &otherVar
Pointers enable lower-level control and efficiency. But misuse can lead to bugs - pointer errors are infamous!
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
&
after type - int& y
References are safer and less error-prone than pointers. Use them to pass function arguments efficiently.
Variables declared normally occupy space on the stack:
int x = 5; // Stack
The heap allows allocating memory dynamically:
int* ptr = new int; // Heap *ptr = 7;
Overuse of heap can waste resources. Stack is better for local variables.
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 scopeshared_ptr
use reference countingSmart 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 C++ standard library provides a wealth of reusable data structures, algorithms, and functions. This STL helps avoid reinventing the wheel.
Some major components include:
Let's look at some commonly used parts of the STL.
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 }
push_back()
[]
Vectors grow efficiently as elements are added.
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"; }
[key]
to access elements.at(key)
also fetches, throws exception if missing.find(key)
returns end iterator if not foundMaps provide fast lookup by key.
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 typebegin()
points to first elementend()
points to after last element++itr
moves to next elementLearning 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.
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 conditioncatch
blockTo handle exceptions:
try { int result = divide(5, 0); } catch (std::invalid_argument& e) { std::cout << e.what(); }
try
block contains code that may throwcatch
block handles the errorcatch
blocks can be chainedThis separates error handling from normal program flow.
C++ defines various standard exception classes in <exception>
:
std::exception
- Base classstd::invalid_argument
- Invalid argumentsstd::out_of_range
- Index out of rangestd::runtime_error
- Recoverable runtime issuestd::logic_error
- Logic bug in codeDerive custom exception classes from std::exception
.
When an exception occurs:
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.
Modern systems involve multiple things happening at once or concurrently. C++ provides features for concurrent and parallel programming:
Let's go through the basics of concurrency in C++.
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.join()
blocks until thread finishThreads facility task parallelism in applications.
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 datam.lock()
begins synchronized sectionm.unlock()
ends itOnly one thread can lock the mutex at a time. This prevents concurrent access issues.
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 variablesfetch_XXX
are atomicPrefer 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.
We've covered the most essential C++ concepts so far. This section will briefly introduce some more advanced C++ capabilities:
Let's summarise each topic:
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
Templates work for any valid type while reusing common logic.
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++.
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!
To retain what you have learned so far, try building some simple C++ programs:
Some things to practice:
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.
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:
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
Copyright © 2024 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