Cours C++ Complet đ
Les 16 chapitres essentiels pour apprendre le C++ â de la syntaxe de base au C++ moderne (C++20/23), avec exceptions, multithreading, fichiers, et 100+ exemples de code
9. La STL : Conteneurs
2. Variables et types de données
10. La STL : Algorithmes et lambdas
3. Opérateurs et flux I/O
11. Gestion mémoire moderne
4. Structures conditionnelles
12. Exceptions et gestion d'erreurs
5. Boucles et tableaux
13. Fichiers et flux (fstream)
6. Fonctions, enums et namespaces
14. Multithreading (std::thread)
7. POO : Classes et objets
15. C++ moderne (17/20/23)
8. Héritage, polymorphisme et templates
16. Bonnes pratiques et outils
đ Hub Programmation
đ§ C
đŠ Rust
â Java
đč Go
đ Python
đ C#
đïž POO
CHAPITRE 01
Introduction et premier programme
#include
int main()
// Avec using namespace (plus concis mais déconseillé dans les headers)
#include
using namespace std;
int main()
C++ vs C : C++ est un superset du C. Il ajoute la POO, les templates, la STL, les exceptions, les smart pointers, et bien plus. Tout code C valide est (presque) du C++ valide, mais le C++ moderne Ă©vite les patterns C (printf â cout, malloc â new/smart pointers).
g++ -std=c++20 -Wall -Wextra hello.cpp -o hello# Exécuter
./hello
# Avec clang++
clang++ -std=c++20 -Wall hello.cpp -o hello
# Avec CMake (projets multi-fichiers â standard en C++)
cmake -B build -DCMAKE_CXX_STANDARD=20
cmake âbuild build
| Caractéristique | C++ |
|---|---|
| Typage | Statique et fort |
| Paradigme | Multi-paradigme : POO + procédural + fonctionnel + générique |
| Compilation | Compilé en code machine natif (trÚs rapide) |
| Mémoire | Gestion manuelle (mais smart pointers en moderne) |
| Usage | Jeux (Unreal Engine), systÚmes, finance, embarqué, navigateurs (Chrome), IA/ML |
| Convention | PascalCase (classes), camelCase ou snake_case (variables/fonctions) |
| Standard actuel | C++23 (2024), C++26 en cours de développement |
CHAPITRE 02
Variables et types de données
#includeint main()
std::string s = « Hello World »;
s.length() // 11 (ou .size())
s.empty() // false
s.substr(0, 5) // « Hello »
s.find(« World ») // 6 (index, ou string::npos si pas trouvé)
s.replace(6, 5, « C++ ») // « Hello C++ »
s.append( » ! ») // « Hello C++ ! »
s[0] // 'H'
s.front() // 'H'
s.back() // '!'
s.starts_with(« He ») // true (C++20)
s.contains(« C++ ») // true (C++23)
// Comparaison avec == (pas besoin de strcmp !)
if (s == « Hello C++ ! »)
// Conversion
std::string n = std::to_string(42); // « 42 »
int val = std::stoi(« 42 »); // 42
double dval = std::stod(« 3.14 »); // 3.14
Toujours std::string en C++. Contrairement au C (char[]), std::string gÚre automatiquement la mémoire, supporte la concaténation avec +, la comparaison avec ==, et ne risque pas le buffer overflow.
int x = 10;
int& ref = x; // ref EST x (mĂȘme adresse mĂ©moire)
ref = 20; // x vaut maintenant 20// RĂ©fĂ©rence const â lecture seule
const int& cref = x;
cref = 30; // â Erreur â const
// Différences pointeur vs référence :
// Pointeur : peut ĂȘtre NULL, peut changer de cible, syntaxe * et &
// Référence : JAMAIS null, liée à vie, syntaxe transparente
CHAPITRE 03
Opérateurs et flux I/O
#include
#includeÂ
// C++20// Sortie â cout (chaĂźnable avec <<)
std::cout << « Nom: « << nom << « , Age: « << age << « n »;
// std::format (C++20) â comme f-string Python
std::cout << std::format(« Nom: , Age: n », nom, age);
std::cout << std::format(« Pi = n », 3.14159); // Pi = 3.14
// std::print (C++23) â encore plus simple
std::print(« Nom: , Age: n », nom, age);
// EntrĂ©e â cin
int age;
std::cout << « Votre ùge : « ;
std::cin >> age;
// Lire une ligne entiĂšre (avec espaces)
std::string ligne;
std::getline(std::cin, ligne);
// Tous les opérateurs C + :
// Scope resolution (::)
std::cout // cout dans le namespace std
MyClass::method // méthode de MyClass
// new / delete (allocation dynamique C++)
int* p = new int(42);
delete p;
int* arr = new int[10];
delete[] arr; // â ïž delete[] pour les tableaux
// Casts C++ (plus sûrs que le cast C)
static_cast<double>(7) / 2 // 3.5
dynamic_cast<Derived*>(basePtr) // Cast polymorphique (vérifié)
En C++ moderne, n'utilisez JAMAIS new/delete directement. Utilisez std::make_unique et std::make_shared (chapitre 11). Le new/delete nu est la source principale de memory leaks.
CHAPITRE 04
Structures conditionnelles
if (age < 18) else // if avec initialisation (C++17)
if (auto it = map.find(key); it != map.end())
// switch â int, char, enum
switch (choix)
// if constexpr (C++17) â Ă©valuĂ© Ă la compilation
template<typename T>
auto stringify(T value)
CHAPITRE 05
Boucles et tableaux
for (int i = 0; i < 5; i++) // Range-based for (C++11) â le plus utilisĂ©
std::vector<int> nums = ;
for (int n : nums)
// Par référence const (pas de copie, pas de modification)
for (const auto& n : nums)
// Par référence (pour modifier)
for (auto& n : nums)
#include// std::array â taille fixe (remplacement du C array)
std::array<int, 5> arr = ;
arr.size() // 5
arr[0] // 10
arr.at(10) // â LĂšve une exception si hors limites
// std::vector â taille dynamique (LE plus utilisĂ©)
std::vector<int> vec = ;
vec.push_back(4); // Ajouter Ă la fin
vec.pop_back(); // Retirer le dernier
vec.size() // 3
vec.empty() // false
vec.front() // 1
vec.back() // 3
vec.clear() // Vider
vec.erase(vec.begin()); // Supprimer le premier
RÚgle d'or : En C++ moderne, utilisez std::vector par défaut. N'utilisez les C arrays int arr[] que pour de l'embarqué ou du code trÚs contraint. std::array pour les tailles fixes connues à la compilation.
CHAPITRE 06
Fonctions, enums et namespaces
int square(int x) // Passage par const ref â gros objets (Ă©vite la copie)
void print(const std::string& s)
// Passage par rĂ©fĂ©rence â pour modifier
void increment(int& x)
// Valeurs par défaut
void greet(std::string name = « World »)
// Surcharge (overloading) â mĂȘme nom, types diffĂ©rents
int add(int a, int b)
double add(double a, double b)
// constexpr function â Ă©valuĂ©e Ă la compilation
constexpr int factorial(int n)
constexpr int f5 = factorial(5); // 120, calculé à la compilation
RĂšgle des paramĂštres : petits types (int, double) â par valeur. Gros objets (string, vector, classes) â par const rĂ©fĂ©rence. Quand on veut modifier â par rĂ©fĂ©rence.
enum Color ;// â enum class (C++11) â scoped, type-safe
enum class Color ;
enum class HttpStatus : int ;
Color c = Color::Red;
// int x = c; // â Pas de conversion implicite â type-safe !
switch (c)
double a = math::area(5.0);// Nested namespaces (C++17)
namespace company::project::module { void init() }
Jamais using namespace std; dans un header (.h). Cela pollue l'espace de noms de tous les fichiers qui incluent le header. Dans un .cpp, c'est toléré mais déconseillé en production.
CHAPITRE 07
POO : Classes et objets
private:
std::string name_;
int age_;public:
// Constructeur
Person(std::string name, int age)
: name_{std::move(name)}, age_{age} // Liste d'initialisation
// Getters
const std::string& name() const { return name_; }
int age() const { return age_; }
// Setter
void set_age(int age) { age_ = age; }
// Méthode
std::string greet() const {
return « Bonjour, je suis « + name_;
}
// Surcharge de l'opérateur <<
friend std::ostream& operator<<(std::ostream& os, const Person& p) {
os << p.name_ <<  » (« << p.age_ <<  » ans) »;
return os;
}
};
Person alice; // Uniform initialization
std::cout << alice << std::endl;
const aprĂšs une mĂ©thode signifie que la mĂ©thode ne modifie pas l'objet. Toutes les mĂ©thodes qui ne modifient pas l'Ă©tat doivent ĂȘtre const. C'est une convention fondamentale en C++.
struct Point ;// Rule of Five â si vous dĂ©finissez l'un, dĂ©finissez les 5 :
class Resource ;
// Rule of Zero (prĂ©fĂ©rĂ©) â si vous n'avez pas de ressource brute,
// ne définissez AUCUN des 5 et laissez le compilateur tout gérer
CHAPITRE 08
Héritage, polymorphisme et templates
protected:
std::string name_;
public:
Animal(std::string name) : name_{std::move(name)} // virtual = peut ĂȘtre surchargĂ©e (nĂ©cessaire pour le polymorphisme)
virtual std::string speak() const {
return name_ +  » fait du bruit »;
}
// Destructeur VIRTUEL â obligatoire si hĂ©ritage
virtual ~Animal() = default;
};
class Dog : public Animal {
public:
Dog(std::string name) : Animal{std::move(name)}
// override â vĂ©rifie Ă la compilation que la mĂ©thode parent existe
std::string speak() const override {
return name_ +  » : Wouf ! »;
}
};
// Polymorphisme â fonctionne avec pointeurs/rĂ©fĂ©rences
std::unique_ptr<Animal> a = std::make_unique<Dog>(« Rex »);
std::cout << a->speak(); // « Rex : Wouf ! »
Destructeur virtuel OBLIGATOIRE sur toute classe de base. Sans lui, delete sur un pointeur de base ne détruira pas correctement l'objet dérivé (memory leak/undefined behavior).
class Shape ;class Circle final : public Shape { // final = personne ne peut en hériter
double radius_;
public:
Circle(double r) : radius_{r}
double area() const override { return 3.14159 * radius_ * radius_; }
};
template<typename T>
T max_val(T a, T b) max_val(3, 7); // T = int â retourne 7
max_val(3.14, 2.71); // T = double â retourne 3.14
max_val
// Concepts (C++20) â contraindre le type
template<typename T>
concept Numeric = std::integral<T> || std::floating_point<T>;
template<Numeric T>
T add(T a, T b)
add(3, 4); // â
add(« a », « b »); // â string n'est pas Numeric
class Stack ;Stack<int> intStack;
intStack.push(42);
Stack
strStack.push(« hello »);
Concepts (C++20) remplacent SFINAE et les static_assert obscurs. Ils donnent des messages d'erreur clairs quand un type ne remplit pas le contrat. Similaire aux contraintes generics de TypeScript.
CHAPITRE 09
La STL : Conteneurs
| Conteneur | Description | AccĂšs |
|---|---|---|
| vector | Tableau dynamique (le plus utilisé) | O(1) par index |
| array | Tableau fixe | O(1) par index |
| deque | File à double extrémité | O(1) début/fin |
| list | Liste doublement chaßnée | O(n) accÚs, O(1) insertion |
| set | ĂlĂ©ments uniques, triĂ©s | O(log n) |
| unordered_set | ĂlĂ©ments uniques, hash | O(1) moyen |
| map | Clé/valeur, triées par clé | O(log n) |
| unordered_map | Clé/valeur, hash | O(1) moyen |
| stack | LIFO | O(1) top |
| queue | FIFO | O(1) front/back |
#include
std::unordered_map
,
{« Bob », 30},
};
// AccĂšs
ages[« Alice »] // 25 (â ïž crĂ©e une entrĂ©e si clĂ© absente)
ages.at(« Alice ») // 25 (lance exception si clé absente)
ages.count(« Eve ») // 0 (n'existe pas)
ages.contains(« Bob ») // true (C++20)
// Itérer
for (const auto& [nom, age] : ages)
// Insérer / supprimer
ages.insert();
ages.erase(« Bob »);
CHAPITRE 10
La STL : Algorithmes et lambdas
// [capture](params) -> retour auto add = [](int a, int b) ;
add(3, 4); // 7
// Captures
int x = 10;
auto f1 = [x]() ; // Copie de x
auto f2 = [&x]() ; // Référence vers x
auto f3 = [=]() ; // Copie de tout
auto f4 = [&]() ; // Référence à tout
// Generic lambda (C++14)
auto print = [](const auto& val) ;
#include
#include // C++20std::vector<int> v = ;
// Trier
std::sort(v.begin(), v.end()); //
std::sort(v.begin(), v.end(), std::greater<>()); // Décroissant
// Chercher
auto it = std::find(v.begin(), v.end(), 8);
bool found = std::binary_search(v.begin(), v.end(), 5); // O(log n)
// Transformer
std::vector<int> doubled;
std::transform(v.begin(), v.end(), std::back_inserter(doubled),[](int n) );
// Filtrer (C++20 Ranges)
auto evens = v | std::views::filter([](int n) );
// ChaĂźnage Ranges (C++20)
auto result = v
| std::views::filter([](int n) )
| std::views::transform([](int n) );
// Autres
std::count_if(v.begin(), v.end(), [](int n) );
std::accumulate(v.begin(), v.end(), 0); // Somme
std::min_element(v.begin(), v.end());
std::max_element(v.begin(), v.end());
std::any_of(v.begin(), v.end(), [](int n) );
std::all_of(v.begin(), v.end(), [](int n) );
C++20 Ranges = la révolution. Chaßnez les opérations avec le pipe |, comme les Streams Java ou LINQ C#. Plus besoin de begin()/end() partout.
CHAPITRE 11
Gestion mémoire moderne
#include
// unique_ptr â propriĂ©taire UNIQUE (pas de copie, move uniquement)
auto ptr = std::make_unique<Person>(« Alice », 25);
ptr->greet(); // Utilisation identique Ă un pointeur brut
// DĂ©truit automatiquement quand ptr sort du scope â
// Transférer la propriété
auto ptr2 = std::move(ptr); // ptr est maintenant nullptr
// shared_ptr â propriĂ©tĂ© partagĂ©e (compteur de rĂ©fĂ©rences)
auto sp1 = std::make_shared<Person>(« Bob », 30);
auto sp2 = sp1; // 2 shared_ptr pointent vers le mĂȘme objet
sp1.use_count() // 2
// Détruit quand le dernier shared_ptr est détruit
// weak_ptr â observe sans possĂ©der (Ă©vite les cycles)
std::weak_ptr<Person> wp = sp1;
if (auto locked = wp.lock())
RÚgle : jamais de new/delete nu. Utilisez make_unique (99% des cas) ou make_shared (propriété partagée). Les smart pointers garantissent la libération automatique et éliminent les memory leaks.
// = les ressources sont liées à la durée de vie d'un objet// Le destructeur nettoie automatiquement
{
std::vector<int> v = ; // Allocation
// ⊠utilisation de v âŠ
} // v dĂ©truit automatiquement, mĂ©moire libĂ©rĂ©e â
// Move semantics â transfĂ©rer au lieu de copier
std::vector<int> createBigVector()
std::vector<int> data = createBigVector(); // Move, O(1)
CHAPITRE 12
Exceptions et gestion d'erreurs
#include
double divide(double a, double b)
try catch (const std::invalid_argument& e) catch (const std::exception& e) catch (âŠ)
| Exception | Usage |
|---|---|
| std::runtime_error | Erreur Ă l'exĂ©cution (fichier introuvable, rĂ©seauâŠ) |
| std::invalid_argument | Argument invalide passé à une fonction |
| std::out_of_range | Index hors limites (vector::at()) |
| std::bad_alloc | Allocation mémoire échouée |
noexcept : marquez les fonctions qui ne lancent jamais d'exception avec noexcept. Le compilateur optimise mieux, et les conteneurs STL en profitent (move constructors noexcept utilisés par vector lors du redimensionnement).
Exceptions vs optional : pour les erreurs « attendues » (fichier absent, entrée invalide), std::optional ou std::expected (C++23) sont souvent préférés car ils n'ont pas le coût du déroulement de pile.
CHAPITRE 13
Fichiers et flux (fstream)
#include// Ăcrire dans un fichier
std::ofstream out(« data.txt »);
if (out.is_open()) // Fichier fermĂ© automatiquement (RAII) â
// Lire ligne par ligne
std::ifstream in(« data.txt »);
std::string line;
while (std::getline(in, line))
// Lire tout le fichier d'un coup
std::ifstream file(« data.txt »);
std::string content(
(std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>()
);
// std::filesystem (C++17) â manipuler chemins et fichiers
#include
namespace fs = std::filesystem;
fs::exists(« data.txt »); // true
fs::file_size(« data.txt »); // taille en octets
fs::remove(« old.txt »); // supprimer
for (auto& entry : fs::directory_iterator(« . »))
RAII pour les fichiers : pas besoin de .close() explicite. Le destructeur de fstream ferme automatiquement le fichier quand l'objet sort du scope. C'est la force du C++ moderne.
CHAPITRE 14
Multithreading (std::thread)
#include
#include// Créer un thread
void work(int id)
std::thread t1(work, 1);
std::thread t2(work, 2);
t1.join(); // Attendre la fin
t2.join();
// Mutex â protĂ©ger une ressource partagĂ©e
std::mutex mtx;
int counter = 0;
void safe_increment() // lock libéré automatiquement
// async â lancer une tĂąche et rĂ©cupĂ©rer le rĂ©sultat
auto future = std::async(std::launch::async, []() );
int result = future.get(); // Bloque jusqu'au résultat
Toujours utiliser std::lock_guard ou std::scoped_lock (C++17) pour les mutex. Ne jamais faire mtx.lock() / mtx.unlock() manuellement â risque de deadlock si une exception est lancĂ©e entre les deux.
std::jthread (C++20) est une version améliorée de thread qui appelle .join() automatiquement dans son destructeur (RAII). Préférez jthread quand votre compilateur le supporte.
CHAPITRE 15
C++ moderne (17/20/23)
auto [nom, age] = std::make_pair(« Alice », 25);
for (const auto& [key, val] : myMap) // std::optional â valeur qui peut ĂȘtre absente
std::optional<int> findAge(const std::string& name)
auto age = findAge(« Alice »);
if (age.has_value()) std::cout << *age;
int val = age.value_or(0);
// std::variant â union type-safe
std::variant<int, std::string> v = 42;
v = « hello »;
if (std::holds_alternative
// if constexpr â branches Ă©valuĂ©es Ă la compilation
// std::filesystem â manipuler fichiers/dossiers
// std::string_view â rĂ©fĂ©rence non-possĂ©dante vers une string
auto result = nums
| std::views::filter([](int n) )
| std::views::transform([](int n) )
| std::views::take(5);// Concepts â contraintes lisibles
templateT>
T gcd(T a, T b)
// Three-way comparison (spaceship operator)
auto r = 5 <=> 3; // std::strong_ordering::greater
// std::format â formatage type-safe
std::cout << std::format(« Pi =  », 3.14159);
// Coroutines (co_await, co_yield, co_return)
// Modules (import std; â remplace #include)
// Designated initializers
Point p = ;
// std::jthread â thread avec RAII (auto-join)
std::print(« Nom: , Age: n », « Alice », 25);
std::println(« Avec saut de ligne automatique »);// std::expected â gestion d'erreur sans exception
std::expected<int, std::string> parse_int(const std::string& s)
auto r = parse_int(« 42 »);
if (r.has_value()) std::cout << *r;
// string::contains (enfin !)
std::string s = « Hello C++23 »;
s.contains(« C++ »); // true
// std::flat_map â map basĂ©e sur des vecteurs triĂ©s (plus rapide)
// Deducing this â simplifie les patterns CRTP
// std::generator â gĂ©nĂ©rateur coroutine simple
// Multidimensional subscript operator: matrix[x, y]
// if consteval â tester si on est Ă©valuĂ© Ă la compilation
std::expected (C++23) est l'alternative moderne aux exceptions pour les erreurs « attendues ». Comme Result
optional exprime explicitement qu'une valeur peut ĂȘtre prĂ©sente ou absente, de façon type-safe.CHAPITRE 16
Bonnes pratiques et outils C++
â
Ă FAIRE
âą -std=c++20 -Wall -Wextra
⹠auto quand le type est évident
âą const et constexpr partout
âą make_unique / make_shared
⹠vector par défaut
âą string_view pour les paramĂštres
âą Ranges pour les algorithmes
âą override / final explicit
âą RAII (pas de resource leak)
âą enum class au lieu de enum
âą noexcept sur les move constructors
â Ă ĂVITER
âą new / delete nus
âą C arrays int arr[]
âą using namespace std dans les headers
âą printf / scanf (utiliser cout / format)
âą C-style casts (int)x
âą malloc / free (c'est du C)
âą Macros pour les constantes (#define)
âą Retourner des raw pointers
⹠Variables non initialisées
âą mtx.lock() sans lock_guard
| Outil | Usage |
|---|---|
| CMake | SystĂšme de build standard â CMakeLists.txt |
| clang-tidy | Linter â dĂ©tecte les mauvaises pratiques |
| AddressSanitizer | -fsanitize=address â dĂ©tecte les accĂšs mĂ©moire invalides |
| Valgrind | Détecte les memory leaks à l'exécution |
| clang-format | Formatage automatique du code |
| Conan / vcpkg | Gestionnaires de paquets C++ |
| Compiler Explorer | godbolt.org â voir l'assembleur gĂ©nĂ©rĂ© en ligne |
optional exprime explicitement qu'une valeur peut ĂȘtre prĂ©sente ou absente, de façon type-safe.đ Hub Programmation
đ§ Cours C
đŠ Cours Rust
â Cours Java
đč Cours Go
đ Cours Python
đ Cours C#
đïž Cours POO
đ§ź Algorithmes
đ Structures de donnĂ©es
âš Clean Code
Cours C++ Complet â Des bases au C++ moderne (C++20/23)
Référence : cppreference.com | isocpp.org
