JN
Accueil
> Cours
> Programmez en orienté objet avec C++
> Découvrez la notion de POO
Programmez en orienté objet avec C++
10 heures Difficile
Mis à jour le 10/02/2022
Découvrez la notion de POO
L'idée de la programmation orientée objet, c'est de manipuler dans son code source des
éléments que l'on appelle des "objets". Dans un programme, cela peut être une fenêtre ou encore
un bouton, et il s'agit d'un mélange de plusieurs variables et fonctions.
Nous n'allons pas voir tout de suite comment faire pour créer des objets, en revanche nous allons
apprendre à en utiliser un.
Comprenez d'abord le fonctionnement de string
Dans ce chapitre, nous allons nous pencher sur le cas de string .
J'ai déjà utilisé le type string , ce n'est pas une nouveauté pour moi ! C'est le type qui
permet de stocker du texte en mémoire, c'est cela ?
Oui ! Mais le type string est différent des autres.
int , bool , float , double sont des types qui stockent des données très
simples.
Ce n'est pas le cas de string qui est en fait... un objet !
Je vais vous montrer comment fonctionne string "à l'intérieur du cube". Préparez-vous à d'horribles
vérités.
Horrible vérité n° 1 : Pour un ordinateur, les lettres n'existent pas…
L'avantage des objets est de masquer la complexité du code à l'utilisateur. Et justement, les choses sont
compliquées parce que, à la base, un ordinateur ne sait pas gérer du texte ! Oui, l'ordinateur n'est
véritablement qu'une grosse machine à calculer dénuée de sentiments. Il ne reconnaît que des nombres.
Mais alors, si l'ordinateur ne peut manipuler que des nombres, comment se fait-il qu'il puisse
afficher du texte à l'écran ?
Grâce à une astuce que l'on utilise depuis longtemps !
La table ASCII (American Standard Code for Information Interchange) est un tableau qui sert de
convention pour convertir des nombres en lettres.
Nombre Lettre Nombre Lettre
64 @ 96 '
65 A 97 a
66 B 98 b
67 C 99 c
68 D 100 d
69 E 101 e
70 F 102 f
71 G 103 g
72 H 104 h
73 I 105 i
Nombre Lettre Nombre Lettre
74 J 106 j
75 K 107 k
76 L 108 l
77 M 109 m
Comme vous le voyez :
la lettre « A » majuscule correspond au nombre ;
la lettre « a » minuscule correspond au nombre ;
etc.
Tous les caractères utilisés en anglais figurent dans cette table.
C'est pour cela que les caractères accentués ne sont, de base, pas utilisables en C++ : ils
n'apparaissent pas dans la table ASCII.
Alors, à chaque fois que l'ordinateur voit le nombre , il prend cela pour la lettre A ?
Non, l'ordinateur ne traduit un nombre en lettre que si on le lui demande. En pratique, on se base sur le
type de la variable pour savoir si le nombre stocké est véritablement un nombre ou, en réalité, une lettre :
Si on utilise le type int pour stocker le nombre , l'ordinateur considérera que c'est un
nombre.
En revanche, si on utilise le type char pour stocker le nombre , l'ordinateur se dira "C'est la
lettre A".
Le type char (abréviation de "character", caractère, en français) est prévu pour stocker un
caractère. Il stocke donc un nombre qui est interprété comme un caractère.
Un char ne peut stocker qu'un seul caractère ? Comment fait-on alors pour stocker une
phrase entière ?
Eh bien, là non plus, ce n'est pas simple ! C'est un autre problème que nous allons voir...
Horrible vérité n° 2 : Les textes sont des tableaux de char
Puisque char ne peut stocker qu'une seule lettre, les programmeurs ont eu l'idée de créer... un
tableau de char ! Mais ça, vous le saviez déjà.
Les tableaux permettant de retrouver côte à côte en mémoire plusieurs variables d'un même
type, ils sont le moyen idéal de stocker du texte.
On parle aussi de "chaînes de caractères", vous comprenez maintenant pourquoi.
Ainsi, il suffit de :
déclarer un tableau de char pour pouvoir stocker du texte (environ 100 caractères) :
cpp
1 char texte[100];
ou utiliser un vector si on veut changer la longueur du texte :
cpp
1 vector<char> texte;
Le texte n'est donc en fait qu'un assemblage de lettres, stocké en mémoire dans un tableau :
T e x t e
Chaque case correspond à un char . Tous ces char mis côte à côte forment du texte.
En théorie, on pourrait se débrouiller avec des tableaux statiques ou dynamiques de char à
chaque fois que l'on veut manipuler du texte. Mais ce serait fastidieux. C'est pour ça que les
concepteurs du langage ont décidé de cacher tout ces mécanismes dans une boîte fermée, un
objet.
Gérer du texte n'est pas vraiment simple. Il faut :
créer un tableau de char dont chaque case correspond à un caractère ;
prévoir une taille suffisante pour stocker le texte que l'on souhaite sinon cela plante...
Bref, cela fait beaucoup de choses auxquelles il faut penser.
C'est là qu'intervient la programmation orientée objet : un développeur place le tout dans un cube facile
à utiliser où il suffit d'appuyer sur des boutons. Ce cube, c'est l'objet string .
Créez un objet string
Vous le savez déjà, la création d'un objet ressemble beaucoup à la création d'une variable classique
comme int ou double :
cpp
1 #include <iostream>
2 #include <string> // Obligatoire pour pouvoir utiliser les objets string
4 using namespace std;
7 int main()
8 {
9 string maChaine; //Création d'un objet 'maChaine' de type string
10
11 return 0;
12 }
Pour pouvoir utiliser des objets de type string dans le code, il est nécessaire d'inclure l'en-tête de la
bibliothèque string . C'est ce que j'ai fait à la deuxième ligne.
Intéressons-nous maintenant à la ligne où je crée un objet de type string ...
Donc... on crée un objet de la même manière qu'on crée une variable ?
Il y a plusieurs façons de créer un objet, celle que vous venez de voir est la plus simple. Et, oui, c'est
exactement comme si on avait créé une variable !
Mais... comment on fait pour différencier les objets des variables ?
C'est bien tout le problème : variables et objets se ressemblent dans le code. Pour éviter la confusion, il
y a des conventions. La plus célèbre d'entre elles est la suivante :
le type des variables commence par une minuscule (ex. : int) ;
le type des objets commence par une majuscule (ex. : Voiture).
Je sais ce que vous allez me dire :
string ne commence pas par une majuscule alors que c'est un objet !
Il faut croire que les créateurs de string ne respectaient pas cette convention. Mais
rassurez-vous, maintenant la plupart des gens mettent une majuscule au début de leurs objets
(moi y compris, ce ne sera donc pas la foire dans la suite de ce cours).
En réalité, lorsque vous serez habitué à penser avec des objets, vous verrez qu'une telle
distinction n'est pas nécessaire. Il y a bien d'autres manières de distinguer les types des
variables des types des objets. La première étant la façon dont les objets sont utilisés.
Initialisez la chaîne lors de la déclaration
Pour initialiser notre objet au moment de la déclaration (et donc lui donner une valeur), il y a plusieurs
possibilités.
La plus courante consiste à ouvrir des parenthèses comme nous l'avons fait jusqu'ici :
cpp
1 int main()
2 {
3 string maChaine("Bonjour !");
4 //Création d'un objet 'maChaine' de type string et initialisation
6 return 0;
7 }
C'est la technique classique que l'on connaît déjà, et qui s'applique aussi bien aux variables qu'aux
objets. On dit que l'on construit l'objet.
Et comme pour les variables, il faut noter que l'on peut aussi initialiser avec le signe égal :
string maChaine = "Bonjour !";
On a maintenant créé un objet maChaine qui contient la chaîne "Bonjour !".
On peut l'afficher comme n'importe quelle chaîne de caractères avec un cout :
cpp
1 int main()
2 {
3 string maChaine("Bonjour !");
4 cout << maChaine << endl;
5 //Affichage du string comme si c'était une chaîne de caractères
7 return 0;
8 }
Bonjour !
Affectez une valeur à la chaîne après déclaration
Maintenant que notre objet est créé, ne nous arrêtons pas là. Changeons le contenu de la chaîne après
sa déclaration :
cpp
1 int main()
2 {
3 string maChaine("Bonjour !");
4 cout << maChaine << endl;
6 maChaine = "Bien le bonjour !";
7 cout << maChaine << endl;
9 return 0;
10 }
Bonjour !
Bien le bonjour !
Pour changer le contenu d'une chaîne après sa déclaration, on doit obligatoirement utiliser le
symbole = .
Tout cela, vous savez déjà le faire. Ce que je veux vous montrer ici, c'est comment la magie de la POO
opère :
1. Vous, l'utilisateur, vous avez appuyé sur un bouton pour dire : Je veux maintenant que la chaîne à
l'intérieur devienne "Bien le bonjour !".
2. À l'intérieur de l'objet, des mécanismes (des fonctions) se sont activés lorsque vous avez réalisé
l'opération. Ces fonctions ont vérifié, entre autres, s'il y avait de la place pour stocker la chaîne
dans le tableau de char .
3. Elles ont vu que non. Elles ont alors créé un nouveau tableau de char , suffisamment long
cette fois, pour stocker la nouvelle chaîne.
4. Et, tant qu'à faire, elles ont détruit l'ancien tableau qui ne servait plus à rien, puis les nouvelles
lettres ont été copiées.
Mais permettez-moi de vous parler franchement : ce qui s'est passé à l'intérieur de l'objet, on s'en fiche
royalement ! C'est bien là tout l'intérêt de la POO : l'utilisateur n'a pas besoin de comprendre comment
cela fonctionne à l'intérieur. On se moque de savoir que le texte est stocké dans un tableau de char
(ou est-ce un vector ?). L'objet est en quelque sorte intelligent et gère tous les cas. Nous, nous
nous contentons de l'utiliser.
Assemblez des chaînes de caractères
Imaginez que l'on souhaite concaténer (assembler) deux chaînes. En théorie, c'est compliqué à faire car
il faut fusionner deux tableaux de char . En pratique, la POO nous évite de nous soucier du
fonctionnement interne :
cpp
1 int main()
2 {
3 string chaine1("Bonjour !");
4 string chaine2("Comment allez-vous ?");
5 string chaine3;
7 chaine3 = chaine1 + chaine2; // 3... 2... 1... Concaténatioooooon
8 cout << chaine3 << endl;
10 return 0;
11 }
Bonjour !Comment allez-vous ?
À L'affichage, il manque une espace au milieu. On n'a qu'à changer la ligne de la concaténation :
cpp
1 chaine3 = chaine1 + " " + chaine2;
Résultat :
Bonjour ! Comment allez-vous ?
C'est très simple à utiliser alors que "derrière", ça s'active pour assembler les deux tableaux de char .
Comparez des chaînes de caractères
On peut comparer des chaînes entre elles à l'aide des symboles == (identique) ou != (différent)
dans un if :
cpp
1 int main()
2 {
3 string chaine1("Bonjour !");
4 string chaine2("Comment allez-vous ?");
6 if (chaine1 == chaine2) // Faux
7 {
8 cout << "Les chaines sont identiques." << endl;
9 }
10 else
11 {
12 cout << "Les chaines sont differentes." << endl;
13 }
14
15 return 0;
16 }
Les chaines sont differentes.
À l'intérieur de l'objet, la comparaison se fait caractère par caractère entre les deux tableaux de char
(à l'aide d'une boucle qui compare chacune des lettres). Nous, nous n'avons pas à nous soucier de tout
cela : nous demandons à l'objet chaine1 s'il est identique à chaine2 ; il fait des calculs et nous
répond très simplement par un oui ou un non.
Dans la suite du cours, nous allons apprendre comment faire pour écrire de tels objets, où toutes les
opérations complexes sont cachées. Vous pourrez alors utiliser ces boîtes dans d'autres parties de votre
programme, sans avoir à vous soucier ni même à vous rappeler de leur fonctionnement.
Faites des opérations sur les string
Comme tout objet qui se respecte, le type string propose un nombre important d'autres
fonctionnalités qui permettent de faire tout ce dont on a besoin. Voyons les principales.
Retenez le vocabulaire de base en POO : "Attribut" et "méthode"
Je vous avais dit qu'un objet était constitué de variables et de fonctions.
En fait, le vocabulaire est un peu différent avec les objets :
1. Les variables contenues à l'intérieur des objets sont appelées "attributs". On parle aussi
de variables membres.
2. Les fonctions sont appelées "méthodes". On parle aussi de fonctions membres.
Imaginez que chaque méthode (fonction) que propose un objet corresponde à un bouton différent sur la
face avant du cube. Pour appeler la méthode d'un objet, on utilise une écriture que vous avez déjà vue :
objet.methode() . On sépare le nom de l'objet et le nom de la méthode par un point.
Cela signifie :
"Sur l'objet indiqué, j'appelle cette méthode".
Traduction : "Sur le cube indiqué, j'appuie sur ce bouton pour déclencher une action".
En théorie, on peut aussi accéder aux variables membres (les attributs) de l'objet de la même
manière. Cependant, en POO, il y a une règle très importante : l'utilisateur ne doit pas pouvoir
accéder aux variables membres, mais seulement aux fonctions membres (les méthodes). On en
reparlera plus en détail juste après ce chapitre.
Je vous avais dit qu'il était facile de distinguer les objets des variables car on les utilisait
différemment. Voici donc un premier exemple. La notation avec le point pour appeler une
méthode de l'objet est propre aux objets. On ne peut pas faire ça avec les variables.
Utilisez les méthodes du type string
La méthode size()
Vous le savez déjà, la méthode size() permet de connaître la longueur de la chaîne actuellement
stockée dans l'objet de type string .
Cette méthode ne prend aucun paramètre et renvoie la longueur de la chaîne. Vous venez de découvrir
qu'il s'agit d'une règle générale, mais nous l'avions déjà fait avant ; il faut appeler la méthode de la
manière suivante :
cpp
1 maChaine.size()
Essayons cela dans un code complet qui affiche la longueur d'une chaîne de caractères :
cpp
1 int main()
2 {
3 string maChaine("Bonjour !");
4 cout << "Longueur de la chaine : " << maChaine.size();
6 return 0;
7 }
Longueur de la chaine : 9
La méthode erase()
Cette méthode très simple supprime tout le contenu de la chaîne :
cpp
1 int main()
2 {
3 string chaine("Bonjour !");
4 chaine.erase();
5 cout << "La chaine contient : " << chaine << endl;
7 return 0;
8 }
La chaine contient :
Comme on pouvait s'y attendre, la chaîne ne contient plus rien.
Notez que c'est équivalent à chaine = ""; .
La méthode substr()
Cette méthode permet d'extraire une partie de la chaîne stockée dans une string .
substr signifie "substring", soit "sous-chaîne" en français.
Tenez, on va regarder son prototype, vous allez voir que c'est intéressant :
cpp
1 string substr( size_type index, size_type num = npos );
Cette méthode renvoie donc un objet de type string .
Ce sera la sous-chaîne obtenue après découpage.
Elle prend deux paramètres ou, plus exactement, un paramètre obligatoire et un paramètre facultatif. En
effet, num possède une valeur par défaut ( npos ), ce qui fait que le second paramètre ne doit pas
obligatoirement être renseigné.
Voyons plus en détail ce qui se cache sous ces paramètres :
1. index permet d'indiquer à partir de quel caractère on doit couper (ce doit être un numéro de
caractère).
2. num permet d'indiquer le nombre de caractères que l'on prend. Par défaut, la valeur est npos
, ce qui revient à prendre tous les caractères qui restent. Si vous indiquez 2, la méthode ne
renverra que 2 caractères.
Allez, un exemple sera plus parlant, je crois :
cpp
1 int main()
2 {
3 string chaine("Bonjour !");
4 cout << chaine.substr(3) << endl;
6 return 0;
7 }
jour !
On a demandé à couper à partir du troisième caractère, soit la lettre "j" (étant donné que la première
lettre correspond au caractère n° 0).
On a volontairement omis le second paramètre facultatif, ce qui fait que substr() a renvoyé tous les
caractères restants jusqu'à la fin de la chaîne.
Essayons de renseigner le paramètre facultatif pour exclure le point d'exclamation, par exemple :
cpp
1 int main()
2 {
3 string chaine("Bonjour !");
4 cout << chaine.substr(3, 4) << endl;
6 return 0;
7 }
jour
Bingo ! On a demandé à prendre 4 caractères en partant du caractère n° 3, ce qui fait qu'on a récupéré
"jour".
Il existe une autre manière de faire pour accéder à un seul caractère. On utilise les crochets
[ ] comme pour les tableaux.
cpp
1 string chaine("Bonjour !");
2 cout << chaine[3] << endl; //Affiche la lettre 'j'
En résumé
La programmation orientée objet est une façon de concevoir son code. On considère qu'on
manipule des objets.
Les objets sont parfois complexes à l'intérieur, mais leur utilisation nous est volontairement
simplifiée. C'est un des avantages de la programmation orientée objet.
Un objet est constitué d'attributs et de méthodes, c'est-à-dire de variables et de fonctions
membres.
On appelle les méthodes de ces objets pour les modifier ou obtenir des informations.
La gestion du texte en mémoire est en fait complexe. Pour nous simplifier les choses, le langage
C++ nous propose le type string . Grâce à lui, nous pouvons créer des objets de type
string et manipuler du texte sans avoir à nous soucier du fonctionnement de la mémoire.
Vous venez de découvrir le monde de la programmation orientée objet, et je pense que tout n’est pas
encore clair pour vous. Nous allons sans tarder créer votre première classe, rien de mieux que de
pratiquer pour comprendre. Vous êtes prêt ?
J'ai terminé ce chapitre et je passe au suivant
Et si vous obteniez un diplôme OpenClassrooms ?
Formations jusqu’à 100 % financées
Date de début flexible
Projets professionnalisants
Mentorat individuel
Trouvez la formation et le financement faits pour vous
Être orienté Comparez nos types de formation
Tirez un maximum de ce cours Créez une classe
Les professeurs
Mathieu Nebra
Entrepreneur à plein temps, auteur à plein temps et co-fondateur d'OpenClassrooms :o)
Ranga Gonnage
Développeur logiciel, mentor et enseignant.
OPENCLASSROOMS
OPPORTUNITÉS
AIDE
POUR LES ENTREPRISES
EN PLUS
Français