C++
En 1979, Bjarne Stroustrup travaille à son doctorat et trouve de nombreuses fonctionnalités intéressantes au langage Simula. Mais il n’était pas aussi performant que le langage C, qui lui, était de trop bas niveaux.

En 1980, dans les laboratoires Bell d'AT&T, Stroustrup commence à améliorer le langage C en lui ajoutant la prise en charge de classe, de dérivation, du polymorphisme, etc. Bref, en lui faisant supporter le paradigme orienté objet. D’ailleurs, son nom de code était : « C with classes » mais, en 1983, il fut nommé « C++ », faisant un clin d’oeil à la syntaxe du langage.
Il est facile de se tirer dans le pied avec le langage C; c’est plus difficile avec le langage C++ mais, lorsque vous y arrivez, c’est la jambe en entier qui explose.
- Bjarne Stroustrup
Pointeur
Un pointeur est une variable comme une autre, à l'exception qu'elle contient une adresse de la mémoire centrale plutôt qu'une valeur.
Déclaration
Le caractère *, lors de la déclaration, permet d'indiquer qu'une variable est un pointeur :
int entier; // Valeur entière.
int* pEntier; // Adresse en mémoire centrale où se trouve une valeur entière.
Déréférencement
Il est possible d'obtenir l'adresse en mémoire centrale d'une variable en la faisant précéder du caractère & :
int entier = 42;
int* pEntier = &entier;
Allocation
L'instruction new permet de réserver un espace en mémoire centrale selon la taille du type, et retourne l'adresse en mémoire centrale de l'espace réservé :
pEntier = new int(42);
Tableau
Pour réserver un espace mémoire pour un tableau :
int* pTabEntiers = new int[TAILLE];
Indirection
Le caractère *, lors de l'utilisation d'une variable pointeur, permet d'accéder à la valeur située à l'adresse en mémoire centrale que contient cette variable pointeur :
*pEntier = 404;
entier = *pEntier;
Libération
Tout espace réservé en mémoire centrale doit aussi être libéré avec l'instruction delete :
delete pEntier;
Tableau
Pour libérer l'espace mémoire d'un tableau :
delete[] pTabEntiers;
Classe
Les classes sont les entités de bases du paradigme orienté objet.
Déclaration
Le mot-clé class permet de déclarer une classe avec l'identificateur de notre choix :
class Identificateur {
// Contenu de la classe.
};
Modificateurs d'accès
Les modificateurs d'accès private et public permettent de limiter l'accès aux membres sensibles :
| Accès | U.M.L. | Description |
|---|---|---|
| public | + | Accessible de l'implémentation de la classe et de ses instances. |
| private | - | Accessible seulement à partir de l’implémentation de la classe. |
Un modificateur d'accès s'applique à tout ce qui le suit :
class Identificateur {
public:
// Déclarations publiques.
private:
// Déclaration privées.
};
Il n’y a pas d’ordre à suivre ; les répétitions sont autorisées ; et si aucun modificateur d’accès n’est spécifié, l’accès private sera appliqué par défaut.
Amie
Une classe amie peut accéder aux membres privés :
class Identificateur {
friend class IdentificateurClasseAmie;
// Contenu de la classe.
};
Données membres
On nomme « donnée membre » les variables déclarées à l'intérieur d'une classe :
/// @brief Représentation d'un entier.
class Entier {
private:
int* entier; ///< Pointeur vers une valeur entière.
};
Méthodes
On nomme « méthode » les fonctions déclarées à l'intérieur d'une classe :
/// @brief Représentation d'un entier.
class Entier {
public:
/// @brief Vérification de la parité.
/// @return Si la valeur est impaire.
bool estImpair() {
return *entier % 2;
}
private:
int* entier; ///< Pointeur vers une valeur entière.
};
Constructeur
Méthode particulière, puisqu'elle est appelée automatiquement lors de l'instanciation.
Puisqu'il s'agit d'une méthode que le compilateur doit différencier des autres méthodes, sa syntaxe comporte quelques exigences :
- Aucun type de retour.
- Le même identificateur que la classe.
Le constructeur est principalement utilisé pour initialiser les données membres :
/// @brief Représentation d'un entier.
class Entier {
public:
/// @brief Constructeur.
/// @param valeur Valeur d'initialisation.
Entier(int valeur) {
entier = new int(valeur);
}
/// @brief Vérification de la parité.
/// @return Si la valeur est impaire.
bool estImpair() {
return *entier % 2;
}
private:
int* entier; ///< Pointeur vers une valeur entière.
};
Défaut
S'il n'a aucun paramètre, on le nomme « constructeur par défaut » :
/// @brief Représentation d'un entier.
class Entier {
public:
/// @brief Constructeur par défaut.
Entier() {
entier = new int();
}
/// @brief Constructeur.
/// @param valeur Valeur d'initialisation.
Entier(int valeur) {
entier = new int(valeur);
}
/// @brief Vérification de la parité.
/// @return Si la valeur est impaire.
bool estImpair() {
return *entier % 2;
}
private:
int* entier; ///< Pointeur vers une valeur entière.
};
Destructeur
Mêmes exigences que le constructeur, mais l'identificateur doit être précédé du caractère tilde (~). Le destructeur est appelé automatiquement lors de la libération :
/// @brief Représentation d'un entier.
class Entier {
public:
Entier() {
entier = new int();
}
/// @brief Constructeur.
/// @param valeur Valeur d'initialisation.
Entier(int valeur) {
entier = new int(valeur);
}
/// @bried Destructeur.
~Entier() {
delete entier;
}
/// @brief Vérification de la parité.
/// @return Si la valeur est impaire.
bool estImpair() {
return *entier % 2;
}
private:
int* entier; ///< Pointeur vers une valeur entière.
};
Opérateurs
...
/// @brief Représentation d'un entier.
class Entier {
public:
Entier() {
entier = new int();
}
/// @brief Constructeur.
/// @param valeur Valeur d'initialisation.
Entier(int valeur) {
entier = new int(valeur);
}
/// @bried Destructeur.
~Entier() {
delete entier;
}
/// @brief Vérification de la parité.
/// @return Si la valeur est impaire.
bool estImpair() {
return *entier % 2;
}
/// @brief Opérateur de conversion.
/// @return Valeur entière.
operator int() {
return *entier;
}
private:
int* entier; ///< Pointeur vers une valeur entière.
};
Instance
On nomme « instance » les variables ayant une classe comme type.
Instanciation
L'instanciation consiste à allouer l'espace en mémoire centrale et initialiser son contenu à l'aide du constructeur :
Entier entierA; // Instance d'un entier.
Entier entierB(42); // Instance d'un entier initialisé à la valeur 42.
Pointeur d'instance
Il est aussi possible d'avoir des pointeurs d'instance :
Entier* entierC = new Entier(); // Pointeur vers une instance d'un entier.
Entier* entierD = new Entier(404); // Pointeur vers une instance d'entier initialisé à la valeur 404.
L'instruction new effectue, dans l'ordre, 3 étapes :
- Allocation d'un espace en mémoire centrale pour stocker les données de l'instance.
- Appel du constructeur de l'instance.
- Retour de l'adresse de l'instance en mémoire centrale.
Libération
Les instances sont libérées de la mémoire centrale au même moment que les variables locales, et leur contenu à l'aide du destructeur.
Pointeur d'instance
Pour libérer une instance à partir d'un pointeur :
delete entierC; // Libération de l'instance pointée par « entierC ».
delete entierD; // Libération de l'instance pointée par « entierD ».
L'instruction delete effectue, dans l'ordre, 2 étapes :
- Appel du destructeur de l'instance.
- Libération de l'espace en mémoire centrale des données de l'instance.
Exception
Ce langage comporte un mécanisme de gestion d'exceptions.
Type
Le fichier d'en-tête stdexcept déclare plusieurs types standards, dont des erreurs logiques :
| Type | Exception | Description |
|---|---|---|
| logic_error | length_error | Dépassement de capacité. |
| out_of_range | Hors de portée. | |
| ... | ... | ... |
Déclenchement
L'instruction throw permet de déclencher une exception :
throw length_error("Depassement de capacite!");
Gestion
Il est possible d'intercepter des exceptions afin d'agir en conséquence plutôt que de faire planter le programme :
try {
// Instructions pouvant déclencher une exception logique.
}
catch (logic_error exception) {
cout << exception.what() << endl;
}
Chaîne de caractères
La classe string est une structure de données qui permet de manipuler les chaînes de caractères de façon beaucoup plus conviviale :
#include <string>
Affectation
Il est maintenant possible d'affecter une chaîne de caractères à tout moment :
std::string chaine = "Initialisation";
chaine = "Affectation";
Caractères
Il est encore possible d'accéder aux caractères que comporte une chaîne comme s'il s'agissait d'un tableau :
std::string chaine = "Caracteres";
char caractere = chaine[4]; // 'c'
Concaténation
Il est maintenant possible de concaténer des chaînes de caractères avec l'opérateur + :
std::string chaineA = "Une ";
std::string chaineB = "chaine ";
std::string chaineC = chaineA + chaineB + "de caractères";
Conversions
Des fonctions permettent de passer d'un nombre à une chaîne de caractères et vice-versa.
Chaîne de caractères à entier
La fonction stoi (string to int) permet de convertir une chaîne de caractères en entier :
std::string chaine = "42";
int entier = stoi(chaine);
Entier à chaîne de caractères
La fonction to_string permet de convertir un entier ou un réel en chaîne de caractères :
int entier = 42;
std::string chaine = std::to_string(entier);
Fichier texte
En langage C++, la manipulation de flux de données est plus uniforme, et incorpore aussi les fichiers.
#include <fstream>
Types
Il y a deux types pour déclarer des variables permettant de manipuler des fichiers :
ifstream fichierEntree; // Fichier en lecture.
ofstream fichierSortie; // Fichier en écriture.
Accès
Pour ouvrir un fichier :
fichierEntree.open("NomFichier.ext");
Il est possible de vérifier si un fichier a bien été ouvert :
if (fichierEntree.isOpen()) { // ...
Il peut être utile, pour s'assurer que les données ont été écrites, de fermer un fichier :
fichierSortie.close();
Données
Il y a plusieurs façons de lire et d'écrire dans un fichier. Mais tous se font de façon séquentiel, c'est-à-dire que la prochaine lecture ou écriture se fait à partir de la fin de la lecture ou de l'écriture précédente.
Lecture
Pour stocker dans une variable une donnée lue dans un fichier :
string mot;
fichierEntree >> mot; // Lecture du premier mot.
fichierEntree >> mot; // Lecture du deuxième mot.
Ce type de lecture s'arrêtera automatiquement à chaque espace et à chaque saut de ligne.
Pour lire toute une ligne, en s'arrêtant uniquement à un saut de ligne :
string ligne;
getline(fichierEntree, ligne); // Lecture de la première ligne.
getline(fichierEntree, ligne); // Lecture de la deuxième ligne.
Et pour ignorer la lecture de caractères :
fichierEntree.ignore(n);
Ou n est le nombre de caractères à ignorer.
Écriture
Pour stocker dans un fichier le contenu d'une variable :
string chaine = "Une chaîne de caractères.";
fichierSortie << chaine << endl; // Écriture de la chaîne de caractères suivie d'un saut de ligne.