Guide de Référence C++ Moderne
Flux, Encapsulation, Polymorphisme, Surcharge, Amitié, Templates et Inline
1. Les fonctions de flux et de sécurisation (Entrées / Sorties)
La gestion des flux en C++ nécessite de la rigueur, notamment pour sécuriser les saisies utilisateur
contre les données inattendues et vider correctement la mémoire tampon du clavier.
#include <iostream>
#include <string>
#include <print> // Spécifique au C++23
int main() {
// 1. Affichage moderne (C++23)
std::println("--- Gestion des Flux ---");
int age;
std::print("Entrez votre âge : ");
std::cin >> age;
// 2. Sécurisation de la saisie
while (std::[Link]() || age < 0) {
std::cerr << "[Erreur] Saisie invalide. Veuillez entrer un nombre positif.
";
std::[Link](); // Réinitialise l'état du flux
std::[Link](10000, '
'); // Vide le tampon magique
std::print("Recommencez : ");
std::cin >> age;
}
// Nettoyage du tampon avant un getline
std::[Link](10000, '
');
// 3. Lecture d'une chaîne complexe
std::string nomComplet;
std::print("Entrez votre nom complet : ");
std::getline(std::cin, nomComplet);
std::println("Bonjour {}, vous avez {} ans.", nomComplet, age);
return 0;
}
2. Les méthodes de classes (L'Encapsulation)
L'encapsulation consiste à protéger les données d'un objet en les rendant privées, et à ne laisser l'accès
que via des méthodes publiques contrôlées (Accesseurs et Mutateurs) afin de préserver l'intégrité des
attributs.
1
#include <string>
#include <print>
class CompteBancaire {
private:
std::string titulaire;
double solde; // Attribut privé protégé
public:
// Constructeur paramétré
CompteBancaire(std::string p_titulaire, double p_soldeInitial)
: titulaire(p_titulaire), solde(p_soldeInitial > 0 ? p_soldeInitial : 0) {}
// Destructeur
~CompteBancaire() {
std::println("Fermeture du compte de {}", titulaire);
}
// Accesseur (Getter) - const garantit la lecture seule
double getSolde() const { return solde; }
std::string getTitulaire() const { return titulaire; }
// Mutateur (Setter) avec contrôle de sécurité
void crediter(double montant) {
if (montant > 0) {
solde += montant;
} else {
std::println("Erreur : Le montant doit être positif.");
}
}
};
3. Les fonctions virtuelles (Le Polymorphisme)
Le polymorphisme dynamique permet de manipuler des objets de classes dérivées (filles) à travers des
pointeurs ou références de la classe de base (mère), en résolvant l'appel de fonction à l'exécution grâce
au mot-clé virtual.
⚠️ Règle d'or : Si une classe possède au moins une fonction virtuelle, son destructeur doit
obligatoirement être déclaré virtuel pour éviter les fuites de mémoire lors de la destruction d'objets
polymorphes.
2
#include <memory>
#include <print>
class Ennemi {
public:
// Destructeur virtuel crucial
virtual ~Ennemi() { std::println("Destructeur d'Ennemi invoqué."); }
// Fonction virtuelle pure (rend la classe abstraite)
virtual void attaquer() const = 0;
};
class Boss : public Ennemi {
public:
~Boss() override { std::println("Destructeur de Boss invoqué (Libération propre)."); }
// override confirme la redéfinition explicite
void attaquer() const override {
std::println("Le Boss lance une attaque dévastatrice !");
}
};
int main() {
// Stockage polymorphique via un pointeur intelligent de la classe mère
std::unique_ptr<Ennemi> mechant = std::make_unique<Boss>();
mechant->attaquer(); // Appelle bien la méthode surchargée du Boss
return 0; // Destruction propre et ordonnée grâce au mécanisme virtuel
}
4. La Surcharge (Fonctions et Opérateurs)
La surcharge permet de déclarer plusieurs entités portant le même nom mais travaillant sur des
signatures de paramètres différentes (surcharge de fonctions) ou de réadapter les opérateurs natifs
pour nos propres structures (surcharge d'opérateurs).
3
#include <print>
#include <string_view>
class Vecteur2D {
private:
double x, y;
public:
Vecteur2D(double p_x = 0, double p_y = 0) : x(p_x), y(p_y) {}
// 1. Surcharge de fonction
void afficher() const { std::println("({}, {})", x, y); }
void afficher(std::string_view prefixe) const { std::print("{} ", prefixe);
afficher(); }
// 2. Surcharge d'opérateur membre (+)
Vecteur2D operator+ (const Vecteur2D& autre) const {
return Vecteur2D(x + autre.x, y + autre.y);
}
// Surcharge d'opérateur d'égalité (==)
bool operator== (const Vecteur2D& autre) const {
return (x == autre.x && y == autre.y);
}
};
5. Les fonctions amies (Friend)
Une fonction déclarée amie (friend) d'une classe obtient les privilèges complets d'accès à ses
membres privés et protégés tout en restant externe à celle-ci. C'est l'outil indispensable pour
surcharger des opérateurs symétriques externes comme l'injection de flux (<<).
#include <iostream>
class Position {
private:
int x;
int y;
public:
Position(int p_x, int p_y) : x(p_x), y(p_y) {}
// Déclaration d'amitié
friend std::ostream& operator<< (std::ostream& flux, const Position& pos);
};
// Définition externe de la fonction amie
std::ostream& operator<< (std::ostream& flux, const Position& pos) {
// Accès légitime aux variables privées x et y
flux << "Pos[" << pos.x << ", " << pos.y << "]";
return flux;
}
4
6. Les modèles de fonctions (Templates)
Les templates sous-tendent la programmation générique. Ils évitent la duplication de code pour des
algorithmes identiques agissant sur des types variables en laissant le compilateur instancier le code
machine requis lors de la phase de compilation.
#include <print>
#include <string>
// Modèle de fonction générique
template <typename T>
T trouverMaximum(T a, T b) {
return (a > b) ? a : b;
}
int main() {
std::println("Max (int) : {}", trouverMaximum(15, 42));
std::println("Max (double) : {}", trouverMaximum(3.14, 2.71));
return 0;
}
7. Les fonctions en ligne (Inline)
Le mot-clé inline est une directive puissante invitant le compilateur à substituer directement le corps
de la fonction à l'endroit de son appel. Cela élimine le surcoût lié aux sauts de pile mémoire tout en
préservant le contrôle strict des types (contrairement aux macros préprocesseurs complexes et
dangereuses).
#include <print>
// Remplacement direct et sécurisé sans effets de bord
inline int calculerCarre(int x) {
return x * x;
}
int main() {
int resultat = calculerCarre(5); // Remplacé par: int resultat = 5 * 5;
std::println("Le carré de 5 est {}", resultat);
return 0;
}