1242.2 Langage C++ - 2025-2026
1. Introduction
2. Espaces de noms
3. Entrées/sorties standards
4. Passage de paramètres
5. Valeurs par défaut des paramètres
6. Surcharge des fonctions
7. Allocation dynamique
8. La classe
9. Divers : auto, range-for. etc.
10. Bibliothèque standard
1979 -
1983 - le nom C++ est créé pour "C incrémenté"
1998 - Le langage C++ est normalisé par l'ISO
2011 -
2014 - C++14 : mise à jour mineure
2017 - C++17 : mise à jour majeure (amélioration des templates, etc)
2020 - C++20 : mise à jour majeure (module, coroutines, etc.)
2023 - C++23 : mise à jour mineure, version courante
2026 - version en cours de développement
Le C++ est une extension du langage C (un compilateur C++ peut compiler du code C)
Le C++ est libre de droit
Au-delà de ~50'000 lignes de code, le C ne suffit plus
C++ contient la notion de classe, d'instances, d'héritage, etc.
C++ est surtout un langage multiparadigme
C++ est entièrement compatible avec C qui n'est pas un langage objet
On peut écrire un programme « C++ » sans jamais utiliser la notion d'objet
Pour programmer en C++, il « faut » connaître le langage C (notions & syntaxe)
En C++, il est possible :
Le C++ peut ne pas être "propre" : il hérite du C, de notions inutiles en POO
#include <iostream>
int main()
{
std::cout << "Hello world++!" << std::endl;
return 0;
}
Fonctionnalités avancées accessibles avec la bibliothèque standard C++
Les variables peuvent être déclarées n'importe où (comme en C99)
#include <print>
int main()
{
for (int i = 0; i < 3; ++i)
{
int x = i * 2;
std::println("{}", x);
}
return 0;
}
Une variable de type
Conversions avec
Entier non-nul :
0 :
Conversions avec les pointeurs
pointeur non-nul :
pointeur nul :
Grands projets ⇒ risque de collision de noms (variables et fonctions)
namespace language::english
{
std::string colors[] = {"White", "Red", "Black"};
void colorName(int index)
{
std::cout << "The color is: " << colors[index] << std::endl;
}
}
namespace language
{
namespace french
{
std::string colors[] = {"Blanc", "Rouge", "Noir"};
void colorName(int index)
{
std::cout << "La couleur est : " << colors[index] << std::endl;
}
}
}
using namespace language;
int main()
{
// GCC: error: 'colorName' was not declared in this scope
// colorName(1);
english::colorName(1);
{
using namespace french;
colorName(1); // -> "Rouge"
}
using namespace english;
colorName(1); // -> "Red"
french::colorName(1); // -> "Rouge"
using namespace french;
// GCC: error: call of overloaded 'colorName(int)' is ambiguous
// colorName(1);
return 0;
}
#include <iostream>
...
int n;
std::cin >> n; // Read from keyboard
std::cout << "val " << n; // Print to screen
Inclure
Accessibles dans l'espace de noms
#include <iostream>
int main()
{
...
std::cout << "val " << n; // Print to screen
}
#include <iostream>
using namespace std;
int main()
{
...
cout << "val " << n; // Print to screen
}
#include <iostream>
...
int j = 10;
std::cout << std::hex << std::nouppercase << j << std::endl;
std::cout << std::hex << std::uppercase << j << std::endl;
std::cout << std::dec << std::showpos << j << std::endl;
int N = 0;
std::cout << "Enter a number between 1 and 6: ";
while (!(std::cin >> N) || N < 1 || N > 6)
{
if (std::cin.fail())
{
std::cout << "Wrong input, try again: ";
std::cin.clear();
std::cin.ignore(256, '\n');
}
else
{
std::cout << "The number is out of range: ";
}
}
Entrez un chiffre entre 1 et 6 : abcdef
Saisie incorrecte, recommencez : -3
Le chiffre n'est pas entre 1 et 6: 17
Le chiffre n'est pas entre 1 et 6: 5
Inclure
#include <iostream>
#include <string>
#include <format>
#include <print>
// C++20: std::format and {:.2} instead of std::setprecision
double dbl = 3.1415926535897932384626433832795;
std::cout << std::format("{:.2f}", dbl) << std::endl;
std::cout << std::format("{:.8f}", dbl) << std::endl;
std::cout << std::format("{:.4e}", dbl) << std::endl;
std::cout << std::format("{:.2f}", dbl) << std::endl;
// C++23: print and println instead of std::cout and std::endl
std::string firstname = "Donald";
std::string lastname = "Knuth";
int answerToEverything = 42;
std::println("Hello, {} {}!", firstname, lastname);
std::print("The answer is = {}\n", answerToEverything);
Une référence à une variable de type
int i;
int &r = i; // r is a reference to i
r = 99; // affects i to 99
Alternative aux pointeurs
Surtout utilisées pour les passages de paramètres
void fn(int param_formel){...}
fn(param_effectif);
void fn(int *param_formel){...}
fn(¶m_effectif);
void fn(int ¶m_formel){...}
fn(param_effectif);
void fn(const int ¶m_formel){...}
fn(param_effectif);
Passer des paramètres modifiables aux fonctions, sans utiliser les pointeurs
void swap(int &a, int &b)
{
int t = a;
a = b;
b = t;
}
int x=2, y=3;
swap(x, y);
L'argument
double CalculerTout(monType pasTouche)
{
...
}
double CalculerTout(const monType &maRef)
{
...
}
3 significations différentes selon le contexte
int &r = i; // ?
p = &i; // ?
z = a&b; // ?
int& getRefOnCount()
{
static int count = 0;
return count;
}
int main()
{
std::println("Count: {}", getRefOnCount()++);
std::println("Count: {}", ++getRefOnCount());
}
Count: 0
Count: 2
#include <iostream>
#include <string>
#include <stdexcept>
const int N=2;
std::string tabNoms[N] = {"Bob", "John"};
int tabAges[N] = {20, 30};
int& age(const std::string &nom)
{
for (int i = 0; i < N; ++i)
{
if (nom == tabNoms[i])
{
return tabAges[i];
}
}
// If we are here, the name was not found
// See chapter on exceptions for more details
throw std::out_of_range("nom not found");
}
...
int main()
{
age("Bob") = 50;
age("John")++;
return 0;
}
Les valeurs sont précisées à la déclaration et non à la définition
Les paramètres peuvent être omis à l'appel
void trier(void *tab, int nbr, int size=100, bool up=true);
Appels possibles
trier(tab, nb, 4); // => size=4, up=true
trier(tab,nb); // => size=100, up=true
int add(int a, int b)
{
return a + b;
}
int add(int a, int b, int c)
{
return a + b + c;
}
double add(double a, double b)
{
return a + b;
}
double add(double a, double b, double c)
{
return a + b + c;
}
double *ptr = nullptr;
ptr = new double; // Réservation de mémoire
delete ptr; // Libération de mémoire
ptr = nullptr; // Sécurité
int *pTableau = nullptr;
pTableau = new int[10];
delete [] pTableau;
pTableau = nullptr;
En cas d'échec d'allocation,
// See chapter on exceptions for more details
try
{
// throws std::bad_alloc if no more memory is available
x = new int[1024 * 1024];
}
// See chapter on exceptions for more details
catch (const std::bad_alloc &e)
{
std::println("Memory allocation failed: {}", e.what());
}
int *ptr = new (std::nothrow) int[1024];
if(ptr == nullptr)
{
...
}
Type (classe) pour les chaînes en C++ :
Plus simple et plus sûr que
Gestion automatique/dynamique de la taille + opérateurs et fonctions dédiées
#include <string>
int main()
{
std::string x = "Hello";
// Or
// auto x = std::string("Hello");
// C++14: string literals
// Need to add "using namespace std::string_literals;"
using namespace std::string_literals;
auto s = "Hello"s;
}
Opérateurs
Affectation :
Concaténation :
Comparaisons :
Méthodes
Exemple
#include <iostream>
#include <string>
int main()
{
std::string x = "toto";
std::string y = x;
std::string z = x + "_" + y;
std::println("{} {} {}", x, y, z);
std::println("cap: {}, size: {}", z.capacity(), z.size());
return 0;
}
Affichage
toto toto toto_toto
cap: 15
size: 9
Conversion de
const char *ptr2char = "Hello";
std::string mystring(ptr2char);
Conversion de
std::string mystring = "Hello";
const char *ptr2char2 = nullptr;
ptr2char2 = mystring.c_str();
Les flux permettent de convertir des données en chaînes de caractères
La source ou la destination d'un flux peut être une chaîne de caractères
⇒ Les 2 sont constitués d'octets
Intérêts : conversions, transferts en mémoire (buffers)
Conversion de
#include <sstream>
int main()
{
std::ostringstream toto;
toto << 10;
std::string texte = toto.str();
}
Conversion de
#include <sstream>
int main()
{
std::istringstream titi("10");
int nombre;
titi >> nombre;
}
Fonctions dont le code est copié à chaque appel
Utilisées pour des fonctions courtes et fréquemment appelées
Macro en C
#define MAX(x,y) ((x)>(y)?(x):(y))
inline int max(int x, int y) { return x>y ? x : y; }
Les expressions
En C++, une structure peut aussi contenir des fonctions (méthodes)
Exemple
struct Vecteur
{
double x, y;
double longueur()
{
return (sqrt(x*x + y*y));
}
};
Vecteur v;
v.x=3.0; v.y=4.0;
v.longueur();
📌 Pas besoin de mentionner
Utiliser
Terminer les fichiers source par une ligne vide pour des raisons de compatibilité avec certains anciens outils qui peuvent ignorer une ligne se terminant par EOF
Utiliser
Utiliser
⇒ Très utile pour les itérateurs et les templates
int values[] = {10, 20, 26};
for (const auto& value : values)
{
std::println("{}", value);
}
Affichage
10
20
26
Structures de données classiques (avec les algorithmes associés)
Intégrée à la procédure de standardisation de C++
Basée sur les modèles de classes (conteneurs valables pour plusieurs classes/types différents)
Contient
Conteneurs
Objets permettant de stocker d'autres objets
Permettent de gérer les objets contenus : ajout, suppression, insertion
Itérateurs
Permettent de parcourir une collection d'objets sans avoir à se préoccuper de l'implémentation. Ceci permet d'avoir une interface de manipulation commune
Utilisation possible d'algorithmes comme tri, recherche, remplacement
2 types de conteneurs :
Les conteneurs séquentiels
Conteneurs dont les éléments sont ordonnés
On peut parcourir le conteneur suivant cet ordre et insérer ou supprimer un élément en un endroit explicitement choisi
Exemples : vecteurs, listes, piles, files, ...
Les conteneurs associatifs
Conteneurs dont les éléments sont identifiés par une clé et ordonnés suivant celle-ci
Pour insérer un élément, il n'est en théorie plus utile de préciser un emplacement
Exemples : dictionnaires, ensembles
Conteneurs séquentiels
Tableau dynamique contigu :
Tableau statique contigu :
File à double entrée :
Liste doublement chainée :
Liste simplement chainée :
Conteneurs associatifs
Dictionnaires (clé ⟷ valeur) :
Ensembles :
Adaptateurs de conteneurs
Files :
Piles :
#include <vector>
int main()
{
// {10, 11}
std::vector<int> myVector1{10,11};
// {10.0, 11.0}
std::vector<double> myVector2;
myVector2.push_back(10.0);
myVector2.push_back(11.0);
// {5, 5}
std::vector<int> myVector3(2,5);
// {10, 11}
myVector3[0]=10;
myVector3[1]=11;
...
}
for (int item : myVector1)
{
std::print("{} ", item);
}
for (const int& item : myVector1)
{
std::print("{} ", item);
}
for (const auto& item : myVector1)
{
std::print("{} ", item);
}
for (int i = 0; i < (int)myVector1.size(); i++)
{
std::print("{} ({}) ", myVector1[i], myVector1.at(i));
}
#include <iostream>
#include <vector>
#include <algorithm> // std::sort
int main()
{
std::vector<int> v{5, -4, 9, 5, 3, 0};
// Ascending order
std::sort(v.begin(), v.end());
// Descending order
std::sort(v.begin(), v.end(), std::greater<int>());
return 0;
}
#include <iostream>
#include <vector>
#include <string>
int main()
{
std::vector<std::string> v;
v.push_back("Introduction");
v.push_back("une phrase");
v.push_back("Conclusion");
for(int i = 0; i < v.size(); ++i)
{
std::println("{}", v[i]);
}
return 0;
}
#include <array>
int main()
{
std::array<int, 2> myArray1{10,11}; // 10 11
std::array<int, 2> myArray2{0}; // 0 0
std::array<int, 2> myArray3;
// myArray3.push_back(10); => not possible
std::array<int, 2> myArray4;
myArray4[0] = 10;
myArray4[1] = 11; // 10 11
return 0;
}
Il est possible d'imbriquer les conteneurs
On peut par exemple, créer un vecteur de listes de chaînes de caractères
La définition d'un type intermédiaire peut augmenter la lisibilité
Des objets
On peut initialiser une matrice identité M (5x5) avec le code suivant :
using Line = std::vector<double>;
using Matrix = std::vector<Line>;
Matrix m(5); // 5 lines
for(int i = 0; i < 5; ++i)
{
m[i].resize(5); // rows size is 5
for(int j = 0; j < 5; ++j)
{
if (i==j)
{
m[i][j]=1;
}
else
{
m[i][j]=0;
}
}
}