SlideShare une entreprise Scribd logo
1  sur  233
COURS C++
2018 - 2019
Professeur Adama Sabaly
 Partie I
Introduction du langage C++
1) Historique
a) Forces et faiblesses
b) Outils de programmation
c) Création nouveau projet
• Chapitre 1 : Généralités sur le langage C++.
1) Structure d’un programme C++
a)Bibliothèque
b) Affichage cout && espace de nom
c)Fonction main
2 ) exemple d’un programme C++
Chapitre II les types de Base C++
a) Variable
b) Déclaration variable
c) Types de variables
d) Initialisation variables &&différents types déclarations de variables
e) Références
4)Lecture de la console
4-1) les chevrons
4-2) les autres variables
4-3 ) changer le contenu d’une variable
5)Notation des constantes
5-1) déclaration
a) initialisation
5-2)exemple
6 - Les types caractères && types de déclarations de caractères
6.1 La notion de caractère en langage C++
6.2 Notation des constantes caractère
6 - Le type bool
Exemple et exercices
Chapitre III : Opérateurs et expressions
1) Les types d’operateurs
Exemple
• 2) les expréssions
exemples
• Les racourcis
• Incrémentation
• Décrementation
• 1) autres opérations
• Fonctions mathématiques
• Expemle puissance , valeur absolue
 Chapitre 4: Les instructions de contrôle
• 1 - Les blocs d’instructions .
• 1.1 Blocs d’instructions
• 1.2 Déclarations dans un bloc
• 2 - L’instruction if
• 2.1 Syntaxe de l’instruction if
• 2.2 Exemples
• 2.3 Imbrication des instructions if
• 3 - L’instruction switch
• 3.1 Exemples d’introduction de l’instruction switch
• 3.2 Syntaxe de l’instruction switch .
• 4 - Instruction do... while
• 4.1 Exemple d’introduction de l’instruction do... while
• 4.2 Syntaxe de l’instruction do... while
• 5 - L’instruction while
• 5.1 Exemple d’introduction de l’instruction while
• 5.2 Syntaxe de l’instruction while
• 6 - L’instruction for
• 6.1 Exemple d’introduction de l’instruction for
• 6.2 L’instruction for en général
• 6.3 Syntaxe de l’instruction for
• 7 - Les instructions de branchement inconditionnel : break, continue et GOTO
• 7.1 L’instruction break
• 7.2 L’instruction continue .
• 7.3 L’instruction GOTO
Chapitre 6 : Les fonctions
• 1 - Exemple de définition et d’utilisation d’une fonction
• 2 - Quelques règles
• 2.1 Arguments muets et arguments effectifs
• 2.2 L’instruction return
• 2.3 Cas des fonctions sans valeur de retour ou sans argument
• 3 - Les fonctions et leurs déclarations
• 3.1 Les différentes façons de déclarer une fonction
• 3.2 Où placer la déclaration d’une fonction
• 3.3 Contrôles et conversions induites par le prototype
Chapitre 7 : Les tableaux et les pointeurs
• 1 - Les tableaux à un indice
• 1.1 Exemple d’utilisation d’un tableau en C++.
• 1.2 Quelques règles . 1.2.1 Les éléments de tableau . . .
• 1.2.2 Les indices
• 1.2.3 La dimension d’un tableau.
• 2 - Les tableaux à plusieurs indices .
• 2.1 Leur déclaration. .
• 2.2 Arrangement en mémoire des tableaux à plusieurs indices.
• 3 - Initialisation des tableaux .
• 3.1 Initialisation de tableaux à un indice
• 3.2 Initialisation de tableaux à plusieurs indices
• 3.3 Initialiseurs et classe d’allocation
• 4 - Notion de pointeur – Les opérateurs * et &
• 4.1 Introduction
• 4.2 Quelques exemples
• 4.3 Incrémentation de pointeurs
• 5 - Comment simuler une transmission par adresse avec un pointeur
• 6 - Un nom de tableau est un pointeur constant
• 6.1 Cas des tableaux à un indice
• 6.2 Cas des tableaux à plusieurs indices
• 7 - Les opérations réalisables sur des pointeurs .
• 7.1 La comparaison de pointeurs
• 7.2 La soustraction de pointeurs
• 7.3 Les affectations de pointeurs et le pointeur nul
Partie II :
Chapitre 11 :
1 - Programmation structurée et programmation orientée objet
• 1.1 Problématique de la programmation
• 1.2 La programmation structurée
• 1.3 Les apports de la programmation orientée objet
• 1.3.1 Objet
• 1.3.2 Encapsulation
• 1.3.3 Classe
• 1.3.4 Héritage
• 1.3.5 Polymorphisme
• 1.4 P.O.O., langages de programmation et C
• 2 - C++ et la programmation structurée
• 3 - C++ et la programmation orientée objet
Introduction du langage C++
1) Qu’est ce que le C++
Le langage C++ est un langage de programmation compilé permettant la programmation sous de multiples paradigmes procédurale et Orienté objet.
Parmi les centaines de langages de programmation qui existent, certains sont plus populaires que d'autres. Sans aucun doute, le
C++ est un langage très populaire. Des sites comme langpop.com tiennent à jour un classement des langages les plus
couramment utilisés, si cette information vous intéresse. Comme vous pourrez le constater, le C, le Java et le C++ occupent
régulièrement le haut du classement.
La question est : faut-il choisir un langage parce qu'il est populaire ? Il existe des langages très intéressants mais peu utilisés. Le
souci avec les langages peu utilisés, c'est qu'il est difficile de trouver des gens pour vous aider et vous conseiller quand vous
avez un problème. Voilà entre autres pourquoi le C++ est un bon choix pour qui veut débuter : il y a suffisamment de gens qui
développent en C++ pour que vous n'ayez pas à craindre de vous retrouver tous seuls !
Bien entendu, il y a d'autres critères que la popularité. Le plus important à mes yeux est le niveau du langage. Il existe des
langages de haut niveau et d'autres de plus bas niveau.
2) Historique
C'est Bjarne Stroustrup, un informaticien originaire du Danemark, qui a conçu le langage C++. Insatisfait des possibilités offertes
par le C, il a créé en 1983 le C++ en y ajoutant les possibilités qui, selon lui, manquaient.
Bjarne Stroustrup est aujourd'hui professeur d'informatique à l'université Texas A&M, aux Etats-Unis. Il s'agit d'une importante
figure de l'univers informatique qu'il faut connaître, au moins de nom (du moins si vous arrivez à le retenir !).
De nombreux langages de programmation se sont par la suite inspirés du C++. C'est notamment le cas du langage Java.
3) Forces && faiblesses
Il est très répandu. Comme nous l'avons vu, il fait partie des langages de programmation les plus utilisés sur la planète.
On trouve donc beaucoup de documentation sur Internet et on peut facilement avoir de l'aide sur les forums. Il paraît
même qu'il y a des gens sympas qui écrivent des cours pour débutants dessus.
Il est rapide, très rapide même, ce qui en fait un langage de choix pour les applications critiques qui ont besoin de
performances. C'est en particulier le cas des jeux vidéo, mais aussi des outils financiers ou de certains programmes
militaires qui doivent fonctionner en temps réel.
Il est portable : un même code source peut théoriquement être transformé sans problème en exécutable sous Windows, Mac OS et Linux.
1) Structure d’un programme C++
Pour la structure du programme nous avons le fameux « hello world » :
b) Outils de programmation
Voici le strict minimum pour un programmeur :
Un éditeur de texte pour écrire le code source du programme en C++. En théorie un logiciel comme le Bloc-Notes sous
Windows ou vi sous Linux fait l'affaire. L'idéal, c'est d'avoir un éditeur de texte intelligent qui colore tout seul le code, ce
qui vous permet de vous y repérer bien plus facilement. Voilà pourquoi aucun programmeur sain d'esprit n'utilise le Bloc-Notes. Un
compilateur pour transformer (« compiler ») votre code source en binaire.
Un débugger (« Débogueur » ou « Débugueur » en français) pour vous aider à traquer les erreurs dans votre programme
(on n'a malheureusement pas encore inventé le « correcteur », un truc qui corrigerait tout seul nos erreurs).
Exemple de code source :
#include <iostream> : C'est ce qu'on appelle une directive de préprocesseur. Son rôle est de « charger » des fonctionnalités du C++ pour que nous
puissions effectuer certaines actions.En effet, le C++ est un langage très modulaire. De base, il ne sait pas faire grand-chose (pas même afficher
un message à l'écran On doit donc charger des extensions que l'on appelle bibliothèques et qui nous offrent de nouvelles possibilités.Ici, on charge
le fichier iostream, ce qui nous permet d'utiliser une bibliothèque… d'affichage de messages à l'écran dans une console ! Quelque chose de
vraiment très basique, comme vous le voyez, mais qui nécessite quand même l'utilisation d’une bibliothèque.
using namespace std : permet en quelque sorte d'indiquer dans quel lot de fonctionnalités notre fichier source va aller piocher.
on a créé des namespaces (espaces de noms), qui sont des sortes de dossiers à noms. La ligne using namespace std; indique que vous allez utiliser
l'espace de noms std dans la suite de votre fichier de code et le cout fait partie de l’espace de nom.
Cet espace de noms est un des plus connus car il correspond à la bibliothèque standard (std), une bibliothèque livrée par
défaut avec le langage C++ et dont iostream fait partie.
• int main() : C'est ici que commence vraiment le coeur du programme. Les programmes, vous le verrez, sont essentiellement
constitués de fonctions. Chaque fonction a un rôle et peut appeler d'autres fonctions pour effectuer certaines actions.
Tous les programmes possèdent une fonction dénommée « main » (Qui se prononce « mèïne » en anglais.), ce qui signifie «principale ». C'est donc
la fonction principale. {} les accolades déterminent le début et la fin de la fonction
cout : commande l'affichage d'un message à l'écran ;
"Hello world!" : indique le message à afficher ;
endl : crée un retour à la ligne dans la console
return 0; : Ce type d'instruction clôt généralement les fonctions. En fait, la plupart des fonctions renvoient une valeur (un nombre par
exemple). Ici, la fonction main renvoie 0 pour indiquer que tout s'est bien passé (toute valeur différente de 0 aurait indiqué un
problème).
Exemple en utilisant les commentaires
• #include <iostream> // Inclut la bibliothèque iostream (affichage de texte)
• using namespace std; // Indique quel espace de noms on va utiliser
/*
Fonction principale "main"
Tous les programmes commencent par la fonction main
*/
int main()
{
cout << "Hello world!" << endl; // Affiche un message
return 0; // Termine la fonction main et donc le programme
}
Chapitre II les types de Base C++
a) Variable
Une variable est une espace mémoire stockée ,
Assez parlé, il est temps d'entrer dans le vif du sujet et de demander à l'ordinateur de nous prêter un de ses tiroirs. En termes
techniques, on parle de déclaration de variable.
Il nous faut indiquer à l'ordinateur le type de la variable que nous voulons, son nom et enfin sa valeur. Pour ce faire, c'est très simple : on
indique les choses exactement dans l'ordre présenté à la figure suivante.
Exemple1 :
#include <iostream>
using namespace std;
int main()
{
int age(28);
return 0;
}
Exemple2:
#include <iostream>
using namespace std;
int main()
{
int ageUtilisateur(28);
int nombreAmis(432);
double pi(3.14159);
bool estMonAmi(true);
char lettre(‘a’);
return 0;
}
Le cas des strings
Les chaînes de caractères sont un petit peu plus complexes à déclarer mais rien d'insurmontable, je vous rassure. La première
chose à faire est d'ajouter une petite ligne au début de votre programme. Il faut, en effet, indiquer au compilateur que nous
souhaitons utiliser des strings. Sans cela, il n'inclurait pas les outils nécessaires à leur gestion. La ligne à ajouter est
• #include <string>.
Exemple:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string nom("Sabaly ");
return 0;
}
Il faut utiliser cout et les chevrons (<<). Parfait. En effet, pour afficher le contenu d'une variable, c'est la
même chose. À la place du texte à afficher, on met simplement le nom de la variable.
Exemple:
#include <iostream>
using namespace std;
int main()
{
int Monage(28);
cout << "Votre age est : ";
cout << Monage;
return 0;
}
Exemple une autre façon d’affichage:
#include <iostream>
using namespace std;
int main()
{
int Monage(16);
cout << "Votre age est : " << Monage << endl;
return 0;
}
Exemple : Combinaison une chaine avec le type entier
#include <iostream>
#include <string>
using namespace std;
int main()
{
int Age(60);
string nom("Adama Sabaly");
cout << "Vous vous appelez " << nom << " et votre age est " << Age << endl;
return 0;
}
4) Lecture au clavier ou de la console
Vous l'aurez remarqué, le C++ utilise beaucoup de mots tirés de l'anglais. C'est notamment le cas pour le flux sortant cout, qui
doit se lire « c-out ». Ce qui est bien, c'est qu'on peut immédiatement en déduire le nom du flux entrant. Avec cout, les données
sortent du programme, d'où l'élément out. Le contraire de out en anglais étant in, qui signifie « vers l'intérieur », on utilise
cin pour faire entrer des informations dans le programme. cin se décompose aussi sous la forme « c-in » et se prononce « siinne».
C'est important pour les soirées entre programmeurs.
Ce n'est pas tout ! Associés à cout, il y avait les chevrons (<<). Dans le cas de cin, il y en a aussi, mais dans l'autre sens (>>).
Exemple:
#include <iostream>
using namespace std;
int main()
{
int age(30);
cout << " merci de préciser votre age SVP!: " << endl;
cin >> age;
cout << "Vous avez " << age << " ans !" << endl;
return 0;
}
5)Probléme d’espace de nom:
Pour les string, on rencontre le problème d’ espace de nom car si la chaine est longue l’ordinateur va couper la chaine . il faudrait
pouvoir récupérer toute la ligne plutôt que seulement le premier mot.
Il faut utiliser la fonction getline(). Il faut remplacer la ligne cin >> nom; par un getline().
Exemple:
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
string nom ;
cout << " merci de préciser votre nom SVP!: " << endl;
getline (cin , nom);
cout << "Vous vous appelez " << nom << endl;
system("PAUSE");
}
Exemple:
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout << "Quel est votre nom ?" << endl;
string nom;
getline(cin, nom);
cout << " quel est ton age ?" << endl;
int age;
cin >> age;
cout << "Vous vous appelez " << nom << " votre age est: " << age << " ans " << endl;
return 0;
}
6) Les références
Une référence peut être vue comme un alias d'une variable. C'est-à-dire qu'utiliser la variable, ou une référence à cette variable
est équivalent. Ce qui signifie que l'on peut modifier le contenu de la variable en utilisant une référence.Une référence ne peut
être initialisée qu'une seule fois : à la déclaration. Toute autre affectation modifie en fait la variable référencée.Une référence ne
peut donc référencer qu'une seule variable tout au long de sa durée de vie.
a)Déclaration
type& identificateur=variable;
ou
type& identificateur(variable);
NB: La variable identificateur est une référence vers la variable variable. La variable variable doit être de type type.
Exemple
Ecrire un programme qui permet de référencier deux variables a et b
#include <iostream>
using namespace std;
int main()
{
int a = 60;
Int b = 78;
Int c;
int &x = a;
c = x + 5; // équivaut à : c = a + 5;
int &y = b;
y = a + 10; // équivaut à : b = a + 10;
cout << "La variable b vaut : " << b << endl;
cout << "La variable c vaut : " << c << endl;
return 0;
}
7)Les constantes
C’est une variable qui ne change pas c’est-à-dire une valeur fixe.
a) Déclaration d’une constate
Type variable const variable;
Exemple :
Double const pi=3.14;
Exemple:
#include <iostream>
using namespace std;
#define const_pi
int main()
{
double const pi=3.14;
cout << « la valeur de pi est : »<< pi <<endl;
return 0;
}
II) Opérateurs et expressions
Les opérateurs sont des symboles permettant d'effectuer des opérations sur des valeurs. Ils sont classés dans trois
catégories.
a) Opérateur d’affectation
L'opérateur d'affectation simple est "=" il signifie "affecter à«
Exemple;
Int x =5;
Int y=6;
x=y;
Exercice 1:
Écrire un programme qui permet d’affecter deux variables a et b;
Exercice
#include <iostream>
using namespace std;
int main()
{
int a (6) , b (4);
cout << "La valeur de a : " << a << « et la valeur de b est: « << b<< endl;
a=b;
cout << « Affectation » : << endl;
cout << "La valeur de a : " << a << « et la valeur de b est: « << b<< endl;
return 0;
}
b)L'opérateur d'affectation additionneur "+="
Syntaxe:
int x, y;
x = 5;
y = 3;
x += y; //x = 8
c) Les opérateurs mathématiques
Il existe certains opérateurs (addition,multiplication,divison,soustraction), pour utiliser certains calculs on utilise le prépocesseur
cmath.
Pour utiliser une fonction mathématique on met le nom de la fonction suivie à calculer
Résultat = fonction (valeur);
Exemple
Resultat =sqrt (nombre);
#include <cmath>
Exemple;
Écrire un programme en C++ qui donne la somme, la multiplication , la divison de deux entiers
Exercice 1:
Écrire un programme qui calcule la racine carré d’un nombre saisie resultat = sqrt(nombre)
Exercice 2:
Ecrire un programme qui calcule la puissance d’une valeur saisie (pow (a,b))
Chapitre II Structure de Contrôle
a)Opérateurs de comparaison
il faut savoir que les conditions permettent de tester des variables. Pour effectuer ces tests, nous utilisons des symboles.
Nous allons utiliser ces symboles pour effectuer des comparaisons dans nos conditions.
Faites très attention : il ne faut pas confondre l’opérateur d’égalité == (il y a bien 2 symboles « = ») et l’opérateur
d’affectation = (un seul symbole « = »)
b)Opérateurs logique
Pour construire des conditions plus complexes, C++ nous permet de combiner plusieurs tests au sein d'une seule et même condition dite complexe. Pour cela, il va
falloir utiliser de nouveaux symboles. Il s’agit des opérateurs logiques, Ce type d'opérateur permet de vérifier si plusieurs conditions sont vraies.
C) Structures de contrôle conditionnelles
On appelle structures de contrôle conditionnelles les instructions qui permettent de tester si une condition est vraie ou non. Il s'agit des instructions suivantes :
1) La structure conditionnelle if
2) Le branchement conditionnel switch
II-1) la structure conditionnelle if
a) if : une première condition
La structure conditionnelle if permet de réaliser un test et d’exécuter une instruction ou non selon le résultat de ce test.
Sa syntaxe est la suivante :
La condition est une expression dont la valeur est booléenne ou entière. Toute valeur non nulle est considérée comme vraie. Si le test est vrai,
instruction est exécutée.
b) if … else : ce qu'il faut faire si la condition n'est pas vérifiée,
c) else if : effectuer un autre test
NB :
- la condition doit être entre des parenthèses
- il est possible de définir plusieurs conditions à remplir avec les opérateurs ET et OU (&& et ||). Par exemple, l'instruction ci-dessous exécutera les instructions si
l'une ou l'autre des deux conditions est vraie :
- s'il n'y a qu'une instruction, les accolades ne sont pas nécessaires...
Exemple:
#include <iostream>
using namespace std;
int main()
{
int a;
cout << "Tapez la valeur de a : ";
cin >> a;
if (a > 10)
cout << "a est plus grand que 10" << endl;
cout << "Le programme est fini" << endl;
return 0;
}
Exemple:
#include <iostream>
using namespace std;
int main()
{
int a;
cout << "Tapez la valeur de a :" <<endl;
cin >> a;
if (a > 10)
cout << "a est plus grand que 10" << endl;
else
cout << "a est inférieur ou égal à 10" << endl;
system("pause") ;
}
II – 2) if … else : ce qu'il faut faire si la condition n'est pas vérifiée
• L'instruction if dans sa forme basique ne permet de tester qu'une condition, or la plupart du temps on aimerait pouvoir choisir les instructions à exécuter en cas de
non réalisation de la condition. L'expression if ... else permet d'exécuter une autre série d'instructions en cas de non-réalisation de la condition. Voici sa syntaxe :
II-3) else if : effectuer un autre test
Il est possible de faire plusieurs tests à la suite. Pour faire tous ces tests un à un dans l'ordre, on va avoir recours à la condition else if qui signifie « sinon si ».
• si le nombre d’étudiant est égal à 0, afficher ce message «on n’a pas d’étudiant dans la salle" ;
• - sinon, si le nombre d’étudiant est égal à 1, afficher ce message « on a un étudiant dans la salle ?";
• - sinon, si le nombre d'enfants est égal à 2, afficher ce message « on a plus d’un étudiant dans la salle";
• - sinon, afficher ce message « il y’a personne dans la salle".
Exercices :
#include <iostream>
using namespace std;
int main()
{
int Etudiants(5);
if (Etudiants == 0)
{
cout << "on n’a pas d’étudiant dans la salle?" << endl;
}
else if (Etudiants > 1)
{
cout << "on a un étudiant dans la salle ?" << endl;
}
else if (Etudiants <2)
{
cout << "on a plus d’un étudiant dans la salle!" << endl;
}
else
{
cout << "il y’ a personne dans la salle !" << endl;
}
cout << "Fin du programme" << endl;
return 0;
}
Exemple:
#include <iostream>
using namespace std;
int main()
{
int a;
cout << "Tapez la valeur de a : ";
cin >> a;
if (a > 10)
cout << "a est plus grand que 10" << endl;
cout << "Le programme est fini" << endl;
return 0;
}
II-3)Le branchement conditionnel switch
Dans le cas où plusieurs instructions différentes doivent être exécutées selon la valeur d’une variable de type intégral, l’écriture des if successifs peut être relativement lourde. Le
C++ fournit donc la structure de contrôle switch, qui permet de réaliser un branchement conditionnel.
Sa syntaxe est la suivante :
switch (variable)
{
case valeur1 :
instruction1;
break;
case valeur2 :
instruction2;
break;
case valeur3 :
instruction3;
break;
default:
instructionParDéfaut;
break;
}
valeur est évalué en premier. Son type doit être entier. Selon le résultat de l’évaluation, l’exécution du programme se poursuit au cas de même valeur. Si aucun des cas
ne correspond et si default est présent, l’exécution se poursuit après default. Si en revanche default n’est pas présent, on sort du switch.
Les instructions qui suivent le case approprié ou default sont exécutées. Puis, les instructions du cas suivant sont également exécutées (on ne sort donc pas du switch).
Pour forcer la sortie du switch, on doit utiliser le mot-clé break.
Exemple :
#include <iostream>
using namespace std;
int main()
{
int Etudiants(45);
switch (Etudiants)
{
case 8:
cout << "on n’a pas d’étudiant dans la salle?" << endl;
break ;
case 1:
cout << "on a un étudiant dans la salle " << endl;
break ;
case 25:
cout << "on a plus d’un étudiant dans la salle!" << endl;
break ;
case 33:
cout << "il y’ a plus d'étudiant dans la salle que prévue " << endl;
break ;
default :
cout << "fin du programme" << endl;
break;
}
return 0;
}
II – 3) Structures de contrôle itérative
Les structures de contrôle itératives sont des structures qui permettent d'exécuter plusieurs fois la même série d'instructions jusqu'à ce qu'une condition ne soit plus
réalisée. On appelle ces structures des boucles.
Il existe 3 types de boucles à connaître :
a) la boucle for,
b) la boucle while et
c la boucle do … while.
a) La boucle for
La structure de contrôle for est sans doute l’une des plus importantes. Elle permet de condenser :
- Un compteur : une instruction (ou un bloc d’instructions) exécutée avant le premier parcours de la boucle du for. Il consiste à préciser le nom de la variable qui sert de
compteur et éventuellement sa valeur de départ.
- une condition : une expression dont la valeur déterminera la fin de la boucle.
- une itération : une instruction qui incrémente ou décrémente le compteur.
Sa syntaxe est la suivante :
for (compteur; condition; itération)) {
instructions ;
}
instruction constitue le traitement de la boucle.
Exemple :
écrire un programme C++ qui affiche les 10 nombre entiers avec la boucle for.
#include <iostream>
using namespace std;
int main()
{
int compteur(0);
for (compteur = 1 ; compteur < 10 ; compteur++)
{
cout << compteur << endl;
}
return 0;
}
NB :
En C++, il est possible que la partie initialisation déclare une variable. Dans ce cas, la variable déclarée n’est définie qu’à l’intérieur de l’instruction for.
Exemple :
for (int compteur = 1 ; compteur < 10 ; compteur++)
{
cout << compteur << endl;
}
Cela signifie que l’on ne peut pas utiliser la variable compteur après l’instruction for, puisqu’elle n’est définie que dans le corps de cette instruction. Cela permet de
réaliser des variables muettes qui ne servent qu’à l’instruction for dans laquelle elles sont définies
II ) La boucle while
Le while permet d’exécuter des instructions en boucle tant qu’une condition est vraie. Sa syntaxe est la suivante :
Tout ce qui est entre accolades sera répété tant que la condition est vérifiée
Exemple :
Exemple:
#include <iostream>
using namespace std;
int main()
{
int i = 1;
while (i < 10)
{
cout << i << endl;
i++;
}
return 0;
}
• La boucle do … while
La structure de contrôle do … while permet, tout comme le while, de réaliser des boucles en attente d’une condition. Cependant, contrairement à celui-ci, le do … while
effectue le test sur la condition après l’exécution des instructions. Cela signifie que les instructions sont toujours exécutées au moins une fois, que le test soit vérifié ou
non. Sa syntaxe est la suivante :
do
{
instructions ;
}
while (condition) ;
Exemple :
Exemple
#include <iostream>
using namespace std;
int main()
{
int i = 1;
do
{
cout << i << endl;
i++;
}
while (i < 10);
return 0;
}
Les boucles permettent de répéter les mêmes instructions plusieurs fois.
On distingue trois types de boucles : for, while et do... while.
La boucle for est généralement utilisée lorsqu'on sait combien de fois on souhaite répéter les instructions, tandis que while et do... while
sont plutôt utilisées lorsqu'on souhaite répéter des instructions jusqu'à ce qu'une condition spécifique soit vérifiée.
Le GOTO est une structure de contrôle obsolète et ne doit plus être utilisé.
L'instruction break sert interrompre une boucle (for, while et do … while), ou un switch.
L'instruction continue sert à "continuer" une boucle (for, while et do … while) avec la prochaine itération.
Chapitre III) Les fonctions
On appelle fonction un sous programme qui permet d’effectuer un ensemble d’instruction par simple appel de la fonction dans le corps du programme principal.
I. 1. Déclaration d’une fonction
Toute fonction doit être déclarée avant d’être appelée pour la première fois. La définition d’une fonction peut faire office de déclaration.
Il peut se trouver des situations où une fonction doit être appelée dans une autre fonction définie avant elle. Comme cette fonction n’est pas définie au moment de
l’appel, elle doit être déclarée.
Le rôle des déclarations est donc de signaler l’existence des fonctions aux compilateurs afin de les utiliser, tout en reportant leur définition de ces fonctions plus loin ou
dans un autre fichier.
La syntaxe de la déclaration d’une fonction est la suivante :
type nomDeLafonction (paramètres) ;
Exemples :
double Moyenne(double x, double y);
char LireCaractere();
void AfficherValeurs(int nombre, double valeur);
NB : la dernière fonction n’est pas destinée à renvoyer une valeur ; c’est pourquoi le type du résultat est void, une telle fonction est parfois appelée procédure (voir I.
Des fonctions qui ne renvoient rien).
Toute fonction doit être définie avant d’être utilisée
type nomDeLafonction (paramètres)
{
instructions ;
}
1) type est le type de la valeur renvoyée par la fonction
2) nomDeLafonction est le nom ou l’identificateur de la fonction, et
3) paramètres est une liste de paramètres. Ce sont les données avec lesquelles la fonction va travailler. Il peut y avoir un, plusieurs ou aucun paramètre.
4) L’instruction-bloc : il s’agit des accolades qui délimitent le contenu de la fonction. Toutes les opérations qui seront effectuées se trouvent entre les deux accolades.
NB : Il est possible de créer plusieurs fonctions ayant le même nom. Il faut alors que la liste des arguments des deux fonctions soit différente. C'est ce qu'on appelle la
surcharge d'une fonction.
Appel de la fonction:
nom_de_la _fonction ();
Ou
Nom_de_la_fonction(parametre1,parametre2);
Exemple :
int ajouteDeux(int nombreRecu)
{
int valeur(nombreRecu + 2);
return valeur;
}
#include <iostream>
using namespace std;
int ajouteDeux(int nombreRecu)
{
int valeur(nombreRecu + 2);
return valeur;
}
int main()
{
int a(2),b(2);
cout << "Valeur de a : " << a << endl;
cout << "Valeur de b : " << b << endl;
b = ajouteDeux(b); //Appel de la fonction
cout << "Valeur de a : " << a << endl;
cout << "Valeur de b : " << b << endl;
return 0;
}
Fonction avec plusieurs paramètres
Pour passer plusieurs paramètres à une fonction, il faut les séparer par des virgules
Exemple:
int addition(int a, int b)
{
return a+b;
}
double multiplication(double a, double b, double c)
{
return a*b*c;
}
#include <iostream>
using namespace std;
// déclaration de la fonction somme :
double somme(double a, double b);
int main()
{
double x, y, resultat;
cout << "Tapez la valeur de x : "; cin >> x;
cout << "Tapez la valeur de y : "; cin >> y;
//appel de notre fonction somme
resultat = somme(x, y);
cout << x << " + " << y << " = " << resultat << endl;
return 0;
}
// définition de la fonction somme : prototype
double somme(double a, double b)
{
double r;
r = a + b;
return r;
}
Prototype d'une fonction
Le prototype va préciser le nom de la fonction, donner le type de la valeur de retour de la fonction (void quand il n'y a pas de retour), et donner les
types des paramètres éventuels, ainsi que leurs éventuelles valeurs par défaut. Le prototype d'une fonction est facultatif. Si on ne met pas de
prototype, on devra rédiger la fonction avant le main,
Exemple
// prototype de la fonction f :
double f(double x,double y);
Le rôle d'un prototype n'est pas de définir les instructions de la fonction, mais donner sa signature. Il est utilisé pour spécifier que la fonction
existe, et est implémentée ailleurs (dans un autre fichier, une librairie, ou à la fin du fichier source).
Dans cet exemple, le prototype est nécessaire, car la fonction est définie après la fonction main() qui l'utilise. Si le prototype est omis, le
compilateur signale une erreur.
Exemple : de variable avec le méme nom
Dans le chapitre sur la mémoire, nous avions vu que chaque variable devait avoir un nom unique. C'est tout à fait correct, mais cette règle n'est
valable qu'à l'intérieur d'une même fonction. Il est tout à fait possible d'avoir deux variables ayant le même nom pour autant qu'elles soient
déclarées dans des fonctions différentes.
#include <iostream>
using namespace std;
double carre(double x)
{
double nombre;
nombre = x*x;
return nombre;
}
int main()
{
double nombre, carreNombre;
cout << "Entrez un nombre : ";
cin >> nombre;
carreNombre = carre(nombre); //On utilise la fonction
cout << "Le carre de " << nombre << " est " << carreNombre << endl;
return 0;
}
#include <iostream>
using namespace std;
void dessineRectangle(int l, int h)
{
for(int ligne(0); ligne < h; ligne++)
{
for(int colonne(0); colonne < l; colonne++)
{
cout << "*";
}
cout << endl;
}
}
int main()
{
int largeur, hauteur;
cout << "Largeur du rectangle : ";
cin >> largeur;
cout << "Hauteur du rectangle : ";
cin >> hauteur;
dessineRectangle(largeur, hauteur);
return 0;
}
Passage par valeur et passage par référence
Il y a deux méthodes pour passer des variables en paramètres dans une fonction : le passage par valeur et le passage par
référence. Ces méthodes sont décrites ci-dessous.
IV. 1. Passage par valeur
La valeur de l’expression passée en paramètre est copiée dans une variable locale. C’est cette variable qui est utilisée pour
faire les calculs dans la fonction appelée.
Pour mieux comprendre, Prenons le programme suivant qui ajoute 1 à l'argument fourni en paramètre.
Passage par valeur
On va vérifier comment l’ordinateur gère la mémoire
Exemple :
int ajouteDeux(int a)
{
a+=2; // passage de valeur
return a;
}
exemple
#include <iostream>
using namespace std;
int ajouteDeux(int a)
{
a+=2;
return a;
}
int main()
{
int nombre(4), resultat;
resultat = ajouteDeux(nombre);
cout << "Le nombre original vaut : " << nombre << endl;
cout << "Le resultat vaut : " << resultat << endl;
return 0;
}
Lors de l’appel de la fonction on constate:
- Le programme évalue la valeur de nombre qui est 4
- Le programme alloue un espace mémoire et y méttre la valeur 4 mais cet espace mémoire posséde l’ettiquette a qui est la variable de la
fonction
- le programme entre dans la fonction & il ajoute 2 à la variable a
- La valeur a est ensuite copiée et affecter à la variable résultat qui est 6
NB : la variable nombre est copiée dans une nouvelle case mémoire on dit que l’argument a est passée par valeur,
La variable nombre reste inchangée
Passage par référence
int ajouteDeux(int& a) //
{
a+=2;
return a;
}
Exemple : passage par réference
#include <iostream>
using namespace std;
void echange (double& a, double& b)
{
double temporaire(a); //On sauvegarde la valeur de 'a'
a = b; //On remplace la valeur de 'a' par celle de 'b'
b = temporaire; //Et on utilise la valeur sauvegardée pour mettre l'ancienne valeur de 'a' dans 'b'
}
int main()
{
double a(1.2), b(4.5);
cout << "a vaut " << a << " et b vaut " << b << endl;
echange(a,b); //On utilise la fonction
cout << "a vaut " << a << " et b vaut " << b << endl;
return 0;
}
Chapitre IV : Les Tableaux
Le C++, comme presque tous les langages de programmation, propose un moyen simple de regrouper des données identiques dans un seul paquet.
Et comme l'indique le titre du chapitre, on appelle ces regroupements de variables des tableaux
Les tableaux statiques
Il existe deux types de tableaux : les tableaux statiques, dont la taille est connue à la compilation, et les tableaux dynamiques, dont la taille est
connue à l'exécution
Déclarez un tableau statique
Comme toujours en C++, une variable est composée d'un nom et d'un type. Comme les tableaux sont des variables, cette règle reste valable. Il
faut juste ajouter une propriété supplémentaire, la taille du tableau. Autrement dit, le nombre de compartiments que notre case mémoire va
pouvoir contenir.
La déclaration d'un tableau est très similaire à celle d'une variable :
TYPE NOM [TAILLE];
On indique le type, puis le nom choisi et enfin, entre crochets, la taille du tableau. Voyons cela avec un exemple :
Exemple de tableau :
#include <iostream>
using namespace std;
int main()
{
int Notes[5]; //Déclare un tableau de 5 int
double anglesTriangle[3]; //Déclare un tableau de 3 double
return 0;
}
Il est également possible de déclarer un tableau en utilisant comme taille une constante
On indique simplement le nom de la constante entre les crochets, à la place du nombre.
Exemple:
int const tailleTableau(20); //La taille du tableau
double angles[tailleTableau];
NB: Il faut impérativement utiliser une constante comme taille du tableau.
• Je vous conseille de toujours utiliser des constantes pour exprimer les tailles de vos tableaux plutôt que d'indiquer directement la taille entre les crochets. C'est
une bonne habitude à prendre.
Comment accéder aux tableaux
Chaque case d'un tableau peut être utilisée comme n'importe quelle autre variable, il n'y a aucune différence. Il faut juste y accéder d'une manière un peu spéciale. On
doit indiquer le nom du tableau et le numéro de la case.
Pour accéder à une case, on utilise la syntaxe
nomDuTableau[numeroDeLaCase]
Il y a simplement une petite subtilité : la première case possède le numéro 0 et pas 1, il faut décaler 1 en quelque sorte,
note[2] = 5;
Parcourez un tableau
Le gros point fort des tableaux, c'est qu'on peut les parcourir en utilisant une boucle. On peut ainsi effectuer une action sur chacune des cases d'un tableau, l'une
après l'autre : par exemple afficher le contenu des cases.
On connaît a priori le nombre de cases du tableau on peut donc utiliser une boucle for Nous allons pouvoir utiliser la variable i de la boucle pour
accéder au ième élément du tableau
Exemple
#include <iostream>
using namespace std;
int main()
{
int const nombreNotes(6);
double notes[nombreNotes];
notes[0] = 12.5;
notes[1] = 19.5; //Bieeeen !
notes[2] = 6.; //Pas bien !
notes[3] = 12;
notes[4] = 14.5;
notes[5] = 15;
Exemple:
double moyenne(0);
for(int i(0); i<nombreNotes; ++i)
{
moyenne += notes[i]; //On additionne toutes les notes
}
//En arrivant ici, la variable moyenne contient la somme des notes (79.5)
//Il ne reste donc qu'à diviser par le nombre de notes
moyenne /= nombreNotes;
cout << "Votre moyenne est : " << moyenne << endl;
return 0;
}
4.1.2. Tableaux à deux dimensions
Les tableaux à deux dimensions ou matrices, sont rangés ligne par ligne et considérés comme des
vecteurs de lignes. L’accès aux composantes est effectué par des doubles crochets.
Déclaration:
Type Nom_Tableau [dim1][dim2];
Nom_Tableau [0][0]
Nom_Tableau [0][1]
Nom_Tableau [0][dim2-1]
Nom_Tableau [1][0]
Nom_Tableau [dim1-1][0] Nom_Tableau [dim1-1][dim2-1]
Exemple3:
int Tab12[4][5];
float Tab34[2][10];
char Tab_Char[5][3]; //déclare un tableau de 5*3=15 caractères
Utilisation : Un élément du tableau est repéré par ses indices. En C/C++ les tableaux commencent aux indices 0. Les
indices maxima sont donc dim1-1, dim2-1.
Appel : Nom_Tableau [indice1][indice2]
Exemple4:
Tab12 [2][4] = 25;
Tab34 [0][5] = 2.79;
Initialisation et réservation automatique
Lors de la déclaration d'un tableau, on peut initialiser ses composantes en indiquant la liste des
valeurs respectives entre accolades.
Exemple5
int Tab_A[5] = {10, 20, 30, 40, 50};
float Tab_B[5] = { 10.1, 70.3, 30.5, 20.0, 50.4 };
int C_Tab[10] = {1, 1, 0, 1, 1, 1, 0, 1, 0, 1};
int D_Tab[] = {1, 5, 3, 21};
float E_Tab[2] = {1.1, 5.0, 1.2, 1.9}; // erreur
int Deux_Dim[2][3] = {{1,5,7},{8,4,3}}; //2 lignes et 3 colonnes
Ecrire un programme qui demande à l'utilisateur de saisir 10 entiers stockés dans un tableau. Le programme doit ensuite afficher
l'indice du plus grand élément.
Ecrire un programme qui affiche les éléments du tableau à deux dimensions suivant :
int A[3][5] = {{ 0, 1, 2, 3, 4}, {10,11,12,13,14}, { 20,21,22,23,24} };
Exemple :
#include <iostream>
using namespace std;
void main() {
int A[3][5] = { { 0, 1, 2, 3, 4}, {10,11,12,13,14},{ 20,21,22,23,24} };
for(int i=0;i<3;i++){
for(int j=0;j<5;j++){
cout << "A[" << i+1 <<"][" << j+1 << "]= " << A[i][j] << "; ";
}
cout << endl ;
}
}
Les chaînes de caractères
4.2.1. Déclaration de chaînes de caractères
En C++ une chaîne de caractères peut être traitée et manipulée à travers un tableau de caractères à
une dimension (vecteur de caractères), avec des déclarations dont la syntaxe est de type :
char Ident[dim]; //Ident : Nom de la chaîne de caractères
Mais il existe aussi un type spécial string (le mot anglais pour une chaîne de caractères), dont la syntaxe est de type :
string Ident;
4.2.2. Initialisation de chaînes de caractères
a) char Ident[dim];
char s[10] = "bonjour !";
NB : Le caractère nul '0' (null terminator), de code ASCII 0, est un caractère de contrôle qu’il ne
faut pas confondre avec le caractère affichable '0', lequel est codé par le nombre ASCII 48. Il doit être placé obligatoirement en
fin de chaîne. Sans lui, la chaîne n'a pas de fin. Une lecture de la chaîne pourrait donc continuer jusqu'au prochain caractère nul
en mémoire, et donc bien après la dimension maximale.
Dans l’exemple, '0' est ajouté automatiquement par le compilateur, car le nombre de caractères
dans "bonjour !" est inférieur à la dimension du tableau s.
Exemple 2 :
char S[] = {'H','e','l','l','o','0’};
Exemple : le programme affiche Hello
#include <iostream>
using namespace std;
int main() {
char S[8]= "Hello";
for(int i=0; i<8; i++){
cout << S[i] << endl;
}
}
NB :
string Ident; // Il faut inclure <string>
Cette construction est équivalente à string Ident = ""; ce qui revient à dire que par défaut une
chaîne est créée vide.
Il existe toutefois de nombreuses autres façons d’initialiser un string
string s1 = "Bonjour a vous";
string s2 = s1; // s2 contient " Bonjour a vous "
string s3(4, 'x'); // équivaut à string s3 = "xxxx"
string s4(s1, 4, 8); // s4 contient "our a vo"
Exemple 6:
#include <string >
string ST = "Salut";
for (int i=0;i<5;i++) {
cout << ST[i] << " "; // affichera : S a l u t
}
Exemple 7 :
#include <iostream >
#include <string >
using namespace std;
int main()
{
string Phrase;
cout << "donner une phrase" << endl ;
while ( cin >> Phrase )
cout << "Dans Phrase il y a: " << Phrase << 'n';
cout << "ok: Plus rien : bye!n";
return 0;
}
Pointeurs
C++permet, comme C, un contrôle fin de la mémoire. En effet, il permet, grâce aux pointeurs, d’accéder directement à des zones
de la mémoire,en travaillant sur les adresses .
1) Déclaration de pointeurs
Les pointeurs se déclarent, comme les variables, en donnant le type de l'objet vers lequel ils devront pointer. Cependant, pour
différencier une variable quelconque d’une variable « pointeur », le type de base (char, float, int, …) est toujours suivi d’une étoile ‘ * ’.
Cela se fait par l'instruction:
type* nom_du_pointeur;
Exemple 2 : on peut déclarer les pointeurs suivants :
int *p, *q, r ; // 2 pointeurs p et q vers des entiers et 1 entier r
char *s; // 1 pointeur s vers un caractère
float *pr; // 1 pointeur pr pointant sur un float
int **tab; // 1 pointeur tab pointant sur un pointeur qui pointe sur un int
L'opérateur * désigne en fait le contenu de l'adresse, c’est l’opérateur de déréférencement.
2. Valeurs pointées et adresses
La manipulation des pointeurs nécessite une bonne maîtrise des deux opérateurs & et *. Lors de l’utilisation des pointeurs, nous avons besoin :
- d'un opérateur 'adresse de': & pour obtenir l'adresse d'une variable,
- d'un opérateur 'contenu de': * pour accéder au contenu d'une adresse,
- d'une syntaxe de déclaration pour pouvoir déclarer un pointeur.
l’exemple :
int i = 35;
int *p; // déclaration : p est un pointeur pointant sur un entier
p = &i; /* initialisation du pointeur p, affecte l'adresse de la variable i.
p pointe maintenant vers la zone mémoire où est stockée la variable i*/
cout << *p; //affiche la valeur pointée par p, donc 35
p contient l’adresse de la variable i (p = &i ) alors que *p contient le contenu de la variable, donc 35.
On peut donc accéder à la valeur de la variable en passant par son adresse et en utilisant l’opérateur ‘’contenu de * ‘’.
EXEMPLE
#include <iostream>
using namespace std;
int main ()
{
int *ptr ;
int i= 42;
ptr = &i;
cout << "ptr: "<< ptr << endl;
cout << "* ptr : "<< * ptr<<endl;
return 0;
}
Passage de paramètres par pointeurs
En C, les pointeurs sont fort utiles lors du passage de paramètres modifiables dans des fonctions. Ceci a pour conséquence de
produire un code peu lisible et constitue une source fréquente d'erreurs, surtout pour les personnes peu habituées à cette
gymnastique. Le langage C++ pallie à cette lacune en introduisant le passage de paramètres par références.
Exemple :
#include <iostream>
using namespace std;
void minmax(int i, int j, int* min, int* max)
{
if(i<j) {
*min=i;
*max=j;
}
Else {
*min=j;
*max=i;
}
}
int main()
{
int a, b, w, x;
cout << "Tapez la valeur de a : "; cin >> a;
cout << "Tapez la valeur de b : "; cin >> b;
minmax(a, b, &w, &x);
cout << "Le plus petit vaut : " << w << endl;
cout << "Le plus grand vaut : " << x << endl;
return 0;
}
Exemple : Pointeur avec références
#include <iostream>
using namespace std;
void affiche(int i, float r, char c){
cout<< "n int = " << i << " float = " << r << " char = " << c ;
}
void Saisie(int &i, float r, char &cc){
cout << "n Donner un entier : ";
cin >> i; // 12
cout << " Donner un reel : ";
cin >> r; // 12.13
cout << " Donner un caractere : ";
cin >> cc; // Z
}
void main(){
int N=5;
float f=6.7;
char C = 'A';
affiche(N, f, C);
Saisie(N, f, C);
affiche(N, f, C);
}
Exemple Tableaux en utilisant un pointeur
#include <iostream>
using namespace std;
int main(){
int T[6] = { 2, 6, 4, 5, 10, 8 };
int *p;
p = T; // p repère le premier élément de T
cout<< *p << endl ;
p++;
cout<< *p << endl ;
p += 4;
cout<< *p << endl ;
}
• Pointeurs et tableaux
Un programme en C++ est capable de demander au système d'exploitation de la mémoire pour y stocker des données et de libérer ces zones mémoire au
cours de l'exécution du programme : on appelle cela l'allocation dynamique de mémoire.
Le programmeur est tenu de "rendre" au système d'exploitation, les zones mémoire qu'il aura réclamé dynamiquement, au plus tard lors de la fermeture
du programme.
Il existe deux méthodes pour effectuer de l'allocation dynamique de mémoire :
L'ancienne méthode qui utilise les fonctions malloc et free.
Une méthode plus récente qui utilise les mots-clés new et delete.
• malloc et free
Il s'agit de 2 appels système standards :
La fonction (void *) malloc(int t) demande au système de fournir une zone mémoire de t octets et renvoie par un return un pointeur vers cette zone (ou le
pointeur NULL s'il n'y a pas assez de mémoire). cette fonction renvoie un élément de type void *, c'est-à-dire un pointeur vers n'importe quelle type. En
général, on effectue un cast pour transformer ce pointeur vers un pointeur vers un autre type, un pointeur vers un int par exemple.
La fonction void free(void *p) libère la zone mémoire pointée p.
• Tableaux de taille variable
Grâce à malloc et free, on peut gérer des tableaux dont la taille est variable : un tableau peut s'allonger ou se réduire
en fonction des besoins du programmeur. On appelle cela de l'allocation dynamique de mémoire. Ne pas oublier de libérer la mémoire.
Pour demander au système d'exploitation une zone de la bonne taille, il peut être utile de connaître la taille occupée
par un int, un char, ou n'importe quelle type structuré par exemple. Pour cela, on peut utiliser le mot-clé sizeof(type)
qui a en paramètre un type quelconque et qui renvoie la taille en octets occupée par une variable de ce type.
Exemple :
#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
int *t;
int i;
t = (int *) malloc( 5 * sizeof(int) );
if (t==NULL)
cout << "pas assez de mémoire" << endl;
else
{
for(i=0 ; i<5 ; i++)
t[i] = i * i;
for(i=0 ; i<5 ; i++)
cout << t[i] << " ";
cout << endl;
free(t);
}
t = (int *) malloc( 10 * sizeof(int) );
if (t==NULL)
cout << "pas assez de mémoire" << endl;
else
{
for(i=0;i<10;i++)
t[i] = i * i;
for(i=0 ; i<10 ; i++)
cout << t[i] << " ";
cout << endl;
free(t);
}
return 0;
}
new et delete
new et delete sont 2 mots-clés permettant de faire de l'allocation dynamique de mémoire de manière plus
performante que malloc et free.
on préférera utiliser new et delete que malloc et free.
Utilisation de new
Syntaxe :
new type[taille];
new renvoie un tableau dont la taille est taille éléments, chaque élément étant de type type. S'il n'y a pas assez de
mémoire, new renvoie NULL.
new renvoie un élément dont le type est type *.
Utilisation de delete
Syntaxe :
delete []t;
Si t est un tableau qui a été créé en utilisant la méthode précédente, l'utilisation de delete détruit ce
tableau. Le
#include <iostream>
using namespace std;
int main()
{
int *t;
int i;
t = new int[5];
if (t == NULL )
cout << "pas assez de mémoire" << endl;
else
{
for ( i=0 ; i<5 ; i++ )
t[i] = i * i;
for ( i=0 ; i<5 ; i++ )
cout << t[i] << " ";
cout << endl;
delete [] t;
t = new int[10];
if (t == NULL)
cout << "pas assez de mémoire" << endl;
else
{
for ( i=0 ; i<10 ; i++ )
t[i] = i * i;
for ( i=0 ; i<10 ; i++ )
cout << t[i] << " ";
cout << endl;
delete [] t;
}
}
return 0;
}
Les Fichiers
Un fichier est un ensemble structuré d'informations stockées sur un support externe (disque dur, disquette, CD-ROM, DVD,
…).
Ecrire ou lire sur une mémoire de masse des données non volatiles, qui restent utilisables après l'exécution d'un programme,
est évidemment fondamental. Nous allons voir dans ce chapitre, comment nous pouvons manipuler des fichiers : les
déclarer, les créer, les ouvrir, lire ou écrire voire modifier des données s’y trouvant et les fermer.
Un fichier est une suite d'octets. Les informations contenues dans le fichier ne sont pas forcément de même type (un char, un
int, une structure ...)
1 ) Accès aux fichiers
Pour pouvoir manipuler un fichier de données en C++, il faut tout d'abord inclure dans le fichier .cpp la librairie fstream qui
fournit les fonctionnalités de manipulation de fichiers.
#include <fstream>
On y trouve essentiellement :
la classe ofstream (output file stream) qui permet d’écrire les données dans le fichier ;
la classe ifstream (input file stream) qui permet de lire les données du fichier ;
2) Ouvrir un fichier
La première chose à faire, quand on manipule un fichier, est de l'ouvrir. Pour ce faire, on déclare une variable en lui associant le nom physique du fichier
visé. Cette variable est de type ofstream s’il s’agit d’écriture, de type ifstream s’il s’agit de lecture ou de type fstream s’il s’agit de lecture/écriture.
La méthode la plus simple pour ouvrir un fichier est d’initialiser la variable qui doit lui être associée à l’aide d’une chaîne de caractères décrivant le
chemin d’accès au fichier.
ifstream input("Data.txt");
ofstream output("Res.txt");
"Data.txt" et "Res.txt" sont des chaînes de caractères donnant les noms réels des fichiers physiques. Cependant, si les fichiers ne sont pas dans le
même répertoire que le programme, il faut indiquer le chemin d'accès. Le caractère '' s'écrit en C++ '', ce qui pourrait donc donner par
Exemple :
ifstream input("c:testData.txt");
ofstream output("c:testRes.txt");
Cette façon d’ouvrir les fichiers présente plusieurs caractéristiques notables : Si le chemin d’accès comporte un répertoire qui n’existe pas, l’ouverture échoue.
Si le chemin est correct, mais que le fichier n’existe pas, il est créé. Si le fichier existe, il est ouvert. S’il s’agit d’ouverture en mode écriture, le contenu antérieur du
fichier est perdu.
• La fonction open()
Si l’initialisation d’une variable est une opération particulièrement simple, son inconvénient et qu’elle ne peut avoir lieu qu’une seule fois. Il arrive pourtant
qu’une même variable intervienne dans plusieurs ouvertures (ou tentatives d’ouvertures…) successives.
Les classes ofstream et ifstream proposent, pour répondre à ce besoin, une fonction membre nommée open() qui peut accepter comme paramètre un
chemin d’accès, comme le montre l’exemple
L’ouverture du fichier est une opération dont le succès ne peut être garanti. Il faut donc tester si l’ouverture a réussi avant d’effectuer des opérations sur
les données du fichier.
On détecte l’échec d’une ouverture de fichier en testant la valeur de la variable que l’on vient de tenter d’associer au fichier. Ceci est illustré dans les
deux exemples suivants:
!output : indique si l’opération sur le fichier a réussi.
7.2.2. Fermeture d’un fichier
Après l’ouverture d’un fichier et les différents traitements qui s’y rapportent, lorsque vous avez donc fini d’utiliser ce fichier, vos programmes doivent
fermer ce flux en utilisant la fonction membre close() comme suit :
• output.close() ;
• input.close() ;
On peut dire qu'entre les événements open() et close() le fichier est ouvert. Il est important de fermer les fichiers après les avoir utilisés, car seulement
un nombre limité de fichiers peuvent être ouverts simultanément par un programme. De plus, le traitement désiré (lecture ou écriture) peut être différé à
la fermeture du fichier. Sans fermeture de fichier, il n'est, par exemple, pas certain que les toutes données que l'on voulait écrire aient été réellement
transférées vers le support externe.
• Lecture et écriture
Il y a lieu maintenant de lire ou d’écrire des informations dans les fichiers. Pour être précis, il importe de signaler que les données lues ou écrites le sont d'abord dans
un tampon (buffer) de la mémoire, avant d'atteindre leur destination souhaitée. Ce tampon de fichier est une zone de
mémoire RAM dans laquelle on range temporairement, avant leur transfert à destination, une certaine quantité de données lues ou écrites dans un fichier. L’avantage
est qu’ainsi on n’a pas besoin de déclencher une opération d’entrée-sortie spécifique pour chaque donnée lue ou écrite.
• ios :: app - Ouvre un fichier texte à ajouter, ce qui signifie que nous pouvons ajouter le texte à la fin.
• ios :: in - Ouvre un fichier texte en lecture.
• ios :: out - Ouvre un fichier texte pour l'écriture.
• ios :: trunc - Il tronque le contenu avant d'ouvrir un fichier, si ce fichier existe.
• ios :: ate - Ouvre un fichier pour la sortie et déplace le contrôle en lecture / écriture à la fin du fichier.
Lecture et écriture
Il y a lieu maintenant de lire ou d’écrire des informations dans les fichiers. Pour être précis, il importe de signaler que les données lues ou écrites le sont d'abord dans
un tampon (buffer) de la mémoire, avant d'atteindre leur destination souhaitée. Ce tampon de fichier est une zone de
mémoire RAM dans laquelle on range temporairement, avant leur transfert à destination, une certaine quantité de données lues ou écrites dans un fichier. L’avantage
est qu’ainsi on n’a pas besoin de déclencher une opération d’entrée-sortie spécifique pour chaque donnée lue ou écrite. La gestion
du tampon est à la charge du système qui intervient lorsque le tampon est plein ou lorsqu'on lui impose de vider le tampon, notamment avec la fonction membre
close() L'ouverture ne donnant qu'un moyen d'accès, la lecture et/ou l’écriture dans des fichiers se fait
respectivement en utilisant les opérateurs >> et/ou << .
Mieux qu’un long discours, nous donnons dans la suite des exemples que nous commentons au fur et a mesure.
#include <fstream> // Fichier d'entete pour la gestion des fichiers
using namespace std;
int main()
{
// Création d'un objet ofstream -> pour ecrire
ofstream fichier;
fichier.open("E:codefichier.txt", ios::out);
// Si erreur d'ouverture
if(fichier.bad())
return 0; // on quitte
fichier << "Ce texte est ecrit dans le fichier" << endl;
// Fermeture du fichier
fichier.close();
return 0;
}
#include <fstream>
#include <iostream> // pour accès à la classe ofstream
using namespace std;
int main() {
ofstream ouput; // on déclare une instance de la classe ofstream
ouput.open("E:codefichier.txt"); // on ouvre le fichier fichier.txt
if(output) { // if (output != NULL) on vérifie si l'ouverture se passe bien
// ou if ( ! output.fail() ) pas d’erreur
cout<<"Pas d Erreur"<<endl;
char caract = 'A';
output << caract <<endl;
int Entier = 10;
output << Entier <<endl;
float Reel = 3.14;
output << Reel <<endl;
double monDouble = 7.12345;
output << monDouble <<endl;
ouput.close(); // on ferme le fichier
}
else{ // si échec à l'ouverture
cout<<"Erreur"<<endl;
}
}
#include <fstream> // pour accès à la classe ifstream
using namespace std;
void main() {
ifstream input; // on déclare une instance de la classe ifstream
input.open("fichier.txt"); // on ouvre le fichier fichier.txt
if(input) { // on vérifie si l'ouverture se passe bien
cout<<"Pas d Erreur"<<endl;
char caract;
input >> caract ;
int Entier ;
input >> Entier;
float Reel ;
input >> Reel ;
double monDouble ;
input >> monDouble ;
input.close(); // on ferme le fichier
cout << "Car = " << caract << " Entier = " << Entier
<< " Reel = " << Reel <<" Double = " << monDouble << endl;
}else{ // si échec à l'ouverture
cout<<"Erreur"<<endl;
}
Exercice 1
Rappel
Un programme qui utilise des fichiers de données doit inclure fstream
Pour écrire dans un fichier, on déclare une variable de type ofstream
ofstream ouput;
ouput.open("fichier.txt"); // on ouvre le fichier fichier.txt
if(ouput) { // on teste si l'ouverture s’est bien passée
On utilise l’opérateur d’insertion << pour envoyer dans le fichier les données.
Pour lire un fichier, on déclare une variable de type ifstraem
ifstream input;
input.open("fichier.txt"); // on ouvre le fichier fichier.txt
if(input) { // on teste si l'ouverture s’est bien passée
On utilise l’opérateur d’extraction >> pour envoyer dans des variables les informations extraites du fichier.
Pour extraire toute la ligne ou un ensemble de caractères on utilisera le fonction getline().
Utiliser la fonction close() pour fermer le fichier.
input.close() ;
Les Structures
• En C ++, la structure est une combinaison ou un groupe de différents éléments de données regroupés sous un même nom.
Les éléments de données sont appelés membres de données et ont un type et une longueur de données différents.
C'est un type de données défini par l'utilisateur qui vous permet de combiner des éléments de données de différents types.
Les structures sont utilisées pour définir les enregistrements, par exemple nous voulons afficher les enregistrements des employés ou les
enregistrements des étudiants.
1) Syntaxe de la structure
Pour définir la structure, vous devez utiliser l'instruction struct. L'instruction struct définit différents types de données pour différents membres de
données.
Exemple de la syntaxe avec la table employée
struct Employee{
char Name[10];
char Designation[10];
int Code;
int Salary;
};
Dans l'exemple ci-dessus, nous avons défini les membres de données avec la taille indiquée dans array
COMMENT ACCÉDER AUX DONNÉES MEMBRES DE LA STRUCTURE?
Vous pouvez accéder à n’importe quel membre de données d’une structure à l’aide de l’opérateur d’accès aux
membres (.).
L'opérateur d'accès au membre est valide entre le nom de la structure et le membre de la structure auquel il faut
accéder. Et pour définir les variables, vous utiliserez le mot-clé struct.
#include <iostream>
#include <cstring>
using namespace std;
struct Employee {
string Name[10];
string Designation[50];
int Code;
int Salary;
};
int main() {
struct Employee Emp1, Emp2;
cout << "Employee 1 Name : " << Emp1.Name <<endl;
cout << "Employee 1 Designation : " << Emp1.Designation <<endl;
cout << "Employee 1 Code : " << Emp1.Code <<endl;
cout << "Employee 1 Salary : " << Emp1.Salary <<endl;
cout << " Employee 2 Name: " << Emp2.Name <<endl;
cout << " Employee 2 Designation: " << Emp2.Designation <<endl;
cout << " Employee 2 Code: " << Emp2.Code <<endl;
cout << " Employee 2 Salary: " << Emp2.Salary <<endl;
return 0;
}
AVANTAGES DES STRUCTURES
Les avantages des structures en C ++ sont les suivants:
Les membres de données de structure sont publics par défaut. Il est rétrocompatible avec le code C.
QUE SONT LES STRUCTURES IMBRIQUÉES?
Les structures imbriquées sont celles où vous déclarez une structure dans une structure. Une structure comprend une autre structure
comme son membre.
PAR EXEMPLE,
vous avez deux structures Sujets et Étudiant. Pour que les sujets soient imbriqués dans Student, vous devez déclarer la structure
Subjects avant et hors de la structure Student et créer un objet de structure Subjects dans la structure Student.
#include <iostream>
using namespace std;
struct Person
{
char name[50];
int age;
float salary;
};
int main()
{
Person p1;
cout << "Enter Full name: ";
cin.get(p1.name, 50);
cout << "Enter age: ";
cin >> p1.age;
cout << "Enter salary: ";
cin >> p1.salary;
cout << "n Information." << endl;
cout << "Name: " << p1.name << endl;
cout <<"Age: " << p1.age << endl;
cout << "Salary: " << p1.salary;
return 0;
}
#include <iostream>
using namespace std;
struct Subjects{
char Name[25]="C++";
char Author[25]="XYZ";
int Code=9000;
};
struct Student{
int Id= 25;
char Name[25]="ABC";
struct Subjects Sub;
};
int main(void)
{
int i;
Student S;
cout << "nDetails of Student";
cout << "ntStudent Id : " << S.Id;
cout << "ntStudent Name : " << S.Name;
cout << "ntStudent Subject Name : " << S.Sub.Name;
cout << "ntStudent Subject Author : " << S.Sub.Author;
cout << "ntStudent Subject Code : " << S.Sub.Code;
return 0 ;
}
TABLEAU DE STRUCTURES
• Comme on l'a vu plus haut, cette structure est une collection de types de données différents et un objet de structure représente un seul
enregistrement en mémoire.
• Donc, si vous voulez ajouter plus d’enregistrements de type structure, vous devez créer un tableau de structure ou d’objet. Comme vous le
savez, le tableau est une collection de type de données similaire. Par conséquent, le tableau peut être de type structure.
#include <iostream>
using namespace std;
struct Student
{
int Id;
char Name[25];
int Age;
};
void main()
{
int i;
Student S[ 5 ];
for(i=0;i<5;i++)
{
cout << "nEnter details of " << i+1 << " Student";
cout << "ntEnter Student Id : ";
cin >> S[i].Id;
cout << "ntEnter Student Name : ";
cin >> S[i].Name;
cout << "ntEnter Student Age : ";
cin >> S[i].Age;
}
cout << "nPrint details of Student";
for(i=0;i<5;i++)
cout << "n"<< S[i].Id <<"t"<<S[i].Name <<"t" << S[i].Age;
}
III ) POINTEURS VERS DES STRUCTURES
Comme nous avons des pointeurs sur les types de données int, char, float et autres, de la même manière que vous avez les
pointeurs pointant sur des structures. Et ces pointeurs sont connus comme des pointeurs de structure.
#include <iostream>
#include <cstring>
using namespace std;
void printdetails(struct Employee *emp );
struct Employee {
char Name[10];
char Designation[50];
int Code;
int Salary;
};
int main() {
struct Employee Emp1;
struct Employee Emp2;
strcpy( Emp1.Name, "ABC");
strcpy( Emp1.Designation, "Manager");
Emp1.Code = 6495;
Emp1.Salary = 40000;
strcpy(Emp2.Name, "CDE");
strcpy(Emp2.Designation, "Analyst");
Emp2.Code = 6467;
Emp2.Salary = 20000;
printdetails(&Emp1);
printdetails(&Emp2);
return 0;
}
}
void printdetails(struct Employee *emp)
{
cout<< “Employee Name:” <<emp->Name <<endl;
cout<< “Employee Designation:”<<emp->Designation <<endl;
cout<< “Employee Code:”<<emp->Code <<endl;
cout<< “Employee Salary:”<<emp->Salary <<endl;
}
#include <iostream>
#include <string>
using namespace std; /* utilisation de l’espace de nommage std pour importer
les symboles de la bibliothèque standard C++ */
struct Client {
string nom;
string adresse;
char Code;
};
Client quel_client(int i, Client DataBase[])
{
if ((i > 0) && (i < 4 ))
return(DataBase[i]);
else
return(DataBase[0]);
}
int main(void) {
int N;
Client DataBase[4] = {
{« ADAMA", « Génie logiciel 00", 'B'},
{« Bintou", « Femme forte 123", 'D'},
{« KINE", « Sine Saloum 15", 'G'},
{« Mohamed", « Mecque 2341", 'M'}
};
cout << "Pour chercher un Client, donner un numero entre 1 et 4 : ";
cin >> N;
cout << "Debut de recherche du Client " << N << endl;
Client ce_client = quel_client(N-1, DataBase);
cout << "n NOM : " << ce_client.nom << "n Adresse : " << ce_client.adresse
<< "n Code : " << ce_client.Code << endl;
}
Partie II : Programmation Orientée Objet
Avec ce chapitre, nous abordons véritablement les possibilités de P.O.O. de C++. Comme nous l’avons dit dans le premier
chapitre, celles-ci reposent entièrement sur le concept de classe. Une classe est la généralisation de la notion de type défini
par l’utilisateur, dans lequel se trouvent associées à la fois des données (membres données) et des méthodes (fonctions
membres). En P.O.O. « pure », les données sont encapsulées et leur accès ne peut se faire que par le biais des méthodes. En
C++, en revanche, vous pourrez n’encapsuler qu’une partie des données d’une classe (même si cette démarche reste
généralement déconseillée).
Vous pourrez même ajouter des méthodes au type structure (mot clé struct) que nous avons déjà rencontré ; dans ce cas, il
n’existera aucune possibilité d’encapsulation. Ce type sera rarement employé sous cette forme généralisée mais comme, sur
un plan conceptuel, il correspond à un cas particulier de la classe, nous l’étudierons tout d’abord, ce qui nous permettra dans
un premier temps de nous limiter à la façon de mettre en oeuvre l’association des données et des méthodes. Nous ne verrons
qu’ensuite comment s’exprime l’encapsulation au sein d’une classe (mot clé class). Comme une classe (ou une structure)
n’est qu’un simple type défini par l’utilisateur, les objets possèdent les mêmes caractéristiques que les variables ordinaires,
en particulier en ce qui concerne leurs différentes classes d’allocation (statique, automatique, dynamique).
Cependant, pour rester simple et nous consacrer au concept de classe, nous ne considérerons dans ce chapitre que des objets
automatiques (déclarés au sein d’une fonction quelconque).
1 Les structures généralisées
Considérons une déclaration classique de structure telle que :
struct point {
int x ;
int y ;
}
C++ nous permet de lui associer des méthodes (fonctions membres). Supposons, par exemple, que nous souhaitions
introduire trois fonctions :
initialise pour attribuer des valeurs aux « coordonnées » d’un point ;
deplace pour modifier les coordonnées d’un point ;
Affiche pour afficher un point : ici, nous nous contenterons, par souci de simplicité, d’afficher les coordonnées du point.
Voyons comment y parvenir, en distinguant la déclaration de ces fonctions membres de leur définition.
1.1 Déclaration des fonctions membres d’une structure
Voici comment nous pourrions déclarer notre structure point :
struct point{
/* déclaration "classique" des données */
int x ;
int y ;
/* déclaration des fonctions membre (méthodes) */
void initialise (int, int) ;
void deplace (int, int) ;
void affiche () ;
} ;
Déclaration d’une structure comportant des méthodes
Outre la déclaration classique des champs de données apparaissent les déclarations (en-têtes) de nos trois fonctions. Notez bien que
la définition de ces fonctions ne figure pas à ce niveau de simple déclaration : elle sera réalisée par ailleurs, comme nous le verrons
un peu plus loin.
Ici, nous avons prévu que la fonction membre initialise recevra en arguments deux valeurs de type int. À ce niveau, rien n’indique
l’usage qui sera fait de ces deux valeurs. Ici, bien entendu, nous avons écrit l’en-tête de initialise en ayant à l’esprit l’idée qu’elle
affecterait aux membres x et y les valeurs reçues en arguments. Les mêmes remarques s’appliquent aux
deux autres fonctions membres. Vous vous attendiez peut-être à trouver, pour chaque fonction membre, un argument
supplémentaire précisant la structure de type point sur laquelle elle doit opérer. Nous verrons comment cette information sera
automatiquement fournie à la fonction membre lors de son appel
1.2 Définition des fonctions membres d’une structure
Elle se fait par une définition (presque) classique de fonction. Voici ce que pourrait être la définition de initialise :
void point::initialise (int abs, int ord)
{
x = abs ;
y = ord ;
}
Dans l’en-tête, le nom de la fonction est : point::initialise
Le symbole :: correspond à ce que l’on nomme l’opérateur de « résolution de portée », lequel sert à modifier la portée d’un
identificateur. Ici, il signifie que l’identificateur initialise concerné est celui défini dans point. En l’absence de ce « préfixe »
(point::), nous définirions effectivement une fonction nommée initialise, mais celle-ci ne serait plus associée à point ; il s’agirait
d’une fonction « ordinaire » nommée initialise, et non plus de la fonction membre initialise de la structure point. Si nous
examinons maintenant le corps de la fonction initialise, nous trouvons une affectation :
x = abs ;
Le symbole abs désigne, classiquement, la valeur reçue en premier argument. Mais x, quant à lui, n’est ni un argument ni une
variable locale. En fait, x désigne le membre x correspondant au type point (cette association étant réalisée par le point:: de l’en-
tête). Quelle sera précisément la structure de type point concernée ? Là encore, nous verrons comment cette information sera
transmise automatiquement à la fonction initialise lors de son appel.
Nous n’insistons pas sur la définition des deux autres fonctions membres ; vous trouverez ci-dessous
-l’ensemble des définitions des trois fonctions.
/* ----- Définition des fonctions membres du type point ---- */
#include <iostream>
using namespace std ;
void point::initialise (int abs, int ord)
{
x = abs ;
y = ord ;
}
void point::deplace (int dx, int dy)
{
x += dx ;
y += dy ;
}
void point::affiche ()
{
cout << "Je suis en " << x << " " << y << "n" ;
}
Exemple
#include <iostream>
using namespace std ;
/* ------------ Déclaration du type point ------------- */
struct point { /* déclaration "classique" des données */
int x ;
int y ;
/* déclaration des fonctions membres (méthodes) */
void initialise (int, int) ;
void deplace (int, int) ;
void affiche () ;
} ;
/* ----- Définition des fonctions membres du type point ---- */
void point::initialise (int abs, int ord) {
x = abs ; y = ord ;
}
void point::deplace (int dx, int dy) {
x += dx ; y += dy ;
}
void point::affiche () {
cout << "Je suis en " << x << " " << y << "n" ; }
main() {
point a, b ;
a.initialise (7, 2) ; a.affiche () ;
a.deplace (5, 4) ; a.affiche () ;
b.initialise (1,-1) ; b.affiche () ;
}
Remarques
1) La syntaxe même de l’appel d’une fonction membre fait que celle-ci reçoit obligatoirement
un argument implicite du type de la structure correspondante. Une fonction membre ne peut pas être appelée comme une
fonction ordinaire. Par exemple, cette instruction :
initialise (3,1) ; sera rejetée à la compilation (à moins qu’il n’existe, par ailleurs, une fonction ordinaire
nommée initialise).
2) Dans la déclaration d’une structure, il est permis (mais généralement peu conseillé) d’introduire les données et les
fonctions dans un ordre quelconque (nous avons systématiquement placé les données avant les fonctions).
Dans notre exemple de programme complet, nous avons introduit :
– la déclaration du type point ;
– la définition des fonctions membres ;
– la fonction (main) utilisant le type point.
Mais, bien entendu, il serait possible de compiler séparément le type point ; c’est d’ailleurs ainsi que l’on pourra « réutiliser
» un composant logiciel
Chapitre I : Classe et objet
1 Notion de classe
Comme nous l’avons déjà dit, en C++ la structure est un cas particulier de la classe. Plus précisément,
une classe sera une structure dans laquelle seulement certains membres et/ou fonctions membres seront « publics », c’est-à-dire
accessibles « de l’extérieur », les autres membres étant dits « privés
La déclaration d’une classe est voisine de celle d’une structure. En effet, il suffit
de remplacer le mot clé struct par le mot clé class ;
de préciser quels sont les membres publics (fonctions ou données) et les membres privés en utilisant les mots clés public et private.
Par exemple, faisons de notre précédente structure point une classe dans laquelle tous les membres données sont privés, et toutes
les fonctions membres sont publiques. :
• En C++, la notion de classe est une extension de la notion de type défini par l'utilisateur dans laquelle se trouvent associées des variables et des
fonctions.
• Les variables et les fonctions d'une classe sont dites les membres de cette classe. On dit aussi :
♦ Membres données ou propriétés pour les variables
♦ Fonctions membres ou méthodes pour les fonctions
• La POO pure exige l'encapsulation des données, c'est-à-dire que les membres données ne peuvent être manipulés qu'à travers les fonctions
membres. En C++, on peut n'encapsuler qu'une partie des membres données.
• C++ traite les structures et les unions comme des classes. Ainsi C++ permet d'associer des fonctions membres à des structures et des unions, mais
dans ce cas aucune encapsulation n'est possible (tous les membres sont publiques). D'autre part, dans les unions on ne peut définir qu'une seule
fonction membre
1 Définition d'une classe
La déclaration d'une classe consiste à décrire ses membres (membres données et prototypes de ses fonctions membres) groupés en sections.
Chaque section est étiquetée par l'un des mots clés : private, public, ou protected, qui précisent le mode d'accès aux membres contenus dans la
section.
♦ private : accès autorisé seulement dans fonction membres
♦ public : accès libre
protected : accès autorisé seulement dans les fonctions membres de la classe et de ses dérivées (voir héritage)
• Pour déclarer une classe, on utilise le mot clé class.
• Considérons, par exemple, la classe point qui comporte deux membres données privés 𝑥 et 𝑦 de type 𝑖nt et trois fonctions
membres publiques 𝑖nitialise, déplace et 𝑎ffiche.
• Utilisation d'une classe
Un objet (ou instance) object_𝑛ame d'une classe nommée 𝑐lasse_name est
déclaré comme une variable de type 𝑐lasse_name:
/* ------------ Déclaration de la classe point ------------- */
class point{ /* déclaration des membres privés */
private : /* facultatif () */
• int x ;
• int y ;
/* déclaration des membres publics */
public :
void initialise (int, int) ;
void deplace (int, int) ;
void affiche () ;
} ;
// Définition des fonctions membres de la classe point
void point::initialise (int abs, int ord)
{
x=abs; y=ord;
}
void point::deplace(int dx, int dy){
x=x+dx;
y=y+dy;
}
void point::affiche()
{
cout << "(" << x << "," << y << ")" << endl;
}
/* -------- Utilisation de la classe point -------- */
int main() {
point a,b;
a.initialise(5,2);
cout << "a = "; a.affiche();
a.deplace(-2,4);
cout << "Apres deplacement a = "; a.affiche();
b.initialise(1,-1);
cout << "b = "; b.affiche();
return 0;
}
Le mot clé ‘public’ précise que tout ce qui le suit (données membres ou fonctions membres) sera public, le reste étant privé. Ainsi :
- x et y sont deux membre privés.
- ‘initialise’, ‘deplace’ et ‘affiche’ sont trois fonctions membres publics.
- La classe ‘point’ ci-dessus peut être définie et utilisée comme dans l’exemple
suivant :
main()
{
point p1, p2, p3;
p1.initialise(1,3); p1.affiche();
p1.deplace(2,4); p1.affiche();
p2.initialise(5,5); p2.affiche();
}
On dit que p1 et p2 sont des instances de la classe ‘point’ ou encore que se sont des objets de type ‘point’.
- Tous les membres données de ‘point’ sont privés ou encapsulés. Ainsi, on ne peut pas accéder à x ou à y.
- Toutefois, les membres données ou les fonctions membres peuvent être privées en utilisant le mot clé ‘private’ ou publiques en
utilisant le mot clé ‘public’.
Exemple :
class C
{
public :
………………………………. ;
…………………………….. ;
private :
………………………………. ;
………………………………. ;
};
2)Affectation d’objets
• C++ autorise l'affectation d'un objet d'un type donnée à un autre objet de même type. Dans ce cas il recopie tout simplement les valeurs des
membres données (privés ou publiques) de l'un dans l'autre.
Exemple 3.2:
Exemple d’affectation entre objets
point a,b; // déclare deux instance de la classe point
a.initialise(2,5) // a.x = 2 et a.y = 5
b = a; // b.x = 2 et b.y = 5
• Il faut noter que les pointeurs ne sont pas pris en considération dans un cas simple d'affectation : Si parmi les membres données, se trouve un
pointeur, l'emplacement pointé ne sera pas recopié
3. Notion de constructeur et de destructeur
Un constructeur est une fonction qui sera appelée automatiquement après la création d’un objet. Ceci aura lieu quelque soit la classe d’allocation
de l’objet : statique, automatique ou dynamique.
- De la même façon, un objet pourra posséder un destructeur, il s’agit également d’une fonction membre qui est appelée automatiquement au
moment de la destruction de l’objet correspondant.
- Par convention, le constructeur se reconnaît à ce qu’il porte le même nom que la classe.
Quand au destructeur, il porte le même nom que la classe précédé du symbole ~.
class point {
int x;
int y;
public:
point(int,int); // constructeur ...
};
// Définition du constructeur
point::point(int abs, int ord)
{
x = abs;
y = ord;
}
Pour déclarer une instance d'une classe ayant un constructeur, on doit spécifier les valeurs des arguments requis par le constructeur
point a(2,5);
point b; // erreur
RQ:
• Même si le constructeur ne retourne aucune valeur, il est déclaré et défini sans le mot clé void
• Le destructeur est une fonction membre qui porte le même nom que sa classe, précédé du symbole (~). Le destructeur est appelé avant la libération de l'espace
associé à l'objet.
class point
{
int x;
int y;
public:
point(int,int); // constructeur
~point(); // destructeur
};
Sa syntaxe du destructeur est la suivante :
point::~point() {… … }
• Le destructeur est une fonction qui ne prend aucun argument et ne renvoie aucune valeur.
• En pratique les destructeurs sont utilisés pour libérer d'éventuels emplacements mémoire occupée par des membres données.
class demo {
int num ;
public :
demo(int);
~demo();
};
demo::demo(int n) {
num=n;
cout<<″Appel constr numéro : ″<<num<<endl;
}
demo::~demo()
{
cout<<″Appel destr numéro : ″<<num<<endl;
}
main() {
void f(int);
demo obj(7);
for (int i=0; i<4; i++)
f(i);
}
void f(int m){
demo obj(m) ;
}
• Le rôle d’un constructeur ou d’un destructeur peut dépasser celui d’initialisation ou de libération.
Rq:
• Un constructeur peut ou non comporter quelques arguments.
- par définition, un constructeur ne renvoie pas de valeur et la présence de void (dans ce cas précis) est une erreur.
- Un destructeur, par définition, ne peut pas disposer d’arguments et ne renvoie pas de valeur.
5)Membres données statiques
Lorsqu’on crée différents objets d’une même classe, chaque objet possède ces propres données membres,
• Un membre donnée déclaré avec l'attribut static est une donnée partagée par tous les instances d'une classe.
• Un membre donnée statique est initialisé par défaut à zéro. Mais :
♦ Il doit être défini à l'extérieur de la déclaration de la classe, même s'il est privé, en utilisant l'opérateur de porté (::).
♦ Ne peut être initialisé à l'intérieur de la classe.
Exemple:
une classe 𝐴 dont on veut connaître à chaque instant le nombre d'instances créées. Pour ce, on munit la classe 𝐴 d'un membre statique 𝑛b_𝑜bj, qu'on incrémente dans
le constructeur et qu’on décrémente dans le destructeur.
class A
{
static int nb_obj;
...
public:
A(...); // constructeur
~A() ;
...
};
// définition obligatoire du membre statique
int A::nb_obj;
// constructeur & destructeur
A::A(...) {... nb_obj++; ...}
A::~A(...) {... nb_obj--; ...}
L'accès à un membre donnée statique d'une classe suit les mêmes règles que les autres membres. D'autre part, un membre donnée
statique est une donnée qui existe même si aucun objet de cette classe n'est déclaré, dans ce cas l'accès se fait à l'aide du nom de
la classe et l'opérateur de porté (::).
/*------------------- Déclaration de la classe-------------------------*/
class point{
int x;
int y;
public:
static int nb_points; // membre donnee static
point(int, int);
~point();
void affiche();
};
/*------------------- Définition de la classe-------------------------*/
// la définition du membre donnée static est obligatoire
int point::nb_points; //Son initialisation peut être faite à ce niveau
point::point(int abs, int ord) {
x = abs; y = ord;
nb_points++; // un point est crée
}
point::~point(){
nb_points--; // un point est détruit
}
void point::affiche(){
cout << "(" << x << "," << y << ")" << endl;
cout << "---> nombre de points : " << nb_points << endl; }
}
// -------------- une fonction quelconque
void f(){
point c (2,2);
c.affiche();
}
//-------------- TEST
int main()
{
// l'accès au membre static peut se faire même si aucun objet // n'est encore crée
cout << "Nombre de points : " << point::nb_points << endl;
// appel d'une fonction qui manipule les objets de type ‘point’
f();
// tous les objets crées par f() sont détruits
cout << "Nombre de points après f() : " << point::nb_points << endl;
point a(5,2);
cout << "a = "; a.affiche();
point b(-2,4);
cout << "b = "; b.affiche();
return 0;
}
Chapitre 2 : Propriétés des fonctions membres
1)Surdéfinition des fonctions membre
La surdéfinition des fonctions s’applique également aux fonctions membres d’une classe, y compris au constructeur (mais pas au
destructeur puisqu’il ne possède pas d’arguments).
Exemple:
class point
{
int x, y;
public :
point();
point(int);
point(int,int);
void affiche();
void affiche(char *);
};
point::point() {
x=0; y=0;
}
point::point(int a) {
x=y=a;
}
point::point(int a,int b){
x=a;
y=b;
}
void point::affiche() {
cout<<″on est a : ″<<x<<″ - ″<<y<<endl;
}
void point::affiche(char *t) {
cout<<t;
affiche();
}
main() {
point p1; p1.affiche();
point p2(7); p2.affiche();
point p3(44,52); p3.affiche();
p3.affiche(″Troisième point : ″);
2. Arguments par défaut
Comme les fonctions ordinaires, les fonctions membres peuvent disposer d’arguments par défaut. Voici comment nous pourrions
modifier l’exemple précédent pour que notre classe point ne possède plus qu’une seule fonction affiche disposant d’un seul argument
de type chaîne. Celui-ci indique le message à afficher avant les valeurs des coordonnées, et sa valeur par défaut est la chaîne vide.
Exemple:
#include <iostream>
using namespace std ;
class point
{
int x, y ;
public :
point () ; // constructeur 1 (sans argument)
point (int) ; // constructeur 2 (un argument)
point (int, int) ; // constructeur 3 (deux arguments)
void affiche (char * = "") ; // fonction affiche (un argument par défaut)
} ;
point::point () // constructeur 1
{
x = 0 ; y = 0 ;
}
point::point (int abs) // constructeur 2
{
x = y = abs ;
}
point::point (int abs, int ord) // constructeur 3
{
x = abs ; y = ord ;
}
void point::affiche (char * message) // fonction affiche
{
cout << message << "Je suis en : " << x << " " << y << "n" ;
}
main() {
point a ; // appel constructeur 1
a.affiche () ;
point b (5) ; // appel constructeur 2
b.affiche ("Point b - ") ;
point c (3, 12) ; // appel constructeur 3
c.affiche (« Salut ---- ") ;
}
3 Les fonctions membres en ligne
Pour rendre ‘en ligne’ une fonction membre, on l’a défini dans la déclaration de la classe même (au lieu de la déclarer dans la classe
et de la définir ailleurs). Le mot clé ‘inline’ n’est plus utilisé.
#include <iostream>
using namespace std ;
class point
{
int x, y ;
public :
point () { x = 0 ; y = 0 ; } // constructeur 1 "en ligne"
point (int abs) { x = y = abs ; } // constructeur 2 "en ligne"
point (int abs, int ord) { x = abs ; y = ord ; } // constructeur 3 "en ligne"
void affiche (char * = "") ;
} ;
void point::affiche (char * message) // fonction affiche
{
cout << message << "Je suis en : " << x << " " << y << "n" ;
}
main()
{
point a ; // "appel" constructeur 1
a.affiche () ;
point b (5) ; // "appel" constructeur 2
b.affiche ("Point b - ") ;
point c (3, 12) ; // "appel" constructeur 3
c.affiche ("Hello ---- ") ;
}
4. Cas des objets transmis en argument d’une fonction membre
Une fonction membre peut recevoir un ou plusieurs arguments du type de sa classe.
Exemple :
class point {
int x, y;
public :
point(int a,int b){ x=a; y=b; }
int coincide(point);
};
int point::coincide(point O)
{
if(x==O.x && y==O.y) return 1;
return 0;
}
main(){
point p1(5,7), p2(5,7), p3(6,6);
cout<<″p1 et p2 : ″<<p1.coincide(p2)<<endl;
cout<<″p2 et p3 : ″<<p3.coincide(p2)<<endl;
cout<<″p1 et p3 : ″<<p1.coincide(p3)<<endl;
}
5. Mode de transmission des objets, arguments d’une fonction
Dans l’exemple ci-dessus, le mode de transmission utilisé, était par valeur.
5.1. Transmission de l’adresse d’un objet
Exemple : reprendre le programme précédent en faisant un passage d’objets par adresse
class point
{
int x, y;
public :
point (int a=0,int b=0)
{
x=a;
y=b;
}
int coincide(point *);
};
int point::coincide(point *O)
{
if(x==O->x) && (y==O->y)
return 1;
return 0;
}
main()
{
point p1, p2(57), p3(57,0);
cout<<″p1 et p2 : ″<<p1.coincide(&p2)<<endl;
cout<<″p2 et p3 : ″<<p3.coincide(&p2)<<endl;
cout<<″p1 et p3 : ″<<p1.coincide(&p3)<<endl;
}
5.2. Transmission par référence
L’emploi des références permet de mettre en place une transmission par adresse, sans avoir à prendre en charge soi même la gestion.
class point
{
int x,y ;
public :
point(int a=0,int b=0){ x=a; y=b; }
int coincide(point &);
};
int point::coincide(point & O)
{
return (x==O.x && y==O.y) ? 1 : 0;
}
main()
{
point p1, p2(57), p3(57,0);
cout<<″p1 et p2 : ″<<p1.coincide(p2)<<endl;
cout<<″p2 et p3 : ″<<p3.coincide(p2)<<endl;
cout<<″p1 et p3 : ″<<p1.coincide(p3)<<endl;
}
6. Autoréférence : le mot clé ‘this’
Le mot clé ‘this’ utilisé uniquement au sein d’une fonction membre désigne un pointeur sur l’objet l’ayant appelé.
class point
{
int x, y;
public :
point(int a=0,int b=0){ x=a; y=b; }
void affiche(){ cout<<″Point : ″<<x<<″ - ″<<y<<″de l’objet dont l’adresse est : ″<<this<<endl; }
};
main()
{
point p1, p2(5,3), p3(6,70);
p1.affiche();
p2.affiche();
p3.affiche();
}
#include <iostream>
using namespace std ;
class point {
int x, y ;
public :
point (int abs=0, int ord=0) // Un constructeur ("inline")
{
x=abs;
y=ord ;
}
void affiche () ; // Une fonction affiche
} ;
void point::affiche () {
cout << "Adresse : " << this << " - Coordonnees " << x << " " << y << "n" ;
}
main()
{
point a(5), b(3,15) ;
a.affiche ();
b.affiche ();
}
Chapitre 3 : Construction, destruction et initialisation des objets
1. Objets automatiques et statiques
1.1. Durée de vie d’allocation mémoire
Les objets automatiques sont créés par une déclaration :
- Dans une fonction.
- Dans un bloc.
Les objets statiques créés par une déclaration :
- En dehors de toute fonction.
- Dans une fonction, mais ‘static’.
Remarque
Les objets statiques sont créés avant le début de l’exécution de la fonction ‘main’ et ils sont détruits après la fin de son exécution
1.2 Appel des constructeurs et des destructeurs
Rappelons que si un objet possède un constructeur, sa déclaration (lorsque, comme nous le supposons pour l’instant, elle ne contient
pas d’initialiseur) doit obligatoirement comporter les arguments correspondants.
si une classe point comporte le constructeur de prototype :
point (int, int) les déclarations suivantes seront incorrectes :
point a ; // incorrect : le constructeur attend deux arguments
point b (3) ; // incorrect (même raison) Celle-ci, en revanche, conviendra :
point a(1, 7) ; // correct car le constructeur possède deux arguments S’il existe plusieurs constructeurs, il suffit que la déclaration comporte les arguments
requis par l’un d’entre eux. Ainsi, si une classe point comporte les constructeurs suivants : point ( ) ; // constructeur 1
point (int, int) ; // constructeur 2 la déclaration suivante sera rejetée :
point a(5) ; // incorrect : aucun constructeur à un argument
Mais celles-ci conviendront :
point a ; // correct : appel du constructeur 1
point b(1, 7) ; // correct : appel du constructeur 2
En ce qui concerne la chronologie, on peut dire que :
• le constructeur est appelé après la création de l’objet ;
• le destructeur est appelé avant la destruction de l’objet.
#include <iostream>
using namespace std ;
class point
{
int x, y ;
public :
point (int abs, int ord) // constructeur ("inline")
{
x = abs ; y = ord ;
cout << "++ Construction d’un point : " << x << " " << y << "n" ;
}
~point () // destructeur ("inline")
{
cout << "-- Destruction du point : " << x << " " << y << "n" ;
}
} ;
point a(1,1) ; // un objet statique de classe point
main()
{
cout << "****** Debut main *****n" ;
point b(10,10) ; // un objet automatique de classe point
int i ;
for (i=1 ; i<=3 ; i++)
{ cout << "** Boucle tour numero " << i << "n" ;
point b(i,2*i) ; // objets créés dans un bloc
}
cout << "****** Fin main ******n" ;
}
2. Les objets temporaires
Lorsqu’une classe dispose d’un constructeur, ce dernier peut être appelé explicitement ; dans ce cas, il y a alors création d’un objet
temporaire.
Exemple
#include <iostream>
using namespace std ;
class point
{ int x, y ;
public :
point (int abs, int ord) // constructeur ("inline")
{ x = abs ; y = ord ;
cout << "++ Constr. point " << x << " " << y << " a l’adresse : " << this << "n" ;
}
~point () // destructeur ("inline")
{ cout << "-- Destr. point " << x << " " << y << " a l’adresse : " << this << "n" ;
}
} ;
main(){
point a(0,0) ; // un objet automatique de classe point
a = point (1, 2) ; // un objet temporaire
a = point (3, 5) ; // un autre objet temporaire
cout << "****** Fin main ******n" ;
}
On voit clairement que les deux affectations de la fonction main entraînent la création d’un objet temporaire distinct de
a, qui se trouve détruit tout de suite après. La dernière destruction,réalisée après la fin de l’exécution, concerne l’objet
automatique a
Exemple d’objet dynamique:
#include <iostream>
using namespace std ;
class point
{
int x, y ;
public :
point (int abs, int ord) // constructeur
{
x=abs ; y=ord ;
cout << "++ Appel Constructeur n" ;
}
~point () // destructeur (en fait, inutile ici)
{
cout << "-- Appel Destructeur n" ;
}
} ;
main()
{
void fct (point *) ; // prototype fonction fct
point * adr ;
cout << "** Debut main n" ;
adr = new point (3,7) ; // création dynamique d’un objet
fct (adr) ;
cout << "** Fin main n" ;
}
void fct (point * adp)
{
cout << "** Debut fct n" ;
delete adp ; // destruction de cet objet
cout << "** Fin fct n" ;
}
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx
COURS C++ [Enregistrement automatique]Complet (1).pptx

Contenu connexe

Similaire à COURS C++ [Enregistrement automatique]Complet (1).pptx

Cours_C_for_Etudiant.pdf
Cours_C_for_Etudiant.pdfCours_C_for_Etudiant.pdf
Cours_C_for_Etudiant.pdfHailisara
 
C++ 11 - Tech Days 2014 in Paris
C++ 11 - Tech Days 2014 in ParisC++ 11 - Tech Days 2014 in Paris
C++ 11 - Tech Days 2014 in Parischristophep21
 
Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
Bonnes pratiques pour apprivoiser le C++11 avec Visual C++Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
Bonnes pratiques pour apprivoiser le C++11 avec Visual C++Microsoft
 
Programmation-en-C-ESIITECH-2023-2024.pptx
Programmation-en-C-ESIITECH-2023-2024.pptxProgrammation-en-C-ESIITECH-2023-2024.pptx
Programmation-en-C-ESIITECH-2023-2024.pptxOlyvierNzighou1
 
Programmation-en-C-ESIITECH-2023-2024-bis.pptx
Programmation-en-C-ESIITECH-2023-2024-bis.pptxProgrammation-en-C-ESIITECH-2023-2024-bis.pptx
Programmation-en-C-ESIITECH-2023-2024-bis.pptxOlyvierNzighou1
 
Cours langage C et C++
Cours langage C et C++Cours langage C et C++
Cours langage C et C++mohamednacim
 
Chap 1 Initiation.pptx
Chap 1 Initiation.pptxChap 1 Initiation.pptx
Chap 1 Initiation.pptxolfaharrabi2
 
Cours de C++, en français, 2002 - Cours 1.2
Cours de C++, en français, 2002 - Cours 1.2Cours de C++, en français, 2002 - Cours 1.2
Cours de C++, en français, 2002 - Cours 1.2Laurent BUNIET
 
Cours VB 2012 seance 1
Cours VB 2012 seance 1Cours VB 2012 seance 1
Cours VB 2012 seance 1ISIG
 
Dotnet csharp
Dotnet csharpDotnet csharp
Dotnet csharpSDFG5
 
20131024 qualité de code et sonar - mug lyon
20131024   qualité de code et sonar - mug lyon20131024   qualité de code et sonar - mug lyon
20131024 qualité de code et sonar - mug lyonClement Bouillier
 

Similaire à COURS C++ [Enregistrement automatique]Complet (1).pptx (20)

Fascicule tp programmation c
Fascicule tp programmation cFascicule tp programmation c
Fascicule tp programmation c
 
introduction au CPP
introduction au CPPintroduction au CPP
introduction au CPP
 
Microsoft07coursbaptiste
Microsoft07coursbaptisteMicrosoft07coursbaptiste
Microsoft07coursbaptiste
 
Langage C++
Langage C++Langage C++
Langage C++
 
cours1.ppt
cours1.pptcours1.ppt
cours1.ppt
 
Cours_C_for_Etudiant.pdf
Cours_C_for_Etudiant.pdfCours_C_for_Etudiant.pdf
Cours_C_for_Etudiant.pdf
 
Langage C
Langage CLangage C
Langage C
 
Cours de c
Cours de cCours de c
Cours de c
 
C++ 11 - Tech Days 2014 in Paris
C++ 11 - Tech Days 2014 in ParisC++ 11 - Tech Days 2014 in Paris
C++ 11 - Tech Days 2014 in Paris
 
Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
Bonnes pratiques pour apprivoiser le C++11 avec Visual C++Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
 
Programmation-en-C-ESIITECH-2023-2024.pptx
Programmation-en-C-ESIITECH-2023-2024.pptxProgrammation-en-C-ESIITECH-2023-2024.pptx
Programmation-en-C-ESIITECH-2023-2024.pptx
 
Programmation-en-C-ESIITECH-2023-2024-bis.pptx
Programmation-en-C-ESIITECH-2023-2024-bis.pptxProgrammation-en-C-ESIITECH-2023-2024-bis.pptx
Programmation-en-C-ESIITECH-2023-2024-bis.pptx
 
Intro c++
Intro c++Intro c++
Intro c++
 
Cours langage C et C++
Cours langage C et C++Cours langage C et C++
Cours langage C et C++
 
Chap 1 Initiation.pptx
Chap 1 Initiation.pptxChap 1 Initiation.pptx
Chap 1 Initiation.pptx
 
Cours de C++, en français, 2002 - Cours 1.2
Cours de C++, en français, 2002 - Cours 1.2Cours de C++, en français, 2002 - Cours 1.2
Cours de C++, en français, 2002 - Cours 1.2
 
Cours VB 2012 seance 1
Cours VB 2012 seance 1Cours VB 2012 seance 1
Cours VB 2012 seance 1
 
Dotnet csharp
Dotnet csharpDotnet csharp
Dotnet csharp
 
20131024 qualité de code et sonar - mug lyon
20131024   qualité de code et sonar - mug lyon20131024   qualité de code et sonar - mug lyon
20131024 qualité de code et sonar - mug lyon
 
Cours Ynov JS B1_1
Cours Ynov JS B1_1Cours Ynov JS B1_1
Cours Ynov JS B1_1
 

Dernier

présentation sur la logistique (4).
présentation     sur la  logistique (4).présentation     sur la  logistique (4).
présentation sur la logistique (4).FatimaEzzahra753100
 
JTC 2024 - Réglementation européenne BEA et Transport.pdf
JTC 2024 - Réglementation européenne BEA et Transport.pdfJTC 2024 - Réglementation européenne BEA et Transport.pdf
JTC 2024 - Réglementation européenne BEA et Transport.pdfInstitut de l'Elevage - Idele
 
JTC 2024 La relance de la filière de la viande de chevreau.pdf
JTC 2024 La relance de la filière de la viande de chevreau.pdfJTC 2024 La relance de la filière de la viande de chevreau.pdf
JTC 2024 La relance de la filière de la viande de chevreau.pdfInstitut de l'Elevage - Idele
 
JTC 2024 - SMARTER Retour sur les indicateurs de santé .pdf
JTC 2024 - SMARTER Retour sur les indicateurs de santé .pdfJTC 2024 - SMARTER Retour sur les indicateurs de santé .pdf
JTC 2024 - SMARTER Retour sur les indicateurs de santé .pdfInstitut de l'Elevage - Idele
 
Câblage, installation et paramétrage d’un réseau informatique.pdf
Câblage, installation et paramétrage d’un réseau informatique.pdfCâblage, installation et paramétrage d’un réseau informatique.pdf
Câblage, installation et paramétrage d’un réseau informatique.pdfmia884611
 
Algo II : les piles ( cours + exercices)
Algo II :  les piles ( cours + exercices)Algo II :  les piles ( cours + exercices)
Algo II : les piles ( cours + exercices)Sana REFAI
 
JTC 2024 - Leviers d’adaptation au changement climatique, qualité du lait et ...
JTC 2024 - Leviers d’adaptation au changement climatique, qualité du lait et ...JTC 2024 - Leviers d’adaptation au changement climatique, qualité du lait et ...
JTC 2024 - Leviers d’adaptation au changement climatique, qualité du lait et ...Institut de l'Elevage - Idele
 

Dernier (9)

présentation sur la logistique (4).
présentation     sur la  logistique (4).présentation     sur la  logistique (4).
présentation sur la logistique (4).
 
JTC 2024 - Réglementation européenne BEA et Transport.pdf
JTC 2024 - Réglementation européenne BEA et Transport.pdfJTC 2024 - Réglementation européenne BEA et Transport.pdf
JTC 2024 - Réglementation européenne BEA et Transport.pdf
 
JTC 2024 La relance de la filière de la viande de chevreau.pdf
JTC 2024 La relance de la filière de la viande de chevreau.pdfJTC 2024 La relance de la filière de la viande de chevreau.pdf
JTC 2024 La relance de la filière de la viande de chevreau.pdf
 
JTC 2024 - SMARTER Retour sur les indicateurs de santé .pdf
JTC 2024 - SMARTER Retour sur les indicateurs de santé .pdfJTC 2024 - SMARTER Retour sur les indicateurs de santé .pdf
JTC 2024 - SMARTER Retour sur les indicateurs de santé .pdf
 
Câblage, installation et paramétrage d’un réseau informatique.pdf
Câblage, installation et paramétrage d’un réseau informatique.pdfCâblage, installation et paramétrage d’un réseau informatique.pdf
Câblage, installation et paramétrage d’un réseau informatique.pdf
 
Algo II : les piles ( cours + exercices)
Algo II :  les piles ( cours + exercices)Algo II :  les piles ( cours + exercices)
Algo II : les piles ( cours + exercices)
 
JTC 2024 - DeCremoux_Anomalies_génétiques.pdf
JTC 2024 - DeCremoux_Anomalies_génétiques.pdfJTC 2024 - DeCremoux_Anomalies_génétiques.pdf
JTC 2024 - DeCremoux_Anomalies_génétiques.pdf
 
JTC 2024 - Leviers d’adaptation au changement climatique, qualité du lait et ...
JTC 2024 - Leviers d’adaptation au changement climatique, qualité du lait et ...JTC 2024 - Leviers d’adaptation au changement climatique, qualité du lait et ...
JTC 2024 - Leviers d’adaptation au changement climatique, qualité du lait et ...
 
CAP2ER_GC_Presentation_Outil_20240422.pptx
CAP2ER_GC_Presentation_Outil_20240422.pptxCAP2ER_GC_Presentation_Outil_20240422.pptx
CAP2ER_GC_Presentation_Outil_20240422.pptx
 

COURS C++ [Enregistrement automatique]Complet (1).pptx

  • 1. COURS C++ 2018 - 2019 Professeur Adama Sabaly
  • 2.  Partie I Introduction du langage C++ 1) Historique a) Forces et faiblesses b) Outils de programmation c) Création nouveau projet • Chapitre 1 : Généralités sur le langage C++. 1) Structure d’un programme C++ a)Bibliothèque b) Affichage cout && espace de nom c)Fonction main 2 ) exemple d’un programme C++ Chapitre II les types de Base C++ a) Variable b) Déclaration variable c) Types de variables d) Initialisation variables &&différents types déclarations de variables e) Références 4)Lecture de la console 4-1) les chevrons 4-2) les autres variables 4-3 ) changer le contenu d’une variable
  • 3. 5)Notation des constantes 5-1) déclaration a) initialisation 5-2)exemple 6 - Les types caractères && types de déclarations de caractères 6.1 La notion de caractère en langage C++ 6.2 Notation des constantes caractère 6 - Le type bool Exemple et exercices Chapitre III : Opérateurs et expressions 1) Les types d’operateurs Exemple • 2) les expréssions exemples • Les racourcis • Incrémentation • Décrementation • 1) autres opérations • Fonctions mathématiques • Expemle puissance , valeur absolue  Chapitre 4: Les instructions de contrôle • 1 - Les blocs d’instructions . • 1.1 Blocs d’instructions • 1.2 Déclarations dans un bloc • 2 - L’instruction if • 2.1 Syntaxe de l’instruction if • 2.2 Exemples • 2.3 Imbrication des instructions if
  • 4. • 3 - L’instruction switch • 3.1 Exemples d’introduction de l’instruction switch • 3.2 Syntaxe de l’instruction switch . • 4 - Instruction do... while • 4.1 Exemple d’introduction de l’instruction do... while • 4.2 Syntaxe de l’instruction do... while • 5 - L’instruction while • 5.1 Exemple d’introduction de l’instruction while • 5.2 Syntaxe de l’instruction while • 6 - L’instruction for • 6.1 Exemple d’introduction de l’instruction for • 6.2 L’instruction for en général • 6.3 Syntaxe de l’instruction for • 7 - Les instructions de branchement inconditionnel : break, continue et GOTO • 7.1 L’instruction break • 7.2 L’instruction continue . • 7.3 L’instruction GOTO
  • 5. Chapitre 6 : Les fonctions • 1 - Exemple de définition et d’utilisation d’une fonction • 2 - Quelques règles • 2.1 Arguments muets et arguments effectifs • 2.2 L’instruction return • 2.3 Cas des fonctions sans valeur de retour ou sans argument • 3 - Les fonctions et leurs déclarations • 3.1 Les différentes façons de déclarer une fonction • 3.2 Où placer la déclaration d’une fonction • 3.3 Contrôles et conversions induites par le prototype
  • 6. Chapitre 7 : Les tableaux et les pointeurs • 1 - Les tableaux à un indice • 1.1 Exemple d’utilisation d’un tableau en C++. • 1.2 Quelques règles . 1.2.1 Les éléments de tableau . . . • 1.2.2 Les indices • 1.2.3 La dimension d’un tableau. • 2 - Les tableaux à plusieurs indices . • 2.1 Leur déclaration. . • 2.2 Arrangement en mémoire des tableaux à plusieurs indices. • 3 - Initialisation des tableaux . • 3.1 Initialisation de tableaux à un indice • 3.2 Initialisation de tableaux à plusieurs indices • 3.3 Initialiseurs et classe d’allocation • 4 - Notion de pointeur – Les opérateurs * et & • 4.1 Introduction • 4.2 Quelques exemples • 4.3 Incrémentation de pointeurs • 5 - Comment simuler une transmission par adresse avec un pointeur • 6 - Un nom de tableau est un pointeur constant • 6.1 Cas des tableaux à un indice • 6.2 Cas des tableaux à plusieurs indices • 7 - Les opérations réalisables sur des pointeurs . • 7.1 La comparaison de pointeurs • 7.2 La soustraction de pointeurs • 7.3 Les affectations de pointeurs et le pointeur nul
  • 7. Partie II : Chapitre 11 : 1 - Programmation structurée et programmation orientée objet • 1.1 Problématique de la programmation • 1.2 La programmation structurée • 1.3 Les apports de la programmation orientée objet • 1.3.1 Objet • 1.3.2 Encapsulation • 1.3.3 Classe • 1.3.4 Héritage • 1.3.5 Polymorphisme • 1.4 P.O.O., langages de programmation et C • 2 - C++ et la programmation structurée • 3 - C++ et la programmation orientée objet
  • 8. Introduction du langage C++ 1) Qu’est ce que le C++ Le langage C++ est un langage de programmation compilé permettant la programmation sous de multiples paradigmes procédurale et Orienté objet. Parmi les centaines de langages de programmation qui existent, certains sont plus populaires que d'autres. Sans aucun doute, le C++ est un langage très populaire. Des sites comme langpop.com tiennent à jour un classement des langages les plus couramment utilisés, si cette information vous intéresse. Comme vous pourrez le constater, le C, le Java et le C++ occupent régulièrement le haut du classement. La question est : faut-il choisir un langage parce qu'il est populaire ? Il existe des langages très intéressants mais peu utilisés. Le souci avec les langages peu utilisés, c'est qu'il est difficile de trouver des gens pour vous aider et vous conseiller quand vous avez un problème. Voilà entre autres pourquoi le C++ est un bon choix pour qui veut débuter : il y a suffisamment de gens qui développent en C++ pour que vous n'ayez pas à craindre de vous retrouver tous seuls ! Bien entendu, il y a d'autres critères que la popularité. Le plus important à mes yeux est le niveau du langage. Il existe des langages de haut niveau et d'autres de plus bas niveau. 2) Historique C'est Bjarne Stroustrup, un informaticien originaire du Danemark, qui a conçu le langage C++. Insatisfait des possibilités offertes par le C, il a créé en 1983 le C++ en y ajoutant les possibilités qui, selon lui, manquaient. Bjarne Stroustrup est aujourd'hui professeur d'informatique à l'université Texas A&M, aux Etats-Unis. Il s'agit d'une importante figure de l'univers informatique qu'il faut connaître, au moins de nom (du moins si vous arrivez à le retenir !). De nombreux langages de programmation se sont par la suite inspirés du C++. C'est notamment le cas du langage Java.
  • 9. 3) Forces && faiblesses Il est très répandu. Comme nous l'avons vu, il fait partie des langages de programmation les plus utilisés sur la planète. On trouve donc beaucoup de documentation sur Internet et on peut facilement avoir de l'aide sur les forums. Il paraît même qu'il y a des gens sympas qui écrivent des cours pour débutants dessus. Il est rapide, très rapide même, ce qui en fait un langage de choix pour les applications critiques qui ont besoin de performances. C'est en particulier le cas des jeux vidéo, mais aussi des outils financiers ou de certains programmes militaires qui doivent fonctionner en temps réel. Il est portable : un même code source peut théoriquement être transformé sans problème en exécutable sous Windows, Mac OS et Linux. 1) Structure d’un programme C++ Pour la structure du programme nous avons le fameux « hello world » : b) Outils de programmation Voici le strict minimum pour un programmeur : Un éditeur de texte pour écrire le code source du programme en C++. En théorie un logiciel comme le Bloc-Notes sous Windows ou vi sous Linux fait l'affaire. L'idéal, c'est d'avoir un éditeur de texte intelligent qui colore tout seul le code, ce qui vous permet de vous y repérer bien plus facilement. Voilà pourquoi aucun programmeur sain d'esprit n'utilise le Bloc-Notes. Un compilateur pour transformer (« compiler ») votre code source en binaire. Un débugger (« Débogueur » ou « Débugueur » en français) pour vous aider à traquer les erreurs dans votre programme (on n'a malheureusement pas encore inventé le « correcteur », un truc qui corrigerait tout seul nos erreurs).
  • 10. Exemple de code source : #include <iostream> : C'est ce qu'on appelle une directive de préprocesseur. Son rôle est de « charger » des fonctionnalités du C++ pour que nous puissions effectuer certaines actions.En effet, le C++ est un langage très modulaire. De base, il ne sait pas faire grand-chose (pas même afficher un message à l'écran On doit donc charger des extensions que l'on appelle bibliothèques et qui nous offrent de nouvelles possibilités.Ici, on charge le fichier iostream, ce qui nous permet d'utiliser une bibliothèque… d'affichage de messages à l'écran dans une console ! Quelque chose de vraiment très basique, comme vous le voyez, mais qui nécessite quand même l'utilisation d’une bibliothèque. using namespace std : permet en quelque sorte d'indiquer dans quel lot de fonctionnalités notre fichier source va aller piocher. on a créé des namespaces (espaces de noms), qui sont des sortes de dossiers à noms. La ligne using namespace std; indique que vous allez utiliser l'espace de noms std dans la suite de votre fichier de code et le cout fait partie de l’espace de nom. Cet espace de noms est un des plus connus car il correspond à la bibliothèque standard (std), une bibliothèque livrée par défaut avec le langage C++ et dont iostream fait partie. • int main() : C'est ici que commence vraiment le coeur du programme. Les programmes, vous le verrez, sont essentiellement constitués de fonctions. Chaque fonction a un rôle et peut appeler d'autres fonctions pour effectuer certaines actions. Tous les programmes possèdent une fonction dénommée « main » (Qui se prononce « mèïne » en anglais.), ce qui signifie «principale ». C'est donc la fonction principale. {} les accolades déterminent le début et la fin de la fonction cout : commande l'affichage d'un message à l'écran ; "Hello world!" : indique le message à afficher ; endl : crée un retour à la ligne dans la console return 0; : Ce type d'instruction clôt généralement les fonctions. En fait, la plupart des fonctions renvoient une valeur (un nombre par exemple). Ici, la fonction main renvoie 0 pour indiquer que tout s'est bien passé (toute valeur différente de 0 aurait indiqué un problème).
  • 11. Exemple en utilisant les commentaires • #include <iostream> // Inclut la bibliothèque iostream (affichage de texte) • using namespace std; // Indique quel espace de noms on va utiliser /* Fonction principale "main" Tous les programmes commencent par la fonction main */ int main() { cout << "Hello world!" << endl; // Affiche un message return 0; // Termine la fonction main et donc le programme }
  • 12. Chapitre II les types de Base C++ a) Variable Une variable est une espace mémoire stockée , Assez parlé, il est temps d'entrer dans le vif du sujet et de demander à l'ordinateur de nous prêter un de ses tiroirs. En termes techniques, on parle de déclaration de variable. Il nous faut indiquer à l'ordinateur le type de la variable que nous voulons, son nom et enfin sa valeur. Pour ce faire, c'est très simple : on indique les choses exactement dans l'ordre présenté à la figure suivante. Exemple1 : #include <iostream> using namespace std; int main() { int age(28); return 0; }
  • 13. Exemple2: #include <iostream> using namespace std; int main() { int ageUtilisateur(28); int nombreAmis(432); double pi(3.14159); bool estMonAmi(true); char lettre(‘a’); return 0; } Le cas des strings Les chaînes de caractères sont un petit peu plus complexes à déclarer mais rien d'insurmontable, je vous rassure. La première chose à faire est d'ajouter une petite ligne au début de votre programme. Il faut, en effet, indiquer au compilateur que nous souhaitons utiliser des strings. Sans cela, il n'inclurait pas les outils nécessaires à leur gestion. La ligne à ajouter est • #include <string>.
  • 14. Exemple: #include <iostream> #include <string> using namespace std; int main() { string nom("Sabaly "); return 0; } Il faut utiliser cout et les chevrons (<<). Parfait. En effet, pour afficher le contenu d'une variable, c'est la même chose. À la place du texte à afficher, on met simplement le nom de la variable. Exemple: #include <iostream> using namespace std; int main() { int Monage(28); cout << "Votre age est : "; cout << Monage; return 0; }
  • 15. Exemple une autre façon d’affichage: #include <iostream> using namespace std; int main() { int Monage(16); cout << "Votre age est : " << Monage << endl; return 0; } Exemple : Combinaison une chaine avec le type entier #include <iostream> #include <string> using namespace std; int main() { int Age(60); string nom("Adama Sabaly"); cout << "Vous vous appelez " << nom << " et votre age est " << Age << endl; return 0; }
  • 16. 4) Lecture au clavier ou de la console Vous l'aurez remarqué, le C++ utilise beaucoup de mots tirés de l'anglais. C'est notamment le cas pour le flux sortant cout, qui doit se lire « c-out ». Ce qui est bien, c'est qu'on peut immédiatement en déduire le nom du flux entrant. Avec cout, les données sortent du programme, d'où l'élément out. Le contraire de out en anglais étant in, qui signifie « vers l'intérieur », on utilise cin pour faire entrer des informations dans le programme. cin se décompose aussi sous la forme « c-in » et se prononce « siinne». C'est important pour les soirées entre programmeurs. Ce n'est pas tout ! Associés à cout, il y avait les chevrons (<<). Dans le cas de cin, il y en a aussi, mais dans l'autre sens (>>). Exemple: #include <iostream> using namespace std; int main() { int age(30); cout << " merci de préciser votre age SVP!: " << endl; cin >> age; cout << "Vous avez " << age << " ans !" << endl; return 0; }
  • 17. 5)Probléme d’espace de nom: Pour les string, on rencontre le problème d’ espace de nom car si la chaine est longue l’ordinateur va couper la chaine . il faudrait pouvoir récupérer toute la ligne plutôt que seulement le premier mot. Il faut utiliser la fonction getline(). Il faut remplacer la ligne cin >> nom; par un getline(). Exemple: #include <iostream> #include <cstdlib> using namespace std; int main() { string nom ; cout << " merci de préciser votre nom SVP!: " << endl; getline (cin , nom); cout << "Vous vous appelez " << nom << endl; system("PAUSE"); }
  • 18. Exemple: #include <iostream> #include <string> using namespace std; int main() { cout << "Quel est votre nom ?" << endl; string nom; getline(cin, nom); cout << " quel est ton age ?" << endl; int age; cin >> age; cout << "Vous vous appelez " << nom << " votre age est: " << age << " ans " << endl; return 0; }
  • 19. 6) Les références Une référence peut être vue comme un alias d'une variable. C'est-à-dire qu'utiliser la variable, ou une référence à cette variable est équivalent. Ce qui signifie que l'on peut modifier le contenu de la variable en utilisant une référence.Une référence ne peut être initialisée qu'une seule fois : à la déclaration. Toute autre affectation modifie en fait la variable référencée.Une référence ne peut donc référencer qu'une seule variable tout au long de sa durée de vie. a)Déclaration type& identificateur=variable; ou type& identificateur(variable); NB: La variable identificateur est une référence vers la variable variable. La variable variable doit être de type type.
  • 20. Exemple Ecrire un programme qui permet de référencier deux variables a et b #include <iostream> using namespace std; int main() { int a = 60; Int b = 78; Int c; int &x = a; c = x + 5; // équivaut à : c = a + 5; int &y = b; y = a + 10; // équivaut à : b = a + 10; cout << "La variable b vaut : " << b << endl; cout << "La variable c vaut : " << c << endl; return 0; }
  • 21. 7)Les constantes C’est une variable qui ne change pas c’est-à-dire une valeur fixe. a) Déclaration d’une constate Type variable const variable; Exemple : Double const pi=3.14; Exemple: #include <iostream> using namespace std; #define const_pi int main() { double const pi=3.14; cout << « la valeur de pi est : »<< pi <<endl; return 0; }
  • 22. II) Opérateurs et expressions Les opérateurs sont des symboles permettant d'effectuer des opérations sur des valeurs. Ils sont classés dans trois catégories. a) Opérateur d’affectation L'opérateur d'affectation simple est "=" il signifie "affecter à« Exemple; Int x =5; Int y=6; x=y; Exercice 1: Écrire un programme qui permet d’affecter deux variables a et b;
  • 23. Exercice #include <iostream> using namespace std; int main() { int a (6) , b (4); cout << "La valeur de a : " << a << « et la valeur de b est: « << b<< endl; a=b; cout << « Affectation » : << endl; cout << "La valeur de a : " << a << « et la valeur de b est: « << b<< endl; return 0; }
  • 24. b)L'opérateur d'affectation additionneur "+=" Syntaxe: int x, y; x = 5; y = 3; x += y; //x = 8 c) Les opérateurs mathématiques Il existe certains opérateurs (addition,multiplication,divison,soustraction), pour utiliser certains calculs on utilise le prépocesseur cmath. Pour utiliser une fonction mathématique on met le nom de la fonction suivie à calculer Résultat = fonction (valeur); Exemple Resultat =sqrt (nombre); #include <cmath> Exemple; Écrire un programme en C++ qui donne la somme, la multiplication , la divison de deux entiers
  • 25. Exercice 1: Écrire un programme qui calcule la racine carré d’un nombre saisie resultat = sqrt(nombre) Exercice 2: Ecrire un programme qui calcule la puissance d’une valeur saisie (pow (a,b))
  • 26. Chapitre II Structure de Contrôle a)Opérateurs de comparaison il faut savoir que les conditions permettent de tester des variables. Pour effectuer ces tests, nous utilisons des symboles. Nous allons utiliser ces symboles pour effectuer des comparaisons dans nos conditions. Faites très attention : il ne faut pas confondre l’opérateur d’égalité == (il y a bien 2 symboles « = ») et l’opérateur d’affectation = (un seul symbole « = »)
  • 27. b)Opérateurs logique Pour construire des conditions plus complexes, C++ nous permet de combiner plusieurs tests au sein d'une seule et même condition dite complexe. Pour cela, il va falloir utiliser de nouveaux symboles. Il s’agit des opérateurs logiques, Ce type d'opérateur permet de vérifier si plusieurs conditions sont vraies. C) Structures de contrôle conditionnelles On appelle structures de contrôle conditionnelles les instructions qui permettent de tester si une condition est vraie ou non. Il s'agit des instructions suivantes : 1) La structure conditionnelle if 2) Le branchement conditionnel switch
  • 28. II-1) la structure conditionnelle if a) if : une première condition La structure conditionnelle if permet de réaliser un test et d’exécuter une instruction ou non selon le résultat de ce test. Sa syntaxe est la suivante : La condition est une expression dont la valeur est booléenne ou entière. Toute valeur non nulle est considérée comme vraie. Si le test est vrai, instruction est exécutée. b) if … else : ce qu'il faut faire si la condition n'est pas vérifiée, c) else if : effectuer un autre test NB : - la condition doit être entre des parenthèses - il est possible de définir plusieurs conditions à remplir avec les opérateurs ET et OU (&& et ||). Par exemple, l'instruction ci-dessous exécutera les instructions si l'une ou l'autre des deux conditions est vraie : - s'il n'y a qu'une instruction, les accolades ne sont pas nécessaires...
  • 29. Exemple: #include <iostream> using namespace std; int main() { int a; cout << "Tapez la valeur de a : "; cin >> a; if (a > 10) cout << "a est plus grand que 10" << endl; cout << "Le programme est fini" << endl; return 0; }
  • 30. Exemple: #include <iostream> using namespace std; int main() { int a; cout << "Tapez la valeur de a :" <<endl; cin >> a; if (a > 10) cout << "a est plus grand que 10" << endl; else cout << "a est inférieur ou égal à 10" << endl; system("pause") ; }
  • 31. II – 2) if … else : ce qu'il faut faire si la condition n'est pas vérifiée • L'instruction if dans sa forme basique ne permet de tester qu'une condition, or la plupart du temps on aimerait pouvoir choisir les instructions à exécuter en cas de non réalisation de la condition. L'expression if ... else permet d'exécuter une autre série d'instructions en cas de non-réalisation de la condition. Voici sa syntaxe : II-3) else if : effectuer un autre test Il est possible de faire plusieurs tests à la suite. Pour faire tous ces tests un à un dans l'ordre, on va avoir recours à la condition else if qui signifie « sinon si ». • si le nombre d’étudiant est égal à 0, afficher ce message «on n’a pas d’étudiant dans la salle" ; • - sinon, si le nombre d’étudiant est égal à 1, afficher ce message « on a un étudiant dans la salle ?"; • - sinon, si le nombre d'enfants est égal à 2, afficher ce message « on a plus d’un étudiant dans la salle"; • - sinon, afficher ce message « il y’a personne dans la salle".
  • 32. Exercices : #include <iostream> using namespace std; int main() { int Etudiants(5); if (Etudiants == 0) { cout << "on n’a pas d’étudiant dans la salle?" << endl; } else if (Etudiants > 1) { cout << "on a un étudiant dans la salle ?" << endl; } else if (Etudiants <2) { cout << "on a plus d’un étudiant dans la salle!" << endl; } else { cout << "il y’ a personne dans la salle !" << endl; } cout << "Fin du programme" << endl; return 0; }
  • 33. Exemple: #include <iostream> using namespace std; int main() { int a; cout << "Tapez la valeur de a : "; cin >> a; if (a > 10) cout << "a est plus grand que 10" << endl; cout << "Le programme est fini" << endl; return 0; }
  • 34. II-3)Le branchement conditionnel switch Dans le cas où plusieurs instructions différentes doivent être exécutées selon la valeur d’une variable de type intégral, l’écriture des if successifs peut être relativement lourde. Le C++ fournit donc la structure de contrôle switch, qui permet de réaliser un branchement conditionnel. Sa syntaxe est la suivante : switch (variable) { case valeur1 : instruction1; break; case valeur2 : instruction2; break; case valeur3 : instruction3; break; default: instructionParDéfaut; break; }
  • 35. valeur est évalué en premier. Son type doit être entier. Selon le résultat de l’évaluation, l’exécution du programme se poursuit au cas de même valeur. Si aucun des cas ne correspond et si default est présent, l’exécution se poursuit après default. Si en revanche default n’est pas présent, on sort du switch. Les instructions qui suivent le case approprié ou default sont exécutées. Puis, les instructions du cas suivant sont également exécutées (on ne sort donc pas du switch). Pour forcer la sortie du switch, on doit utiliser le mot-clé break.
  • 36. Exemple : #include <iostream> using namespace std; int main() { int Etudiants(45); switch (Etudiants) { case 8: cout << "on n’a pas d’étudiant dans la salle?" << endl; break ; case 1: cout << "on a un étudiant dans la salle " << endl; break ; case 25: cout << "on a plus d’un étudiant dans la salle!" << endl; break ; case 33: cout << "il y’ a plus d'étudiant dans la salle que prévue " << endl; break ; default : cout << "fin du programme" << endl; break; } return 0; }
  • 37. II – 3) Structures de contrôle itérative Les structures de contrôle itératives sont des structures qui permettent d'exécuter plusieurs fois la même série d'instructions jusqu'à ce qu'une condition ne soit plus réalisée. On appelle ces structures des boucles. Il existe 3 types de boucles à connaître : a) la boucle for, b) la boucle while et c la boucle do … while. a) La boucle for La structure de contrôle for est sans doute l’une des plus importantes. Elle permet de condenser : - Un compteur : une instruction (ou un bloc d’instructions) exécutée avant le premier parcours de la boucle du for. Il consiste à préciser le nom de la variable qui sert de compteur et éventuellement sa valeur de départ. - une condition : une expression dont la valeur déterminera la fin de la boucle. - une itération : une instruction qui incrémente ou décrémente le compteur. Sa syntaxe est la suivante : for (compteur; condition; itération)) { instructions ; } instruction constitue le traitement de la boucle.
  • 38. Exemple : écrire un programme C++ qui affiche les 10 nombre entiers avec la boucle for. #include <iostream> using namespace std; int main() { int compteur(0); for (compteur = 1 ; compteur < 10 ; compteur++) { cout << compteur << endl; } return 0; }
  • 39. NB : En C++, il est possible que la partie initialisation déclare une variable. Dans ce cas, la variable déclarée n’est définie qu’à l’intérieur de l’instruction for. Exemple : for (int compteur = 1 ; compteur < 10 ; compteur++) { cout << compteur << endl; } Cela signifie que l’on ne peut pas utiliser la variable compteur après l’instruction for, puisqu’elle n’est définie que dans le corps de cette instruction. Cela permet de réaliser des variables muettes qui ne servent qu’à l’instruction for dans laquelle elles sont définies II ) La boucle while Le while permet d’exécuter des instructions en boucle tant qu’une condition est vraie. Sa syntaxe est la suivante : Tout ce qui est entre accolades sera répété tant que la condition est vérifiée Exemple :
  • 40. Exemple: #include <iostream> using namespace std; int main() { int i = 1; while (i < 10) { cout << i << endl; i++; } return 0; }
  • 41. • La boucle do … while La structure de contrôle do … while permet, tout comme le while, de réaliser des boucles en attente d’une condition. Cependant, contrairement à celui-ci, le do … while effectue le test sur la condition après l’exécution des instructions. Cela signifie que les instructions sont toujours exécutées au moins une fois, que le test soit vérifié ou non. Sa syntaxe est la suivante : do { instructions ; } while (condition) ; Exemple :
  • 42. Exemple #include <iostream> using namespace std; int main() { int i = 1; do { cout << i << endl; i++; } while (i < 10); return 0; }
  • 43. Les boucles permettent de répéter les mêmes instructions plusieurs fois. On distingue trois types de boucles : for, while et do... while. La boucle for est généralement utilisée lorsqu'on sait combien de fois on souhaite répéter les instructions, tandis que while et do... while sont plutôt utilisées lorsqu'on souhaite répéter des instructions jusqu'à ce qu'une condition spécifique soit vérifiée. Le GOTO est une structure de contrôle obsolète et ne doit plus être utilisé. L'instruction break sert interrompre une boucle (for, while et do … while), ou un switch. L'instruction continue sert à "continuer" une boucle (for, while et do … while) avec la prochaine itération.
  • 44. Chapitre III) Les fonctions On appelle fonction un sous programme qui permet d’effectuer un ensemble d’instruction par simple appel de la fonction dans le corps du programme principal. I. 1. Déclaration d’une fonction Toute fonction doit être déclarée avant d’être appelée pour la première fois. La définition d’une fonction peut faire office de déclaration. Il peut se trouver des situations où une fonction doit être appelée dans une autre fonction définie avant elle. Comme cette fonction n’est pas définie au moment de l’appel, elle doit être déclarée. Le rôle des déclarations est donc de signaler l’existence des fonctions aux compilateurs afin de les utiliser, tout en reportant leur définition de ces fonctions plus loin ou dans un autre fichier. La syntaxe de la déclaration d’une fonction est la suivante : type nomDeLafonction (paramètres) ; Exemples : double Moyenne(double x, double y); char LireCaractere(); void AfficherValeurs(int nombre, double valeur); NB : la dernière fonction n’est pas destinée à renvoyer une valeur ; c’est pourquoi le type du résultat est void, une telle fonction est parfois appelée procédure (voir I. Des fonctions qui ne renvoient rien). Toute fonction doit être définie avant d’être utilisée type nomDeLafonction (paramètres) { instructions ; }
  • 45. 1) type est le type de la valeur renvoyée par la fonction 2) nomDeLafonction est le nom ou l’identificateur de la fonction, et 3) paramètres est une liste de paramètres. Ce sont les données avec lesquelles la fonction va travailler. Il peut y avoir un, plusieurs ou aucun paramètre. 4) L’instruction-bloc : il s’agit des accolades qui délimitent le contenu de la fonction. Toutes les opérations qui seront effectuées se trouvent entre les deux accolades. NB : Il est possible de créer plusieurs fonctions ayant le même nom. Il faut alors que la liste des arguments des deux fonctions soit différente. C'est ce qu'on appelle la surcharge d'une fonction. Appel de la fonction: nom_de_la _fonction (); Ou Nom_de_la_fonction(parametre1,parametre2); Exemple : int ajouteDeux(int nombreRecu) { int valeur(nombreRecu + 2); return valeur; }
  • 46. #include <iostream> using namespace std; int ajouteDeux(int nombreRecu) { int valeur(nombreRecu + 2); return valeur; } int main() { int a(2),b(2); cout << "Valeur de a : " << a << endl; cout << "Valeur de b : " << b << endl; b = ajouteDeux(b); //Appel de la fonction cout << "Valeur de a : " << a << endl; cout << "Valeur de b : " << b << endl; return 0; }
  • 47. Fonction avec plusieurs paramètres Pour passer plusieurs paramètres à une fonction, il faut les séparer par des virgules Exemple: int addition(int a, int b) { return a+b; } double multiplication(double a, double b, double c) { return a*b*c; }
  • 48. #include <iostream> using namespace std; // déclaration de la fonction somme : double somme(double a, double b); int main() { double x, y, resultat; cout << "Tapez la valeur de x : "; cin >> x; cout << "Tapez la valeur de y : "; cin >> y; //appel de notre fonction somme resultat = somme(x, y); cout << x << " + " << y << " = " << resultat << endl; return 0; } // définition de la fonction somme : prototype double somme(double a, double b) { double r; r = a + b; return r; }
  • 49. Prototype d'une fonction Le prototype va préciser le nom de la fonction, donner le type de la valeur de retour de la fonction (void quand il n'y a pas de retour), et donner les types des paramètres éventuels, ainsi que leurs éventuelles valeurs par défaut. Le prototype d'une fonction est facultatif. Si on ne met pas de prototype, on devra rédiger la fonction avant le main, Exemple // prototype de la fonction f : double f(double x,double y); Le rôle d'un prototype n'est pas de définir les instructions de la fonction, mais donner sa signature. Il est utilisé pour spécifier que la fonction existe, et est implémentée ailleurs (dans un autre fichier, une librairie, ou à la fin du fichier source).
  • 50. Dans cet exemple, le prototype est nécessaire, car la fonction est définie après la fonction main() qui l'utilise. Si le prototype est omis, le compilateur signale une erreur. Exemple : de variable avec le méme nom Dans le chapitre sur la mémoire, nous avions vu que chaque variable devait avoir un nom unique. C'est tout à fait correct, mais cette règle n'est valable qu'à l'intérieur d'une même fonction. Il est tout à fait possible d'avoir deux variables ayant le même nom pour autant qu'elles soient déclarées dans des fonctions différentes.
  • 51. #include <iostream> using namespace std; double carre(double x) { double nombre; nombre = x*x; return nombre; } int main() { double nombre, carreNombre; cout << "Entrez un nombre : "; cin >> nombre; carreNombre = carre(nombre); //On utilise la fonction cout << "Le carre de " << nombre << " est " << carreNombre << endl; return 0; }
  • 52. #include <iostream> using namespace std; void dessineRectangle(int l, int h) { for(int ligne(0); ligne < h; ligne++) { for(int colonne(0); colonne < l; colonne++) { cout << "*"; } cout << endl; } } int main() { int largeur, hauteur; cout << "Largeur du rectangle : "; cin >> largeur; cout << "Hauteur du rectangle : "; cin >> hauteur; dessineRectangle(largeur, hauteur); return 0; }
  • 53. Passage par valeur et passage par référence Il y a deux méthodes pour passer des variables en paramètres dans une fonction : le passage par valeur et le passage par référence. Ces méthodes sont décrites ci-dessous. IV. 1. Passage par valeur La valeur de l’expression passée en paramètre est copiée dans une variable locale. C’est cette variable qui est utilisée pour faire les calculs dans la fonction appelée. Pour mieux comprendre, Prenons le programme suivant qui ajoute 1 à l'argument fourni en paramètre. Passage par valeur On va vérifier comment l’ordinateur gère la mémoire Exemple : int ajouteDeux(int a) { a+=2; // passage de valeur return a; } exemple
  • 54. #include <iostream> using namespace std; int ajouteDeux(int a) { a+=2; return a; } int main() { int nombre(4), resultat; resultat = ajouteDeux(nombre); cout << "Le nombre original vaut : " << nombre << endl; cout << "Le resultat vaut : " << resultat << endl; return 0; }
  • 55. Lors de l’appel de la fonction on constate: - Le programme évalue la valeur de nombre qui est 4 - Le programme alloue un espace mémoire et y méttre la valeur 4 mais cet espace mémoire posséde l’ettiquette a qui est la variable de la fonction - le programme entre dans la fonction & il ajoute 2 à la variable a - La valeur a est ensuite copiée et affecter à la variable résultat qui est 6 NB : la variable nombre est copiée dans une nouvelle case mémoire on dit que l’argument a est passée par valeur, La variable nombre reste inchangée Passage par référence int ajouteDeux(int& a) // { a+=2; return a; }
  • 56. Exemple : passage par réference #include <iostream> using namespace std; void echange (double& a, double& b) { double temporaire(a); //On sauvegarde la valeur de 'a' a = b; //On remplace la valeur de 'a' par celle de 'b' b = temporaire; //Et on utilise la valeur sauvegardée pour mettre l'ancienne valeur de 'a' dans 'b' } int main() { double a(1.2), b(4.5); cout << "a vaut " << a << " et b vaut " << b << endl; echange(a,b); //On utilise la fonction cout << "a vaut " << a << " et b vaut " << b << endl; return 0; }
  • 57. Chapitre IV : Les Tableaux Le C++, comme presque tous les langages de programmation, propose un moyen simple de regrouper des données identiques dans un seul paquet. Et comme l'indique le titre du chapitre, on appelle ces regroupements de variables des tableaux Les tableaux statiques Il existe deux types de tableaux : les tableaux statiques, dont la taille est connue à la compilation, et les tableaux dynamiques, dont la taille est connue à l'exécution Déclarez un tableau statique Comme toujours en C++, une variable est composée d'un nom et d'un type. Comme les tableaux sont des variables, cette règle reste valable. Il faut juste ajouter une propriété supplémentaire, la taille du tableau. Autrement dit, le nombre de compartiments que notre case mémoire va pouvoir contenir. La déclaration d'un tableau est très similaire à celle d'une variable : TYPE NOM [TAILLE]; On indique le type, puis le nom choisi et enfin, entre crochets, la taille du tableau. Voyons cela avec un exemple :
  • 58. Exemple de tableau : #include <iostream> using namespace std; int main() { int Notes[5]; //Déclare un tableau de 5 int double anglesTriangle[3]; //Déclare un tableau de 3 double return 0; } Il est également possible de déclarer un tableau en utilisant comme taille une constante On indique simplement le nom de la constante entre les crochets, à la place du nombre. Exemple: int const tailleTableau(20); //La taille du tableau double angles[tailleTableau]; NB: Il faut impérativement utiliser une constante comme taille du tableau.
  • 59. • Je vous conseille de toujours utiliser des constantes pour exprimer les tailles de vos tableaux plutôt que d'indiquer directement la taille entre les crochets. C'est une bonne habitude à prendre. Comment accéder aux tableaux Chaque case d'un tableau peut être utilisée comme n'importe quelle autre variable, il n'y a aucune différence. Il faut juste y accéder d'une manière un peu spéciale. On doit indiquer le nom du tableau et le numéro de la case. Pour accéder à une case, on utilise la syntaxe nomDuTableau[numeroDeLaCase] Il y a simplement une petite subtilité : la première case possède le numéro 0 et pas 1, il faut décaler 1 en quelque sorte, note[2] = 5; Parcourez un tableau Le gros point fort des tableaux, c'est qu'on peut les parcourir en utilisant une boucle. On peut ainsi effectuer une action sur chacune des cases d'un tableau, l'une après l'autre : par exemple afficher le contenu des cases. On connaît a priori le nombre de cases du tableau on peut donc utiliser une boucle for Nous allons pouvoir utiliser la variable i de la boucle pour accéder au ième élément du tableau
  • 60. Exemple #include <iostream> using namespace std; int main() { int const nombreNotes(6); double notes[nombreNotes]; notes[0] = 12.5; notes[1] = 19.5; //Bieeeen ! notes[2] = 6.; //Pas bien ! notes[3] = 12; notes[4] = 14.5; notes[5] = 15;
  • 61. Exemple: double moyenne(0); for(int i(0); i<nombreNotes; ++i) { moyenne += notes[i]; //On additionne toutes les notes } //En arrivant ici, la variable moyenne contient la somme des notes (79.5) //Il ne reste donc qu'à diviser par le nombre de notes moyenne /= nombreNotes; cout << "Votre moyenne est : " << moyenne << endl; return 0; }
  • 62. 4.1.2. Tableaux à deux dimensions Les tableaux à deux dimensions ou matrices, sont rangés ligne par ligne et considérés comme des vecteurs de lignes. L’accès aux composantes est effectué par des doubles crochets. Déclaration: Type Nom_Tableau [dim1][dim2]; Nom_Tableau [0][0] Nom_Tableau [0][1] Nom_Tableau [0][dim2-1] Nom_Tableau [1][0] Nom_Tableau [dim1-1][0] Nom_Tableau [dim1-1][dim2-1] Exemple3: int Tab12[4][5]; float Tab34[2][10]; char Tab_Char[5][3]; //déclare un tableau de 5*3=15 caractères
  • 63. Utilisation : Un élément du tableau est repéré par ses indices. En C/C++ les tableaux commencent aux indices 0. Les indices maxima sont donc dim1-1, dim2-1. Appel : Nom_Tableau [indice1][indice2] Exemple4: Tab12 [2][4] = 25; Tab34 [0][5] = 2.79; Initialisation et réservation automatique Lors de la déclaration d'un tableau, on peut initialiser ses composantes en indiquant la liste des valeurs respectives entre accolades. Exemple5 int Tab_A[5] = {10, 20, 30, 40, 50}; float Tab_B[5] = { 10.1, 70.3, 30.5, 20.0, 50.4 }; int C_Tab[10] = {1, 1, 0, 1, 1, 1, 0, 1, 0, 1}; int D_Tab[] = {1, 5, 3, 21}; float E_Tab[2] = {1.1, 5.0, 1.2, 1.9}; // erreur int Deux_Dim[2][3] = {{1,5,7},{8,4,3}}; //2 lignes et 3 colonnes
  • 64. Ecrire un programme qui demande à l'utilisateur de saisir 10 entiers stockés dans un tableau. Le programme doit ensuite afficher l'indice du plus grand élément.
  • 65. Ecrire un programme qui affiche les éléments du tableau à deux dimensions suivant : int A[3][5] = {{ 0, 1, 2, 3, 4}, {10,11,12,13,14}, { 20,21,22,23,24} }; Exemple : #include <iostream> using namespace std; void main() { int A[3][5] = { { 0, 1, 2, 3, 4}, {10,11,12,13,14},{ 20,21,22,23,24} }; for(int i=0;i<3;i++){ for(int j=0;j<5;j++){ cout << "A[" << i+1 <<"][" << j+1 << "]= " << A[i][j] << "; "; } cout << endl ; } }
  • 66. Les chaînes de caractères 4.2.1. Déclaration de chaînes de caractères En C++ une chaîne de caractères peut être traitée et manipulée à travers un tableau de caractères à une dimension (vecteur de caractères), avec des déclarations dont la syntaxe est de type : char Ident[dim]; //Ident : Nom de la chaîne de caractères Mais il existe aussi un type spécial string (le mot anglais pour une chaîne de caractères), dont la syntaxe est de type : string Ident; 4.2.2. Initialisation de chaînes de caractères a) char Ident[dim]; char s[10] = "bonjour !";
  • 67. NB : Le caractère nul '0' (null terminator), de code ASCII 0, est un caractère de contrôle qu’il ne faut pas confondre avec le caractère affichable '0', lequel est codé par le nombre ASCII 48. Il doit être placé obligatoirement en fin de chaîne. Sans lui, la chaîne n'a pas de fin. Une lecture de la chaîne pourrait donc continuer jusqu'au prochain caractère nul en mémoire, et donc bien après la dimension maximale. Dans l’exemple, '0' est ajouté automatiquement par le compilateur, car le nombre de caractères dans "bonjour !" est inférieur à la dimension du tableau s. Exemple 2 : char S[] = {'H','e','l','l','o','0’};
  • 68. Exemple : le programme affiche Hello #include <iostream> using namespace std; int main() { char S[8]= "Hello"; for(int i=0; i<8; i++){ cout << S[i] << endl; } } NB : string Ident; // Il faut inclure <string> Cette construction est équivalente à string Ident = ""; ce qui revient à dire que par défaut une chaîne est créée vide. Il existe toutefois de nombreuses autres façons d’initialiser un string string s1 = "Bonjour a vous"; string s2 = s1; // s2 contient " Bonjour a vous " string s3(4, 'x'); // équivaut à string s3 = "xxxx" string s4(s1, 4, 8); // s4 contient "our a vo"
  • 69. Exemple 6: #include <string > string ST = "Salut"; for (int i=0;i<5;i++) { cout << ST[i] << " "; // affichera : S a l u t } Exemple 7 : #include <iostream > #include <string > using namespace std; int main() { string Phrase; cout << "donner une phrase" << endl ; while ( cin >> Phrase ) cout << "Dans Phrase il y a: " << Phrase << 'n'; cout << "ok: Plus rien : bye!n"; return 0; }
  • 70. Pointeurs C++permet, comme C, un contrôle fin de la mémoire. En effet, il permet, grâce aux pointeurs, d’accéder directement à des zones de la mémoire,en travaillant sur les adresses . 1) Déclaration de pointeurs Les pointeurs se déclarent, comme les variables, en donnant le type de l'objet vers lequel ils devront pointer. Cependant, pour différencier une variable quelconque d’une variable « pointeur », le type de base (char, float, int, …) est toujours suivi d’une étoile ‘ * ’. Cela se fait par l'instruction: type* nom_du_pointeur; Exemple 2 : on peut déclarer les pointeurs suivants : int *p, *q, r ; // 2 pointeurs p et q vers des entiers et 1 entier r char *s; // 1 pointeur s vers un caractère float *pr; // 1 pointeur pr pointant sur un float int **tab; // 1 pointeur tab pointant sur un pointeur qui pointe sur un int L'opérateur * désigne en fait le contenu de l'adresse, c’est l’opérateur de déréférencement.
  • 71. 2. Valeurs pointées et adresses La manipulation des pointeurs nécessite une bonne maîtrise des deux opérateurs & et *. Lors de l’utilisation des pointeurs, nous avons besoin : - d'un opérateur 'adresse de': & pour obtenir l'adresse d'une variable, - d'un opérateur 'contenu de': * pour accéder au contenu d'une adresse, - d'une syntaxe de déclaration pour pouvoir déclarer un pointeur. l’exemple : int i = 35; int *p; // déclaration : p est un pointeur pointant sur un entier p = &i; /* initialisation du pointeur p, affecte l'adresse de la variable i. p pointe maintenant vers la zone mémoire où est stockée la variable i*/ cout << *p; //affiche la valeur pointée par p, donc 35 p contient l’adresse de la variable i (p = &i ) alors que *p contient le contenu de la variable, donc 35. On peut donc accéder à la valeur de la variable en passant par son adresse et en utilisant l’opérateur ‘’contenu de * ‘’.
  • 72. EXEMPLE #include <iostream> using namespace std; int main () { int *ptr ; int i= 42; ptr = &i; cout << "ptr: "<< ptr << endl; cout << "* ptr : "<< * ptr<<endl; return 0; }
  • 73. Passage de paramètres par pointeurs En C, les pointeurs sont fort utiles lors du passage de paramètres modifiables dans des fonctions. Ceci a pour conséquence de produire un code peu lisible et constitue une source fréquente d'erreurs, surtout pour les personnes peu habituées à cette gymnastique. Le langage C++ pallie à cette lacune en introduisant le passage de paramètres par références. Exemple : #include <iostream> using namespace std; void minmax(int i, int j, int* min, int* max) { if(i<j) { *min=i; *max=j; } Else { *min=j; *max=i;
  • 74. } } int main() { int a, b, w, x; cout << "Tapez la valeur de a : "; cin >> a; cout << "Tapez la valeur de b : "; cin >> b; minmax(a, b, &w, &x); cout << "Le plus petit vaut : " << w << endl; cout << "Le plus grand vaut : " << x << endl; return 0; }
  • 75. Exemple : Pointeur avec références #include <iostream> using namespace std; void affiche(int i, float r, char c){ cout<< "n int = " << i << " float = " << r << " char = " << c ; } void Saisie(int &i, float r, char &cc){ cout << "n Donner un entier : "; cin >> i; // 12 cout << " Donner un reel : "; cin >> r; // 12.13 cout << " Donner un caractere : "; cin >> cc; // Z } void main(){ int N=5; float f=6.7; char C = 'A'; affiche(N, f, C); Saisie(N, f, C); affiche(N, f, C); }
  • 76. Exemple Tableaux en utilisant un pointeur #include <iostream> using namespace std; int main(){ int T[6] = { 2, 6, 4, 5, 10, 8 }; int *p; p = T; // p repère le premier élément de T cout<< *p << endl ; p++; cout<< *p << endl ; p += 4; cout<< *p << endl ; }
  • 77. • Pointeurs et tableaux Un programme en C++ est capable de demander au système d'exploitation de la mémoire pour y stocker des données et de libérer ces zones mémoire au cours de l'exécution du programme : on appelle cela l'allocation dynamique de mémoire. Le programmeur est tenu de "rendre" au système d'exploitation, les zones mémoire qu'il aura réclamé dynamiquement, au plus tard lors de la fermeture du programme. Il existe deux méthodes pour effectuer de l'allocation dynamique de mémoire : L'ancienne méthode qui utilise les fonctions malloc et free. Une méthode plus récente qui utilise les mots-clés new et delete. • malloc et free Il s'agit de 2 appels système standards : La fonction (void *) malloc(int t) demande au système de fournir une zone mémoire de t octets et renvoie par un return un pointeur vers cette zone (ou le pointeur NULL s'il n'y a pas assez de mémoire). cette fonction renvoie un élément de type void *, c'est-à-dire un pointeur vers n'importe quelle type. En général, on effectue un cast pour transformer ce pointeur vers un pointeur vers un autre type, un pointeur vers un int par exemple. La fonction void free(void *p) libère la zone mémoire pointée p.
  • 78. • Tableaux de taille variable Grâce à malloc et free, on peut gérer des tableaux dont la taille est variable : un tableau peut s'allonger ou se réduire en fonction des besoins du programmeur. On appelle cela de l'allocation dynamique de mémoire. Ne pas oublier de libérer la mémoire. Pour demander au système d'exploitation une zone de la bonne taille, il peut être utile de connaître la taille occupée par un int, un char, ou n'importe quelle type structuré par exemple. Pour cela, on peut utiliser le mot-clé sizeof(type) qui a en paramètre un type quelconque et qui renvoie la taille en octets occupée par une variable de ce type. Exemple : #include<iostream> #include<cstdlib> using namespace std; int main() { int *t; int i; t = (int *) malloc( 5 * sizeof(int) ); if (t==NULL) cout << "pas assez de mémoire" << endl; else { for(i=0 ; i<5 ; i++) t[i] = i * i;
  • 79. for(i=0 ; i<5 ; i++) cout << t[i] << " "; cout << endl; free(t); } t = (int *) malloc( 10 * sizeof(int) ); if (t==NULL) cout << "pas assez de mémoire" << endl; else { for(i=0;i<10;i++) t[i] = i * i; for(i=0 ; i<10 ; i++) cout << t[i] << " "; cout << endl; free(t); } return 0; }
  • 80. new et delete new et delete sont 2 mots-clés permettant de faire de l'allocation dynamique de mémoire de manière plus performante que malloc et free. on préférera utiliser new et delete que malloc et free. Utilisation de new Syntaxe : new type[taille]; new renvoie un tableau dont la taille est taille éléments, chaque élément étant de type type. S'il n'y a pas assez de mémoire, new renvoie NULL. new renvoie un élément dont le type est type *. Utilisation de delete Syntaxe : delete []t; Si t est un tableau qui a été créé en utilisant la méthode précédente, l'utilisation de delete détruit ce tableau. Le
  • 81. #include <iostream> using namespace std; int main() { int *t; int i; t = new int[5]; if (t == NULL ) cout << "pas assez de mémoire" << endl; else { for ( i=0 ; i<5 ; i++ ) t[i] = i * i; for ( i=0 ; i<5 ; i++ ) cout << t[i] << " "; cout << endl; delete [] t;
  • 82. t = new int[10]; if (t == NULL) cout << "pas assez de mémoire" << endl; else { for ( i=0 ; i<10 ; i++ ) t[i] = i * i; for ( i=0 ; i<10 ; i++ ) cout << t[i] << " "; cout << endl; delete [] t; } } return 0; }
  • 83. Les Fichiers Un fichier est un ensemble structuré d'informations stockées sur un support externe (disque dur, disquette, CD-ROM, DVD, …). Ecrire ou lire sur une mémoire de masse des données non volatiles, qui restent utilisables après l'exécution d'un programme, est évidemment fondamental. Nous allons voir dans ce chapitre, comment nous pouvons manipuler des fichiers : les déclarer, les créer, les ouvrir, lire ou écrire voire modifier des données s’y trouvant et les fermer. Un fichier est une suite d'octets. Les informations contenues dans le fichier ne sont pas forcément de même type (un char, un int, une structure ...) 1 ) Accès aux fichiers Pour pouvoir manipuler un fichier de données en C++, il faut tout d'abord inclure dans le fichier .cpp la librairie fstream qui fournit les fonctionnalités de manipulation de fichiers. #include <fstream> On y trouve essentiellement : la classe ofstream (output file stream) qui permet d’écrire les données dans le fichier ; la classe ifstream (input file stream) qui permet de lire les données du fichier ;
  • 84. 2) Ouvrir un fichier La première chose à faire, quand on manipule un fichier, est de l'ouvrir. Pour ce faire, on déclare une variable en lui associant le nom physique du fichier visé. Cette variable est de type ofstream s’il s’agit d’écriture, de type ifstream s’il s’agit de lecture ou de type fstream s’il s’agit de lecture/écriture. La méthode la plus simple pour ouvrir un fichier est d’initialiser la variable qui doit lui être associée à l’aide d’une chaîne de caractères décrivant le chemin d’accès au fichier. ifstream input("Data.txt"); ofstream output("Res.txt"); "Data.txt" et "Res.txt" sont des chaînes de caractères donnant les noms réels des fichiers physiques. Cependant, si les fichiers ne sont pas dans le même répertoire que le programme, il faut indiquer le chemin d'accès. Le caractère '' s'écrit en C++ '', ce qui pourrait donc donner par Exemple : ifstream input("c:testData.txt"); ofstream output("c:testRes.txt"); Cette façon d’ouvrir les fichiers présente plusieurs caractéristiques notables : Si le chemin d’accès comporte un répertoire qui n’existe pas, l’ouverture échoue. Si le chemin est correct, mais que le fichier n’existe pas, il est créé. Si le fichier existe, il est ouvert. S’il s’agit d’ouverture en mode écriture, le contenu antérieur du fichier est perdu.
  • 85. • La fonction open() Si l’initialisation d’une variable est une opération particulièrement simple, son inconvénient et qu’elle ne peut avoir lieu qu’une seule fois. Il arrive pourtant qu’une même variable intervienne dans plusieurs ouvertures (ou tentatives d’ouvertures…) successives. Les classes ofstream et ifstream proposent, pour répondre à ce besoin, une fonction membre nommée open() qui peut accepter comme paramètre un chemin d’accès, comme le montre l’exemple
  • 86. L’ouverture du fichier est une opération dont le succès ne peut être garanti. Il faut donc tester si l’ouverture a réussi avant d’effectuer des opérations sur les données du fichier. On détecte l’échec d’une ouverture de fichier en testant la valeur de la variable que l’on vient de tenter d’associer au fichier. Ceci est illustré dans les deux exemples suivants:
  • 87. !output : indique si l’opération sur le fichier a réussi. 7.2.2. Fermeture d’un fichier Après l’ouverture d’un fichier et les différents traitements qui s’y rapportent, lorsque vous avez donc fini d’utiliser ce fichier, vos programmes doivent fermer ce flux en utilisant la fonction membre close() comme suit : • output.close() ; • input.close() ; On peut dire qu'entre les événements open() et close() le fichier est ouvert. Il est important de fermer les fichiers après les avoir utilisés, car seulement un nombre limité de fichiers peuvent être ouverts simultanément par un programme. De plus, le traitement désiré (lecture ou écriture) peut être différé à la fermeture du fichier. Sans fermeture de fichier, il n'est, par exemple, pas certain que les toutes données que l'on voulait écrire aient été réellement transférées vers le support externe. • Lecture et écriture Il y a lieu maintenant de lire ou d’écrire des informations dans les fichiers. Pour être précis, il importe de signaler que les données lues ou écrites le sont d'abord dans un tampon (buffer) de la mémoire, avant d'atteindre leur destination souhaitée. Ce tampon de fichier est une zone de mémoire RAM dans laquelle on range temporairement, avant leur transfert à destination, une certaine quantité de données lues ou écrites dans un fichier. L’avantage est qu’ainsi on n’a pas besoin de déclencher une opération d’entrée-sortie spécifique pour chaque donnée lue ou écrite.
  • 88. • ios :: app - Ouvre un fichier texte à ajouter, ce qui signifie que nous pouvons ajouter le texte à la fin. • ios :: in - Ouvre un fichier texte en lecture. • ios :: out - Ouvre un fichier texte pour l'écriture. • ios :: trunc - Il tronque le contenu avant d'ouvrir un fichier, si ce fichier existe. • ios :: ate - Ouvre un fichier pour la sortie et déplace le contrôle en lecture / écriture à la fin du fichier. Lecture et écriture Il y a lieu maintenant de lire ou d’écrire des informations dans les fichiers. Pour être précis, il importe de signaler que les données lues ou écrites le sont d'abord dans un tampon (buffer) de la mémoire, avant d'atteindre leur destination souhaitée. Ce tampon de fichier est une zone de mémoire RAM dans laquelle on range temporairement, avant leur transfert à destination, une certaine quantité de données lues ou écrites dans un fichier. L’avantage est qu’ainsi on n’a pas besoin de déclencher une opération d’entrée-sortie spécifique pour chaque donnée lue ou écrite. La gestion du tampon est à la charge du système qui intervient lorsque le tampon est plein ou lorsqu'on lui impose de vider le tampon, notamment avec la fonction membre close() L'ouverture ne donnant qu'un moyen d'accès, la lecture et/ou l’écriture dans des fichiers se fait respectivement en utilisant les opérateurs >> et/ou << . Mieux qu’un long discours, nous donnons dans la suite des exemples que nous commentons au fur et a mesure.
  • 89. #include <fstream> // Fichier d'entete pour la gestion des fichiers using namespace std; int main() { // Création d'un objet ofstream -> pour ecrire ofstream fichier; fichier.open("E:codefichier.txt", ios::out); // Si erreur d'ouverture if(fichier.bad()) return 0; // on quitte fichier << "Ce texte est ecrit dans le fichier" << endl; // Fermeture du fichier fichier.close(); return 0; }
  • 90. #include <fstream> #include <iostream> // pour accès à la classe ofstream using namespace std; int main() { ofstream ouput; // on déclare une instance de la classe ofstream ouput.open("E:codefichier.txt"); // on ouvre le fichier fichier.txt if(output) { // if (output != NULL) on vérifie si l'ouverture se passe bien // ou if ( ! output.fail() ) pas d’erreur cout<<"Pas d Erreur"<<endl; char caract = 'A'; output << caract <<endl; int Entier = 10; output << Entier <<endl; float Reel = 3.14; output << Reel <<endl; double monDouble = 7.12345; output << monDouble <<endl; ouput.close(); // on ferme le fichier } else{ // si échec à l'ouverture cout<<"Erreur"<<endl; } }
  • 91. #include <fstream> // pour accès à la classe ifstream using namespace std; void main() { ifstream input; // on déclare une instance de la classe ifstream input.open("fichier.txt"); // on ouvre le fichier fichier.txt if(input) { // on vérifie si l'ouverture se passe bien cout<<"Pas d Erreur"<<endl; char caract; input >> caract ; int Entier ; input >> Entier; float Reel ; input >> Reel ; double monDouble ; input >> monDouble ; input.close(); // on ferme le fichier cout << "Car = " << caract << " Entier = " << Entier << " Reel = " << Reel <<" Double = " << monDouble << endl; }else{ // si échec à l'ouverture cout<<"Erreur"<<endl; }
  • 93. Rappel Un programme qui utilise des fichiers de données doit inclure fstream Pour écrire dans un fichier, on déclare une variable de type ofstream ofstream ouput; ouput.open("fichier.txt"); // on ouvre le fichier fichier.txt if(ouput) { // on teste si l'ouverture s’est bien passée On utilise l’opérateur d’insertion << pour envoyer dans le fichier les données. Pour lire un fichier, on déclare une variable de type ifstraem ifstream input; input.open("fichier.txt"); // on ouvre le fichier fichier.txt if(input) { // on teste si l'ouverture s’est bien passée On utilise l’opérateur d’extraction >> pour envoyer dans des variables les informations extraites du fichier. Pour extraire toute la ligne ou un ensemble de caractères on utilisera le fonction getline(). Utiliser la fonction close() pour fermer le fichier. input.close() ;
  • 94. Les Structures • En C ++, la structure est une combinaison ou un groupe de différents éléments de données regroupés sous un même nom. Les éléments de données sont appelés membres de données et ont un type et une longueur de données différents. C'est un type de données défini par l'utilisateur qui vous permet de combiner des éléments de données de différents types. Les structures sont utilisées pour définir les enregistrements, par exemple nous voulons afficher les enregistrements des employés ou les enregistrements des étudiants. 1) Syntaxe de la structure Pour définir la structure, vous devez utiliser l'instruction struct. L'instruction struct définit différents types de données pour différents membres de données.
  • 95. Exemple de la syntaxe avec la table employée struct Employee{ char Name[10]; char Designation[10]; int Code; int Salary; }; Dans l'exemple ci-dessus, nous avons défini les membres de données avec la taille indiquée dans array COMMENT ACCÉDER AUX DONNÉES MEMBRES DE LA STRUCTURE? Vous pouvez accéder à n’importe quel membre de données d’une structure à l’aide de l’opérateur d’accès aux membres (.). L'opérateur d'accès au membre est valide entre le nom de la structure et le membre de la structure auquel il faut accéder. Et pour définir les variables, vous utiliserez le mot-clé struct.
  • 96. #include <iostream> #include <cstring> using namespace std; struct Employee { string Name[10]; string Designation[50]; int Code; int Salary; }; int main() { struct Employee Emp1, Emp2;
  • 97. cout << "Employee 1 Name : " << Emp1.Name <<endl; cout << "Employee 1 Designation : " << Emp1.Designation <<endl; cout << "Employee 1 Code : " << Emp1.Code <<endl; cout << "Employee 1 Salary : " << Emp1.Salary <<endl; cout << " Employee 2 Name: " << Emp2.Name <<endl; cout << " Employee 2 Designation: " << Emp2.Designation <<endl; cout << " Employee 2 Code: " << Emp2.Code <<endl; cout << " Employee 2 Salary: " << Emp2.Salary <<endl; return 0; }
  • 98. AVANTAGES DES STRUCTURES Les avantages des structures en C ++ sont les suivants: Les membres de données de structure sont publics par défaut. Il est rétrocompatible avec le code C. QUE SONT LES STRUCTURES IMBRIQUÉES? Les structures imbriquées sont celles où vous déclarez une structure dans une structure. Une structure comprend une autre structure comme son membre. PAR EXEMPLE, vous avez deux structures Sujets et Étudiant. Pour que les sujets soient imbriqués dans Student, vous devez déclarer la structure Subjects avant et hors de la structure Student et créer un objet de structure Subjects dans la structure Student.
  • 99. #include <iostream> using namespace std; struct Person { char name[50]; int age; float salary; }; int main() { Person p1; cout << "Enter Full name: "; cin.get(p1.name, 50); cout << "Enter age: "; cin >> p1.age; cout << "Enter salary: "; cin >> p1.salary; cout << "n Information." << endl; cout << "Name: " << p1.name << endl; cout <<"Age: " << p1.age << endl; cout << "Salary: " << p1.salary; return 0; }
  • 100. #include <iostream> using namespace std; struct Subjects{ char Name[25]="C++"; char Author[25]="XYZ"; int Code=9000; }; struct Student{ int Id= 25; char Name[25]="ABC"; struct Subjects Sub; }; int main(void) { int i; Student S; cout << "nDetails of Student"; cout << "ntStudent Id : " << S.Id; cout << "ntStudent Name : " << S.Name; cout << "ntStudent Subject Name : " << S.Sub.Name; cout << "ntStudent Subject Author : " << S.Sub.Author; cout << "ntStudent Subject Code : " << S.Sub.Code; return 0 ; }
  • 101. TABLEAU DE STRUCTURES • Comme on l'a vu plus haut, cette structure est une collection de types de données différents et un objet de structure représente un seul enregistrement en mémoire. • Donc, si vous voulez ajouter plus d’enregistrements de type structure, vous devez créer un tableau de structure ou d’objet. Comme vous le savez, le tableau est une collection de type de données similaire. Par conséquent, le tableau peut être de type structure.
  • 102. #include <iostream> using namespace std; struct Student { int Id; char Name[25]; int Age; }; void main() { int i; Student S[ 5 ]; for(i=0;i<5;i++) { cout << "nEnter details of " << i+1 << " Student"; cout << "ntEnter Student Id : "; cin >> S[i].Id; cout << "ntEnter Student Name : "; cin >> S[i].Name;
  • 103. cout << "ntEnter Student Age : "; cin >> S[i].Age; } cout << "nPrint details of Student"; for(i=0;i<5;i++) cout << "n"<< S[i].Id <<"t"<<S[i].Name <<"t" << S[i].Age; } III ) POINTEURS VERS DES STRUCTURES Comme nous avons des pointeurs sur les types de données int, char, float et autres, de la même manière que vous avez les pointeurs pointant sur des structures. Et ces pointeurs sont connus comme des pointeurs de structure.
  • 104. #include <iostream> #include <cstring> using namespace std; void printdetails(struct Employee *emp ); struct Employee { char Name[10]; char Designation[50]; int Code; int Salary; }; int main() { struct Employee Emp1; struct Employee Emp2; strcpy( Emp1.Name, "ABC"); strcpy( Emp1.Designation, "Manager"); Emp1.Code = 6495; Emp1.Salary = 40000;
  • 105. strcpy(Emp2.Name, "CDE"); strcpy(Emp2.Designation, "Analyst"); Emp2.Code = 6467; Emp2.Salary = 20000; printdetails(&Emp1); printdetails(&Emp2); return 0; } } void printdetails(struct Employee *emp) { cout<< “Employee Name:” <<emp->Name <<endl; cout<< “Employee Designation:”<<emp->Designation <<endl; cout<< “Employee Code:”<<emp->Code <<endl; cout<< “Employee Salary:”<<emp->Salary <<endl; }
  • 106. #include <iostream> #include <string> using namespace std; /* utilisation de l’espace de nommage std pour importer les symboles de la bibliothèque standard C++ */ struct Client { string nom; string adresse; char Code; }; Client quel_client(int i, Client DataBase[]) { if ((i > 0) && (i < 4 )) return(DataBase[i]); else return(DataBase[0]); } int main(void) { int N;
  • 107. Client DataBase[4] = { {« ADAMA", « Génie logiciel 00", 'B'}, {« Bintou", « Femme forte 123", 'D'}, {« KINE", « Sine Saloum 15", 'G'}, {« Mohamed", « Mecque 2341", 'M'} }; cout << "Pour chercher un Client, donner un numero entre 1 et 4 : "; cin >> N; cout << "Debut de recherche du Client " << N << endl; Client ce_client = quel_client(N-1, DataBase); cout << "n NOM : " << ce_client.nom << "n Adresse : " << ce_client.adresse << "n Code : " << ce_client.Code << endl; }
  • 108. Partie II : Programmation Orientée Objet Avec ce chapitre, nous abordons véritablement les possibilités de P.O.O. de C++. Comme nous l’avons dit dans le premier chapitre, celles-ci reposent entièrement sur le concept de classe. Une classe est la généralisation de la notion de type défini par l’utilisateur, dans lequel se trouvent associées à la fois des données (membres données) et des méthodes (fonctions membres). En P.O.O. « pure », les données sont encapsulées et leur accès ne peut se faire que par le biais des méthodes. En C++, en revanche, vous pourrez n’encapsuler qu’une partie des données d’une classe (même si cette démarche reste généralement déconseillée). Vous pourrez même ajouter des méthodes au type structure (mot clé struct) que nous avons déjà rencontré ; dans ce cas, il n’existera aucune possibilité d’encapsulation. Ce type sera rarement employé sous cette forme généralisée mais comme, sur un plan conceptuel, il correspond à un cas particulier de la classe, nous l’étudierons tout d’abord, ce qui nous permettra dans un premier temps de nous limiter à la façon de mettre en oeuvre l’association des données et des méthodes. Nous ne verrons qu’ensuite comment s’exprime l’encapsulation au sein d’une classe (mot clé class). Comme une classe (ou une structure) n’est qu’un simple type défini par l’utilisateur, les objets possèdent les mêmes caractéristiques que les variables ordinaires, en particulier en ce qui concerne leurs différentes classes d’allocation (statique, automatique, dynamique). Cependant, pour rester simple et nous consacrer au concept de classe, nous ne considérerons dans ce chapitre que des objets automatiques (déclarés au sein d’une fonction quelconque).
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115. 1 Les structures généralisées Considérons une déclaration classique de structure telle que : struct point { int x ; int y ; } C++ nous permet de lui associer des méthodes (fonctions membres). Supposons, par exemple, que nous souhaitions introduire trois fonctions : initialise pour attribuer des valeurs aux « coordonnées » d’un point ; deplace pour modifier les coordonnées d’un point ; Affiche pour afficher un point : ici, nous nous contenterons, par souci de simplicité, d’afficher les coordonnées du point. Voyons comment y parvenir, en distinguant la déclaration de ces fonctions membres de leur définition.
  • 116. 1.1 Déclaration des fonctions membres d’une structure Voici comment nous pourrions déclarer notre structure point : struct point{ /* déclaration "classique" des données */ int x ; int y ; /* déclaration des fonctions membre (méthodes) */ void initialise (int, int) ; void deplace (int, int) ; void affiche () ; } ;
  • 117. Déclaration d’une structure comportant des méthodes Outre la déclaration classique des champs de données apparaissent les déclarations (en-têtes) de nos trois fonctions. Notez bien que la définition de ces fonctions ne figure pas à ce niveau de simple déclaration : elle sera réalisée par ailleurs, comme nous le verrons un peu plus loin. Ici, nous avons prévu que la fonction membre initialise recevra en arguments deux valeurs de type int. À ce niveau, rien n’indique l’usage qui sera fait de ces deux valeurs. Ici, bien entendu, nous avons écrit l’en-tête de initialise en ayant à l’esprit l’idée qu’elle affecterait aux membres x et y les valeurs reçues en arguments. Les mêmes remarques s’appliquent aux deux autres fonctions membres. Vous vous attendiez peut-être à trouver, pour chaque fonction membre, un argument supplémentaire précisant la structure de type point sur laquelle elle doit opérer. Nous verrons comment cette information sera automatiquement fournie à la fonction membre lors de son appel
  • 118. 1.2 Définition des fonctions membres d’une structure Elle se fait par une définition (presque) classique de fonction. Voici ce que pourrait être la définition de initialise : void point::initialise (int abs, int ord) { x = abs ; y = ord ; } Dans l’en-tête, le nom de la fonction est : point::initialise Le symbole :: correspond à ce que l’on nomme l’opérateur de « résolution de portée », lequel sert à modifier la portée d’un identificateur. Ici, il signifie que l’identificateur initialise concerné est celui défini dans point. En l’absence de ce « préfixe » (point::), nous définirions effectivement une fonction nommée initialise, mais celle-ci ne serait plus associée à point ; il s’agirait d’une fonction « ordinaire » nommée initialise, et non plus de la fonction membre initialise de la structure point. Si nous examinons maintenant le corps de la fonction initialise, nous trouvons une affectation :
  • 119. x = abs ; Le symbole abs désigne, classiquement, la valeur reçue en premier argument. Mais x, quant à lui, n’est ni un argument ni une variable locale. En fait, x désigne le membre x correspondant au type point (cette association étant réalisée par le point:: de l’en- tête). Quelle sera précisément la structure de type point concernée ? Là encore, nous verrons comment cette information sera transmise automatiquement à la fonction initialise lors de son appel. Nous n’insistons pas sur la définition des deux autres fonctions membres ; vous trouverez ci-dessous -l’ensemble des définitions des trois fonctions.
  • 120. /* ----- Définition des fonctions membres du type point ---- */ #include <iostream> using namespace std ; void point::initialise (int abs, int ord) { x = abs ; y = ord ; } void point::deplace (int dx, int dy) { x += dx ; y += dy ; } void point::affiche () { cout << "Je suis en " << x << " " << y << "n" ; }
  • 121. Exemple #include <iostream> using namespace std ; /* ------------ Déclaration du type point ------------- */ struct point { /* déclaration "classique" des données */ int x ; int y ; /* déclaration des fonctions membres (méthodes) */ void initialise (int, int) ; void deplace (int, int) ; void affiche () ; } ; /* ----- Définition des fonctions membres du type point ---- */ void point::initialise (int abs, int ord) { x = abs ; y = ord ; } void point::deplace (int dx, int dy) { x += dx ; y += dy ; } void point::affiche () { cout << "Je suis en " << x << " " << y << "n" ; }
  • 122. main() { point a, b ; a.initialise (7, 2) ; a.affiche () ; a.deplace (5, 4) ; a.affiche () ; b.initialise (1,-1) ; b.affiche () ; }
  • 123. Remarques 1) La syntaxe même de l’appel d’une fonction membre fait que celle-ci reçoit obligatoirement un argument implicite du type de la structure correspondante. Une fonction membre ne peut pas être appelée comme une fonction ordinaire. Par exemple, cette instruction : initialise (3,1) ; sera rejetée à la compilation (à moins qu’il n’existe, par ailleurs, une fonction ordinaire nommée initialise). 2) Dans la déclaration d’une structure, il est permis (mais généralement peu conseillé) d’introduire les données et les fonctions dans un ordre quelconque (nous avons systématiquement placé les données avant les fonctions). Dans notre exemple de programme complet, nous avons introduit : – la déclaration du type point ; – la définition des fonctions membres ; – la fonction (main) utilisant le type point. Mais, bien entendu, il serait possible de compiler séparément le type point ; c’est d’ailleurs ainsi que l’on pourra « réutiliser » un composant logiciel
  • 124. Chapitre I : Classe et objet 1 Notion de classe Comme nous l’avons déjà dit, en C++ la structure est un cas particulier de la classe. Plus précisément, une classe sera une structure dans laquelle seulement certains membres et/ou fonctions membres seront « publics », c’est-à-dire accessibles « de l’extérieur », les autres membres étant dits « privés La déclaration d’une classe est voisine de celle d’une structure. En effet, il suffit de remplacer le mot clé struct par le mot clé class ; de préciser quels sont les membres publics (fonctions ou données) et les membres privés en utilisant les mots clés public et private. Par exemple, faisons de notre précédente structure point une classe dans laquelle tous les membres données sont privés, et toutes les fonctions membres sont publiques. :
  • 125. • En C++, la notion de classe est une extension de la notion de type défini par l'utilisateur dans laquelle se trouvent associées des variables et des fonctions. • Les variables et les fonctions d'une classe sont dites les membres de cette classe. On dit aussi : ♦ Membres données ou propriétés pour les variables ♦ Fonctions membres ou méthodes pour les fonctions • La POO pure exige l'encapsulation des données, c'est-à-dire que les membres données ne peuvent être manipulés qu'à travers les fonctions membres. En C++, on peut n'encapsuler qu'une partie des membres données. • C++ traite les structures et les unions comme des classes. Ainsi C++ permet d'associer des fonctions membres à des structures et des unions, mais dans ce cas aucune encapsulation n'est possible (tous les membres sont publiques). D'autre part, dans les unions on ne peut définir qu'une seule fonction membre 1 Définition d'une classe La déclaration d'une classe consiste à décrire ses membres (membres données et prototypes de ses fonctions membres) groupés en sections. Chaque section est étiquetée par l'un des mots clés : private, public, ou protected, qui précisent le mode d'accès aux membres contenus dans la section. ♦ private : accès autorisé seulement dans fonction membres ♦ public : accès libre
  • 126. protected : accès autorisé seulement dans les fonctions membres de la classe et de ses dérivées (voir héritage) • Pour déclarer une classe, on utilise le mot clé class. • Considérons, par exemple, la classe point qui comporte deux membres données privés 𝑥 et 𝑦 de type 𝑖nt et trois fonctions membres publiques 𝑖nitialise, déplace et 𝑎ffiche.
  • 127.
  • 128. • Utilisation d'une classe Un objet (ou instance) object_𝑛ame d'une classe nommée 𝑐lasse_name est déclaré comme une variable de type 𝑐lasse_name:
  • 129. /* ------------ Déclaration de la classe point ------------- */ class point{ /* déclaration des membres privés */ private : /* facultatif () */ • int x ; • int y ; /* déclaration des membres publics */ public : void initialise (int, int) ; void deplace (int, int) ; void affiche () ; } ;
  • 130. // Définition des fonctions membres de la classe point void point::initialise (int abs, int ord) { x=abs; y=ord; } void point::deplace(int dx, int dy){ x=x+dx; y=y+dy; } void point::affiche() { cout << "(" << x << "," << y << ")" << endl; }
  • 131. /* -------- Utilisation de la classe point -------- */ int main() { point a,b; a.initialise(5,2); cout << "a = "; a.affiche(); a.deplace(-2,4); cout << "Apres deplacement a = "; a.affiche(); b.initialise(1,-1); cout << "b = "; b.affiche(); return 0; }
  • 132. Le mot clé ‘public’ précise que tout ce qui le suit (données membres ou fonctions membres) sera public, le reste étant privé. Ainsi : - x et y sont deux membre privés. - ‘initialise’, ‘deplace’ et ‘affiche’ sont trois fonctions membres publics. - La classe ‘point’ ci-dessus peut être définie et utilisée comme dans l’exemple suivant : main() { point p1, p2, p3; p1.initialise(1,3); p1.affiche(); p1.deplace(2,4); p1.affiche(); p2.initialise(5,5); p2.affiche(); }
  • 133. On dit que p1 et p2 sont des instances de la classe ‘point’ ou encore que se sont des objets de type ‘point’. - Tous les membres données de ‘point’ sont privés ou encapsulés. Ainsi, on ne peut pas accéder à x ou à y. - Toutefois, les membres données ou les fonctions membres peuvent être privées en utilisant le mot clé ‘private’ ou publiques en utilisant le mot clé ‘public’. Exemple : class C { public : ………………………………. ; …………………………….. ; private : ………………………………. ; ………………………………. ; };
  • 134. 2)Affectation d’objets • C++ autorise l'affectation d'un objet d'un type donnée à un autre objet de même type. Dans ce cas il recopie tout simplement les valeurs des membres données (privés ou publiques) de l'un dans l'autre. Exemple 3.2: Exemple d’affectation entre objets point a,b; // déclare deux instance de la classe point a.initialise(2,5) // a.x = 2 et a.y = 5 b = a; // b.x = 2 et b.y = 5 • Il faut noter que les pointeurs ne sont pas pris en considération dans un cas simple d'affectation : Si parmi les membres données, se trouve un pointeur, l'emplacement pointé ne sera pas recopié 3. Notion de constructeur et de destructeur Un constructeur est une fonction qui sera appelée automatiquement après la création d’un objet. Ceci aura lieu quelque soit la classe d’allocation de l’objet : statique, automatique ou dynamique. - De la même façon, un objet pourra posséder un destructeur, il s’agit également d’une fonction membre qui est appelée automatiquement au moment de la destruction de l’objet correspondant. - Par convention, le constructeur se reconnaît à ce qu’il porte le même nom que la classe. Quand au destructeur, il porte le même nom que la classe précédé du symbole ~.
  • 135. class point { int x; int y; public: point(int,int); // constructeur ... }; // Définition du constructeur point::point(int abs, int ord) { x = abs; y = ord; } Pour déclarer une instance d'une classe ayant un constructeur, on doit spécifier les valeurs des arguments requis par le constructeur point a(2,5); point b; // erreur
  • 136. RQ: • Même si le constructeur ne retourne aucune valeur, il est déclaré et défini sans le mot clé void • Le destructeur est une fonction membre qui porte le même nom que sa classe, précédé du symbole (~). Le destructeur est appelé avant la libération de l'espace associé à l'objet. class point { int x; int y; public: point(int,int); // constructeur ~point(); // destructeur }; Sa syntaxe du destructeur est la suivante : point::~point() {… … } • Le destructeur est une fonction qui ne prend aucun argument et ne renvoie aucune valeur. • En pratique les destructeurs sont utilisés pour libérer d'éventuels emplacements mémoire occupée par des membres données.
  • 137. class demo { int num ; public : demo(int); ~demo(); }; demo::demo(int n) { num=n; cout<<″Appel constr numéro : ″<<num<<endl; } demo::~demo() { cout<<″Appel destr numéro : ″<<num<<endl; } main() { void f(int); demo obj(7); for (int i=0; i<4; i++) f(i); } void f(int m){ demo obj(m) ; }
  • 138. • Le rôle d’un constructeur ou d’un destructeur peut dépasser celui d’initialisation ou de libération. Rq: • Un constructeur peut ou non comporter quelques arguments. - par définition, un constructeur ne renvoie pas de valeur et la présence de void (dans ce cas précis) est une erreur. - Un destructeur, par définition, ne peut pas disposer d’arguments et ne renvoie pas de valeur. 5)Membres données statiques Lorsqu’on crée différents objets d’une même classe, chaque objet possède ces propres données membres, • Un membre donnée déclaré avec l'attribut static est une donnée partagée par tous les instances d'une classe. • Un membre donnée statique est initialisé par défaut à zéro. Mais : ♦ Il doit être défini à l'extérieur de la déclaration de la classe, même s'il est privé, en utilisant l'opérateur de porté (::). ♦ Ne peut être initialisé à l'intérieur de la classe. Exemple: une classe 𝐴 dont on veut connaître à chaque instant le nombre d'instances créées. Pour ce, on munit la classe 𝐴 d'un membre statique 𝑛b_𝑜bj, qu'on incrémente dans le constructeur et qu’on décrémente dans le destructeur.
  • 139. class A { static int nb_obj; ... public: A(...); // constructeur ~A() ; ... }; // définition obligatoire du membre statique int A::nb_obj; // constructeur & destructeur A::A(...) {... nb_obj++; ...} A::~A(...) {... nb_obj--; ...} L'accès à un membre donnée statique d'une classe suit les mêmes règles que les autres membres. D'autre part, un membre donnée statique est une donnée qui existe même si aucun objet de cette classe n'est déclaré, dans ce cas l'accès se fait à l'aide du nom de la classe et l'opérateur de porté (::).
  • 140. /*------------------- Déclaration de la classe-------------------------*/ class point{ int x; int y; public: static int nb_points; // membre donnee static point(int, int); ~point(); void affiche(); }; /*------------------- Définition de la classe-------------------------*/ // la définition du membre donnée static est obligatoire int point::nb_points; //Son initialisation peut être faite à ce niveau point::point(int abs, int ord) { x = abs; y = ord; nb_points++; // un point est crée } point::~point(){ nb_points--; // un point est détruit } void point::affiche(){ cout << "(" << x << "," << y << ")" << endl; cout << "---> nombre de points : " << nb_points << endl; }
  • 141. } // -------------- une fonction quelconque void f(){ point c (2,2); c.affiche(); } //-------------- TEST int main() { // l'accès au membre static peut se faire même si aucun objet // n'est encore crée cout << "Nombre de points : " << point::nb_points << endl; // appel d'une fonction qui manipule les objets de type ‘point’ f(); // tous les objets crées par f() sont détruits cout << "Nombre de points après f() : " << point::nb_points << endl; point a(5,2); cout << "a = "; a.affiche(); point b(-2,4); cout << "b = "; b.affiche(); return 0; }
  • 142. Chapitre 2 : Propriétés des fonctions membres 1)Surdéfinition des fonctions membre La surdéfinition des fonctions s’applique également aux fonctions membres d’une classe, y compris au constructeur (mais pas au destructeur puisqu’il ne possède pas d’arguments). Exemple: class point { int x, y; public : point(); point(int); point(int,int); void affiche(); void affiche(char *); }; point::point() { x=0; y=0; }
  • 143. point::point(int a) { x=y=a; } point::point(int a,int b){ x=a; y=b; } void point::affiche() { cout<<″on est a : ″<<x<<″ - ″<<y<<endl; } void point::affiche(char *t) { cout<<t; affiche(); } main() { point p1; p1.affiche(); point p2(7); p2.affiche(); point p3(44,52); p3.affiche(); p3.affiche(″Troisième point : ″);
  • 144. 2. Arguments par défaut Comme les fonctions ordinaires, les fonctions membres peuvent disposer d’arguments par défaut. Voici comment nous pourrions modifier l’exemple précédent pour que notre classe point ne possède plus qu’une seule fonction affiche disposant d’un seul argument de type chaîne. Celui-ci indique le message à afficher avant les valeurs des coordonnées, et sa valeur par défaut est la chaîne vide. Exemple: #include <iostream> using namespace std ; class point { int x, y ; public : point () ; // constructeur 1 (sans argument) point (int) ; // constructeur 2 (un argument) point (int, int) ; // constructeur 3 (deux arguments) void affiche (char * = "") ; // fonction affiche (un argument par défaut) } ;
  • 145. point::point () // constructeur 1 { x = 0 ; y = 0 ; } point::point (int abs) // constructeur 2 { x = y = abs ; } point::point (int abs, int ord) // constructeur 3 { x = abs ; y = ord ; } void point::affiche (char * message) // fonction affiche { cout << message << "Je suis en : " << x << " " << y << "n" ; } main() { point a ; // appel constructeur 1 a.affiche () ; point b (5) ; // appel constructeur 2 b.affiche ("Point b - ") ; point c (3, 12) ; // appel constructeur 3 c.affiche (« Salut ---- ") ; }
  • 146. 3 Les fonctions membres en ligne Pour rendre ‘en ligne’ une fonction membre, on l’a défini dans la déclaration de la classe même (au lieu de la déclarer dans la classe et de la définir ailleurs). Le mot clé ‘inline’ n’est plus utilisé. #include <iostream> using namespace std ; class point { int x, y ; public : point () { x = 0 ; y = 0 ; } // constructeur 1 "en ligne" point (int abs) { x = y = abs ; } // constructeur 2 "en ligne" point (int abs, int ord) { x = abs ; y = ord ; } // constructeur 3 "en ligne" void affiche (char * = "") ; } ;
  • 147. void point::affiche (char * message) // fonction affiche { cout << message << "Je suis en : " << x << " " << y << "n" ; } main() { point a ; // "appel" constructeur 1 a.affiche () ; point b (5) ; // "appel" constructeur 2 b.affiche ("Point b - ") ; point c (3, 12) ; // "appel" constructeur 3 c.affiche ("Hello ---- ") ; }
  • 148. 4. Cas des objets transmis en argument d’une fonction membre Une fonction membre peut recevoir un ou plusieurs arguments du type de sa classe. Exemple : class point { int x, y; public : point(int a,int b){ x=a; y=b; } int coincide(point); }; int point::coincide(point O) { if(x==O.x && y==O.y) return 1; return 0; } main(){ point p1(5,7), p2(5,7), p3(6,6); cout<<″p1 et p2 : ″<<p1.coincide(p2)<<endl; cout<<″p2 et p3 : ″<<p3.coincide(p2)<<endl; cout<<″p1 et p3 : ″<<p1.coincide(p3)<<endl; }
  • 149. 5. Mode de transmission des objets, arguments d’une fonction Dans l’exemple ci-dessus, le mode de transmission utilisé, était par valeur. 5.1. Transmission de l’adresse d’un objet Exemple : reprendre le programme précédent en faisant un passage d’objets par adresse class point { int x, y; public : point (int a=0,int b=0) { x=a; y=b; } int coincide(point *); };
  • 150. int point::coincide(point *O) { if(x==O->x) && (y==O->y) return 1; return 0; } main() { point p1, p2(57), p3(57,0); cout<<″p1 et p2 : ″<<p1.coincide(&p2)<<endl; cout<<″p2 et p3 : ″<<p3.coincide(&p2)<<endl; cout<<″p1 et p3 : ″<<p1.coincide(&p3)<<endl; } 5.2. Transmission par référence L’emploi des références permet de mettre en place une transmission par adresse, sans avoir à prendre en charge soi même la gestion.
  • 151. class point { int x,y ; public : point(int a=0,int b=0){ x=a; y=b; } int coincide(point &); }; int point::coincide(point & O) { return (x==O.x && y==O.y) ? 1 : 0; } main() { point p1, p2(57), p3(57,0); cout<<″p1 et p2 : ″<<p1.coincide(p2)<<endl; cout<<″p2 et p3 : ″<<p3.coincide(p2)<<endl; cout<<″p1 et p3 : ″<<p1.coincide(p3)<<endl; }
  • 152. 6. Autoréférence : le mot clé ‘this’ Le mot clé ‘this’ utilisé uniquement au sein d’une fonction membre désigne un pointeur sur l’objet l’ayant appelé. class point { int x, y; public : point(int a=0,int b=0){ x=a; y=b; } void affiche(){ cout<<″Point : ″<<x<<″ - ″<<y<<″de l’objet dont l’adresse est : ″<<this<<endl; } }; main() { point p1, p2(5,3), p3(6,70); p1.affiche(); p2.affiche(); p3.affiche(); }
  • 153. #include <iostream> using namespace std ; class point { int x, y ; public : point (int abs=0, int ord=0) // Un constructeur ("inline") { x=abs; y=ord ; } void affiche () ; // Une fonction affiche } ; void point::affiche () { cout << "Adresse : " << this << " - Coordonnees " << x << " " << y << "n" ; } main() { point a(5), b(3,15) ; a.affiche (); b.affiche (); }
  • 154. Chapitre 3 : Construction, destruction et initialisation des objets 1. Objets automatiques et statiques 1.1. Durée de vie d’allocation mémoire Les objets automatiques sont créés par une déclaration : - Dans une fonction. - Dans un bloc. Les objets statiques créés par une déclaration : - En dehors de toute fonction. - Dans une fonction, mais ‘static’. Remarque Les objets statiques sont créés avant le début de l’exécution de la fonction ‘main’ et ils sont détruits après la fin de son exécution 1.2 Appel des constructeurs et des destructeurs Rappelons que si un objet possède un constructeur, sa déclaration (lorsque, comme nous le supposons pour l’instant, elle ne contient pas d’initialiseur) doit obligatoirement comporter les arguments correspondants.
  • 155. si une classe point comporte le constructeur de prototype : point (int, int) les déclarations suivantes seront incorrectes : point a ; // incorrect : le constructeur attend deux arguments point b (3) ; // incorrect (même raison) Celle-ci, en revanche, conviendra : point a(1, 7) ; // correct car le constructeur possède deux arguments S’il existe plusieurs constructeurs, il suffit que la déclaration comporte les arguments requis par l’un d’entre eux. Ainsi, si une classe point comporte les constructeurs suivants : point ( ) ; // constructeur 1 point (int, int) ; // constructeur 2 la déclaration suivante sera rejetée : point a(5) ; // incorrect : aucun constructeur à un argument Mais celles-ci conviendront : point a ; // correct : appel du constructeur 1 point b(1, 7) ; // correct : appel du constructeur 2 En ce qui concerne la chronologie, on peut dire que : • le constructeur est appelé après la création de l’objet ; • le destructeur est appelé avant la destruction de l’objet.
  • 156. #include <iostream> using namespace std ; class point { int x, y ; public : point (int abs, int ord) // constructeur ("inline") { x = abs ; y = ord ; cout << "++ Construction d’un point : " << x << " " << y << "n" ; }
  • 157. ~point () // destructeur ("inline") { cout << "-- Destruction du point : " << x << " " << y << "n" ; } } ; point a(1,1) ; // un objet statique de classe point main() { cout << "****** Debut main *****n" ; point b(10,10) ; // un objet automatique de classe point int i ; for (i=1 ; i<=3 ; i++) { cout << "** Boucle tour numero " << i << "n" ; point b(i,2*i) ; // objets créés dans un bloc } cout << "****** Fin main ******n" ; }
  • 158. 2. Les objets temporaires Lorsqu’une classe dispose d’un constructeur, ce dernier peut être appelé explicitement ; dans ce cas, il y a alors création d’un objet temporaire. Exemple #include <iostream> using namespace std ; class point { int x, y ; public : point (int abs, int ord) // constructeur ("inline") { x = abs ; y = ord ; cout << "++ Constr. point " << x << " " << y << " a l’adresse : " << this << "n" ; } ~point () // destructeur ("inline") { cout << "-- Destr. point " << x << " " << y << " a l’adresse : " << this << "n" ; } } ;
  • 159. main(){ point a(0,0) ; // un objet automatique de classe point a = point (1, 2) ; // un objet temporaire a = point (3, 5) ; // un autre objet temporaire cout << "****** Fin main ******n" ; } On voit clairement que les deux affectations de la fonction main entraînent la création d’un objet temporaire distinct de a, qui se trouve détruit tout de suite après. La dernière destruction,réalisée après la fin de l’exécution, concerne l’objet automatique a Exemple d’objet dynamique:
  • 160. #include <iostream> using namespace std ; class point { int x, y ; public : point (int abs, int ord) // constructeur { x=abs ; y=ord ; cout << "++ Appel Constructeur n" ; } ~point () // destructeur (en fait, inutile ici) { cout << "-- Appel Destructeur n" ; } } ;
  • 161. main() { void fct (point *) ; // prototype fonction fct point * adr ; cout << "** Debut main n" ; adr = new point (3,7) ; // création dynamique d’un objet fct (adr) ; cout << "** Fin main n" ; } void fct (point * adp) { cout << "** Debut fct n" ; delete adp ; // destruction de cet objet cout << "** Fin fct n" ; }

Notes de l'éditeur

  1. On commence par déclarer une variable Ptr de type int * : un pointeur sur entier , puis une variable i de type entier , On assigne à ptr l’adresse en mémoire grace à l’operateur &. On affiche ensuite ce que contient ptr :une adresse une valeur qui sera affichée en héxadécimal puis on affiche la valeur pointée par ptr (méme valeur que i) on dit qu’on a déferencée le pointeur ptr
  2. Classe :
  3. getch :instruction non-standard pour récupèrer un appui sur le clavier, sans qu'il soit affiché