Cours Poo

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 70

Programmation orientée objet - POO :

C++/Python

Licence Sciences et Techniques GI

Pr. Lotfi ELAACHAK


Département Génie Informatique

2021 — 2022
Table des matières

1 Le Paradigm de la Programmation orientée objet 4


1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2 Une classe orientée objet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3 Un Objet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.4 L’encapsulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.5 L’héritage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.6 Le polymorphisme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.6.1 Overriding : Surdefinition . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.6.2 Overloading : SurCharge . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.7 Classe abstraite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

2 La programmation POO : C++ 11


2.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.1.1 Bibliothèques standard C++ . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.1.2 Utilisation de C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.1.3 C++ Premier Programme . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.2 Entrée/sortie de base C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.2.1 Fichiers d’en-tête de bibliothèque d’E/S . . . . . . . . . . . . . . . . . . . 12
2.2.2 Flux de sortie standard (cout) . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.2.3 Flux d’entré standard (cin) . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.2.4 Ligne de fin standard (endl) . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.3 C vs C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.3.1 Comparaison . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.3.2 Pointer vs Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.3.3 Différences entre la référence et le pointeur . . . . . . . . . . . . . . . . . . 15
2.4 C++ Object et Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.4.1 C++ Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.4.2 C++ Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.4.3 Initialiser et afficher les données via la méthode . . . . . . . . . . . . . . . 18
2.4.4 Constructeurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.4.5 Constructeur par copie C++ . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.4.6 Destructeur C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.4.7 C++ this pointeur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.4.8 C++ static . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.4.9 Fonction Ami C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.5 C++ héritage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.5.1 Types d’héritage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.5.2 Héritage unique C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

1
2.5.3 Héritage multiple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.6 C++ Polymorphisme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
2.6.1 Polymorphisme au moment de la compilation . . . . . . . . . . . . . . . . 34
2.6.2 Polymorphisme d’exécution . . . . . . . . . . . . . . . . . . . . . . . . . . 34
2.6.3 Surcharge Fonction et opérateur . . . . . . . . . . . . . . . . . . . . . . . . 35
2.6.4 Redéfinition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
2.6.5 Virtual . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
2.6.6 Fonction virtuelle pure et C++ Abstraction . . . . . . . . . . . . . . . . . 40
2.7 C++ Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
2.7.1 C++ Exception Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
2.7.2 C++ try/catch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
2.7.3 Exceptions personnalisées . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
2.8 C++ Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
2.8.1 template de fonction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
2.8.2 Template de class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
2.9 C++ STL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
2.9.1 Les conteneurs STL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
2.9.2 Les Vecteurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
2.9.3 Les Listes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
2.9.4 Les Sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
2.9.5 Les Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

3 La programmation POO : Python 57


3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
3.2 Python Classe et Objets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
3.2.1 Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
3.2.2 Objets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
3.2.3 Constructeur Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
3.3 Python héritage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
3.3.1 Héritage simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
3.3.2 Héritage multiple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
3.3.3 La méthode issubclass(sub,sup) . . . . . . . . . . . . . . . . . . . . . . . . 60
3.3.4 La méthode isinstance (obj, class) . . . . . . . . . . . . . . . . . . . . . . . 60
3.3.5 Redéfinition de la méthode . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
3.3.6 Abstraction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
3.4 Try Except . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
3.4.1 Le problème sans gérer les exceptions . . . . . . . . . . . . . . . . . . . . . 63
3.4.2 Gestion des exceptions en python . . . . . . . . . . . . . . . . . . . . . . . 63
3.5 Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
3.5.1 List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
3.5.2 Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
3.5.3 Dictionary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67

Lotfi ELAACHAK Page 2


Chapitre1
Le Paradigm de la Programmation
orientée objet
1.1 Introduction
La programmation orientée objet (POO) est le terme utilisé pour décrire une approche de pro-
grammation basée sur des objets et des classes. Le paradigme orienté objet nous permet d’organi-
ser le logiciel comme une collection d’objets constitués à la fois de données et de comportements.
Cela contraste avec la pratique de programmation fonctionnelle conventionnelle qui ne relie que
vaguement les données et le comportement.

Depuis les années 1980, le mot « objet » est apparu en relation avec les langages de programma-
tion, presque tous les langages développés depuis 1990 ayant des fonctionnalités orientées objet.
Certains langages ont même été équipés de fonctionnalités orientées objet. Il est largement admis
que la programmation orientée objet est le moyen le plus important et le plus puissant de créer
des logiciels.

L’approche de programmation orientée objet encourage :

Modularisation : où l’application peut être décomposée en modules.

Réutilisation du logiciel : où une application peut être composée de modules existants et nou-
veaux.

Un langage de programmation orienté objet prend généralement en charge cinq fonctionnalités


principales :
— Classes
— Objets
— Encapsulation
— Héritage
— Polymorphisme

1.2 Une classe orientée objet


Si on pense à un objet du monde réel, tel qu’une télévision , il aura plusieurs caractéristiques et
propriétés :
— On n’a pas besoin d’ouvrir le boîtier pour l’utiliser.
— On a quelques commandes pour l’utiliser ( télécommande).
— On peut encore comprendre le concept d’un téléviseur, même s’il est connecté à un lecteur
DVD.
— Il est complet lorsque nous l’achetons, avec toutes les exigences externes bien documentées.
— Le téléviseur ne plantera pas !

3
Une classe doit :
— Fournir une interface bien définie - telle que la télécommande du téléviseur.
— Représenter un concept clair - tel que le concept d’une télévision.
— Complet et bien documenté - le téléviseur doit avoir une prise et un manuel qui documente
toutes les fonctionnalités.
— Le code doit être robuste - il ne doit pas planter, comme la télévision.

Avec un langage de programmation procédural (comme C), nous aurions les composants du té-
léviseur dispersés partout et nous serions responsables de les faire fonctionner correctement - il
n’y aurait aucun cas entourant les composants électroniques.

Les humains utilisent tout le temps des descriptions basées sur les classes - qu’est-ce qu’un
moteur ?
Les classes nous permettent de représenter des structures complexes dans un langage de pro-
grammation. Ils ont deux composants :
— Les états - (données/attributs) sont les valeurs de l’objet.
— Méthodes - (ou comportement) sont les façons dont l’objet peut interagir avec ses données,
les actions.

La notation utilisée dans la Figure suivante sur le côté droit est une représentation en langage
de modélisation unifié (UML) de la classe Télévision pour la modélisation et la programmation
orientées objet.

1.3 Un Objet
Un objet est une instance d’une classe. Vous pourriez considérer une classe comme la description
d’un concept et un objet comme la réalisation de cette description pour créer une entité distincte
indépendante. Par exemple, dans le cas de la télévision, la classe est l’ensemble de plans (ou de
plans) pour une télévision générique, tandis qu’un objet de télévision est la réalisation de ces
plans dans une télévision physique du monde réel. Il y aurait donc un ensemble de plans (la
classe), mais il pourrait y avoir des milliers de téléviseurs du monde réel (objets).

Les objets peuvent être concrets (un objet du monde réel, un fichier sur un ordinateur) ou peuvent
être conceptuels (comme une structure de base de données) chacun avec sa propre identité indivi-
duelle. La figure suivante montre un exemple où la description de la classe Télévision est réalisée
en plusieurs objets télévision. Ces objets doivent avoir leur propre identité et sont indépendants
les uns des autres. Par exemple, si le canal est modifié sur un téléviseur, il ne changera pas sur
les autres téléviseurs.

Lotfi ELAACHAK Page 4


1.4 L’encapsulation
Le paradigme orienté objet encourage l’encapsulation. L’encapsulation est utilisée pour masquer
la mécanique de l’objet, permettant de masquer la mise en œuvre réelle de l’objet, de sorte qu’on
n’a pas besoin de comprendre comment l’objet fonctionne. Tout ce que nous devons comprendre,
c’est l’interface qui nous est fournie.

On peut penser à cela dans le cas de la classe Télévision, où la fonctionnalité de la télévision nous
est cachée, mais on nous fournit une télécommande ou un ensemble de commandes pour interagir
avec la télévision, offrant un haut niveau d’abstraction. Ainsi, comme dans la figure suivante, il
n’est pas nécessaire de comprendre comment le signal est décodé de l’antenne et converti en une
image à afficher sur l’écran avant de pouvoir utiliser le téléviseur.

Il existe un sous-ensemble de fonctionnalités que l’utilisateur est autorisé à appeler, appelé l’in-
terface. Dans le cas du téléviseur, il s’agirait de la fonctionnalité que nous pourrions utiliser via
la télécommande ou les boutons situés à l’avant du téléviseur.

L’implémentation complète d’une classe est la somme de l’interface publique et de l’implémen-


tation privée.

L’encapsulation est le terme utilisé pour décrire la manière dont l’interface est séparée de l’im-
plémentation. Vous pouvez considérer l’encapsulation comme un "masquage de données", per-
mettant à certaines parties d’un objet d’être visibles, tandis que d’autres parties restent cachées.
Cela présente des avantages à la fois pour l’utilisateur et le programmeur.
Pour l’utilisateur (qui pourrait être un autre programmeur) :
— L’utilisateur n’a qu’à comprendre l’interface.

Lotfi ELAACHAK Page 5


— L’utilisateur n’a pas besoin de comprendre comment l’implémentation fonctionne ou a été
créée.

Pour le programmeur :
— Le programmeur peut modifier l’implémentation, mais n’a pas besoin d’en informer l’uti-
lisateur.

Ainsi, à condition que le programmeur ne modifie en aucune manière l’interface, l’utilisateur ne


sera pas au courant de tout changement, à l’exception peut-être d’un changement mineur dans
la fonctionnalité réelle de l’application.
On peut identifier un niveau de « masquage » de méthodes ou d’états particuliers au sein d’une
classe en utilisant les mots-clés public, private et protected :
— méthodes publiques - décrivent l’interface.
— méthodes privées - décrivent la mise en œuvre.

La Figure suivante montre l’encapsulation en ce qui concerne la classe Télévision. Selon la notation
UML, les méthodes privées sont désignées par un signe moins et les méthodes publiques sont
désignées par un signe plus. Les méthodes privées seraient des méthodes écrites qui font partie
du fonctionnement interne de la télévision, mais n’ont pas besoin d’être comprises par l’utilisateur.
Par exemple, l’utilisateur aurait besoin d’appeler la méthode powerOn() mais la méthode privée
displayPicture() serait également appelée, mais en interne si nécessaire, pas directement par
l’utilisateur. Cette méthode n’est donc pas ajoutée à l’interface, mais masquée en interne dans
l’implémentation en utilisant le mot clé private.

1.5 L’héritage
Si on a plusieurs descriptions avec des points communs entre ces descriptions, nous pouvons
regrouper les descriptions et leurs points communs en utilisant l’héritage pour fournir une repré-
sentation compacte de ces descriptions. L’approche de programmation orientée objet nous permet
de regrouper les points communs et de créer des classes qui peuvent décrire leurs différences par
rapport aux autres classes.

Les humains utilisent ce concept pour catégoriser les objets et les descriptions. Par exemple, vous
avez peut-être répondu à la question « Qu’est-ce qu’un canard ? » par « un oiseau qui nage », ou
encore plus précisément « un oiseau qui nage, avec des pattes palmées et un bec au lieu d’un bec
». Nous pourrions donc dire qu’un canard est un oiseau qui nage, nous pourrions donc le décrire
comme dans la figure suivante . Cette figure illustre la relation d’héritage entre un canard et un
oiseau. En effet on peut dire qu’un Canard est un type particulier d’Oiseau.

Lotfi ELAACHAK Page 6


Un autre exemple plus complexe :

1.6 Le polymorphisme
Lorsqu’une classe hérite d’une autre classe, elle hérite à la fois des états et des méthodes de
cette classe, donc dans le cas de la classe Car héritant de la classe Vehicle, la classe Car hérite
des méthodes de la classe Vehicle, telles que engineStart(), gearChange( ), lightsOn() etc. La
classe Car héritera également des états de la classe Vehicle, tels que isEngineOn, isLightsOn,
numberWheels etc.

Le polymorphisme signifie "formes multiples". En POO, ces formes multiples font référence à
plusieurs formes de la même méthode, où exactement le même nom de méthode peut être utilisé
dans différentes classes, ou le même nom de méthode peut être utilisé dans la même classe avec
des paramètres légèrement différents. Il existe deux formes de polymorphisme, le surdefinition et
la surcharge.

On pourrait définir le polymorphisme comme la propriété permettant à un programme de réagir


de manière différenciée à l’envoi d’un même message (invocation de méthode) en fonction des
objets qui reçoivent ce message.
— Il s’agit donc d’une aptitude d’adaptation dynamique du comportement selon les objets
en présence.
— Avec l’encapsulation et l’héritage, le polymorphisme est une des propriétés essentielles de
la programmation orientée objet.

1.6.1 Overriding : Surdefinition


Comme indiqué, une classe dérivée hérite de ses méthodes de la classe de base. Il peut être né-
cessaire de redéfinir une méthode héritée pour fournir un comportement spécifique à une classe

Lotfi ELAACHAK Page 7


dérivée - et ainsi modifier l’implémentation. Ainsi, la substitution est le terme utilisé pour décrire
la situation où le même nom de méthode est appelé sur deux objets différents et chaque objet
répond différemment.

Le Overriding permet à différents types d’objets partageant un comportement commun d’être


utilisés dans du code qui ne requiert que ce comportement commun.

Considérons l’exemple précédent du diagramme de classe de véhicule. Dans ce cas, Car hérite de
Véhicule et à partir de cette classe Car, il existe d’autres classes dérivées SaloonCar et EstateCar.
Si une méthode draw() est ajoutée à la classe Car, cela est nécessaire pour dessiner une image d’un
véhicule générique. Cette méthode ne dessinera pas de manière adéquate un break ou d’autres
classes d’enfants. Over-Riding nous permet d’écrire une méthode draw() spécialisée pour la classe
EstateCar - Il n’est pas nécessaire d’écrire une nouvelle méthode draw() pour la classe SaloonCar
car la classe Car fournit une méthode draw() suffisamment appropriée. Tout ce que nous avons à
faire est d’écrire une nouvelle méthode draw() dans la classe EstateCar avec exactement le même
nom de méthode. Ainsi, l’Overriding permet :
— Une API plus simple où nous pouvons appeler des méthodes du même nom, même si ces
méthodes ont des fonctionnalités légèrement différentes.
— Un meilleur niveau d’abstraction, dans la mesure où les mécanismes d’implémentation
restent cachés.

1.6.2 Overloading : SurCharge


La surcharge est la deuxième forme de polymorphisme. Le même nom de méthode peut être
utilisé, mais le nombre de paramètres ou les types de paramètres peuvent différer, ce qui permet
au compilateur de choisir la bonne méthode. Par example :

add (int x, int y)


add (String x, String y)

sont deux méthodes différentes qui ont le même nom et le même nombre de paramètres. Cepen-
dant, lorsque nous passons deux objets String au lieu de deux variables int, nous attendons des
fonctionnalités différentes. Lorsque nous ajoutons deux valeurs int, nous attendons un résultat
- par exemple 6 + 7 = 13. Cependant, si nous passons deux objets String, nous attendons un
résultat de "6" + "7" = "67". En d’autres termes, les chaînes doivent être concaténées.

Le nombre d’arguments peut également déterminer quelle méthode doit être exécutée.

Lotfi ELAACHAK Page 8


channel()
channel(int x)

fournira des fonctionnalités différentes où la première méthode peut simplement afficher le numéro
de canal actuel, mais la deuxième méthode définira le numéro de canal sur le numéro passé.

1.7 Classe abstraite


Une classe abstraite est une classe incomplète, en ce sens qu’elle décrit un ensemble d’opérations,
mais auquel il manque l’implémentation réelle de ces opérations. Cours abstraits :
— Ne peut pas être instancié.
— onc, ne peut être utilisé que par héritage.

Lotfi ELAACHAK Page 9


Chapitre 2
La programmation POO : C++
2.1 Introduction
C++ est un langage de programmation de forme libre à usage général, sensible à la casse, qui
prend en charge la programmation orientée objet, procédurale et générique.

C++ est un langage de niveau intermédiaire, car il encapsule à la fois des fonctionnalités de
langage de haut et de bas niveau.

C++ supports the object-oriented programming, the four major pillar of object-oriented pro-
gramming (OOPs) used in C++ are :
— Inheritance
— Polymorphism
— Encapsulation
— Abstraction

2.1.1 Bibliothèques standard C++


La programmation C++ standard est divisée en trois parties importantes :
— La bibliothèque principale comprend les types de données, les variables, etc.
— La bibliothèque standard comprend l’ensemble des fonctions manipulant des chaînes de
caractères, des fichiers, etc.
— La bibliothèque de modèles standard (STL) comprend l’ensemble des méthodes manipu-
lant une structure de données.

2.1.2 Utilisation de C++


A l’aide du langage de programmation C++, nous pouvons développer différents types d’appli-
cations sécurisées et robustes :

10
— Application de Bureau
— Application client-serveur
— Pilotes de périphérique
— Micrologiciel intégré, Programmation embarquée, etc.

2.1.3 C++ Premier Programme


Dans un fichier main.cpp par exemple :
Hello word
#include <iostream>
using namespace std;

int main(){
cout << "hello word" << endl ;
return 0 ;
}

2.2 Entrée/sortie de base C++


L’opération d’E/S C++ utilise le concept de flux. Le flux est la séquence d’octets ou le flux de
données. Cela rend la performance rapide.

Si des octets circulent de la mémoire principale vers un périphérique comme une imprimante, un
écran d’affichage ou une connexion réseau, etc., cela s’appelle une opération de sortie.

Si des octets circulent depuis un périphérique comme une imprimante, un écran d’affichage ou
une connexion réseau, etc. vers la mémoire principale, cela s’appelle une opération d’entrée.

2.2.1 Fichiers d’en-tête de bibliothèque d’E/S

Fichier d’en-tête Fonction et description


<iostream> Définir les objets cout, cin et cerr,
<iomanip> Déclarer des services utiles pour effectuer des E/S formatées,
<fstream> Déclarer des services pour le traitement de fichiers contrôlé par l’utilisateur.

2.2.2 Flux de sortie standard (cout)


Le cout est un objet prédéfini de la classe ostream. Il est connecté au périphérique de sortie
standard, qui est généralement un écran d’affichage. Le cout est utilisé en conjonction avec
l’opérateur d’insertion de flux («) pour afficher la sortie sur une console.
CIN
#include <iostream>
using namespace std;

Lotfi ELAACHAK Page 11


int main(){
char [] msg = "Hello CIN"
cout << msg << endl; ;
return 0 ;
}

2.2.3 Flux d’entré standard (cin)


Le cin est un objet prédéfini de la classe istream. Il est connecté au périphérique d’entrée standard,
qui est généralement un clavier. Le cin est utilisé en conjonction avec l’opérateur d’extraction de
flux (») pour lire l’entrée à partir d’une console.
COUT
#include <iostream>
using namespace std;

int main(){
int age;
cout << "Enter your age: ";
cin >> age;
cout << "Your age is: " << age << endl;
return 0 ;
}

2.2.4 Ligne de fin standard (endl)


Le endl est un objet prédéfini de la classe ostream. Il est utilisé pour insérer une nouvelle ligne
de caractères et vide le flux.
ENDL
#include <iostream>
using namespace std;

int main(){
cout << "C++ Tutorial";
cout << " Javatpoint"<<endl;
cout << "End of line"<<endl;
return 0 ;
}

Lotfi ELAACHAK Page 12


2.3 C vs C++

2.3.1 Comparaison

No C C++
1 Programmation de style procédural. Procédural et orienté objet.
2 Les données sont moins sécurisées en C. En C++, on peut utiliser des modificateurs
3 Ne prend pas en charge la surcharge de fonction. Supporte la surcharge de fonction.
4 N’utilise pas de fonctions dans la structure. Utilise des fonctions dans la structure.
5 ne prend pas en charge les variables de référence. Supporte les variables de référence.
6 En C, scanf() et printf() En C,++ cin et cout
7 Surcharge d’opérateurs n’est supporté en C. Surcharge d’opérateurs est supporté en C++.
8 pas d’espace de noms "namespace" Support d’espace de noms
9 Gestion d’Excpetions difficile Gestion d’Excpetions facile
10 Pas d’héritage Avec héritage

2.3.2 Pointer vs Reference


La référence et le pointeur C++ semblent être similaires, mais il existe des différences entre
eux. Une référence est une variable qui est un autre nom de la variable existante, tandis que le
pointeur est une variable qui stocke l’adresse d’une autre variable.

Reference

Une référence est une variable qui est appelée un autre nom pour une variable déjà existante. La
référence d’une variable est créée en stockant l’adresse d’une autre variable.

Une variable de référence peut être considérée comme un pointeur constant avec indirection
automatique. Ici, l’indirection automatique signifie que le compilateur applique automatiquement
l’opérateur d’indirection (*).
Reference
#include <iostream>
using namespace std;
int main()
{
int i=8; // variable initialization

Lotfi ELAACHAK Page 13


int &a=i; // creating a reference variable
cout<<"The value of 'i' variable is :"<<a;
return 0;
}

Pointer

Un pointeur est une variable qui contient l’adresse d’une autre variable. Il peut être déréférencé
à l’aide de l’opérateur (*) pour accéder à l’emplacement mémoire vers lequel pointe le pointeur.
Pointer
#include <iostream>
using namespace std;
int main()
{
int i=8; // variable initialization
int *a=&i; // creating a reference variable
cout<<"The value of 'i' variable is :"<<*a<<endl;
cout<<"The address of 'i' variable is :"<<a<<endl;
cout<<"The address of 'i' variable is :"<<&i<<endl;
return 0;
}

2.3.3 Différences entre la référence et le pointeur


Une variable de référence est un autre nom pour une variable déjà existante. Il est principalement
utilisé dans le « passer par référence » où la variable de référence est transmise en tant que
paramètre à la fonction et la fonction à laquelle cette variable est transmise fonctionne sur la
copie originale de la variable.
Call Functions
#include <iostream>
using namespace std;
void funcref(int &);
void funcpointer(int *);
void funcvalue(int m);
int main()
{
int a=10, b= 10 , c = 10;
std::cout <<"Value of 'a' is :" <<a<< std::endl;
funcref(a);
std::cout << "Now value of 'a' before reference call is :" <<a<< std::endl;

std::cout <<"Value of 'b' is :" <<b<< std::endl;


funcpointer(&b);
std::cout << "Now value of 'b' before address call is :" <<b<< std::endl;

Lotfi ELAACHAK Page 14


std::cout <<"Value of 'c' is :" <<c<< std::endl;
funcvalue(c);
std::cout << "Now value of 'c' before value call is :" <<c<< std::endl;

return 0;
}

void funcvalue(int m)
{
m=8;
}

void funcpointer(int *m)


{
*m=8;
}

void funcref(int &m)


{
m=8;
}

2.4 C++ Object et Class


L’objectif principal de la programmation C++ est d’introduire le concept d’orientation objet
dans le langage de programmation C.

La programmation orientée objet est un paradigme qui fournit de nombreux concepts tels que
l’héritage, la liaison de données, le polymorphisme, etc.

Le paradigme de programmation où tout est représenté comme un objet est connu comme un
langage de programmation véritablement orienté objet. Smalltalk est considéré comme le premier
langage de programmation véritablement orienté objet.

2.4.1 C++ Class


En C++, la classe est un groupe d’objets similaires. C’est un modèle à partir duquel les objets
sont créés. Il peut avoir des champs, des méthodes, des constructeurs, etc.
Class
#include <iostream>
using namespace std;
class Student
{
public:

Lotfi ELAACHAK Page 15


int id; //field or data member
float salary; //field or data member
string name;//field or data member

};

int main()
{

return 0;
}

2.4.2 C++ Object


En C++, l’objet est une entité du monde réel, par exemple, une chaise, une voiture, un stylo, un
mobile, un ordinateur portable, etc.

En d’autres termes, l’objet est une entité qui a un état et un comportement. Ici, état signifie
données et comportement signifie fonctionnalité.

L’objet est une entité d’exécution, il est créé lors de l’exécution.

L’objet est une instance d’une classe. Tous les membres de la classe sont accessibles via object.

Class
#include <iostream>
using namespace std;
class Student
{
public:
int id; //field or data member
float salary; //field or data member
string name;//field or data member

};

int main()
{

Student student ;

student.id = 201;
student.name = "Sonoo Jaiswal";
cout<<student.id<<endl;
cout<<student.name<<endl;

Lotfi ELAACHAK Page 16


return 0;
}

2.4.3 Initialiser et afficher les données via la méthode

Exemple
#include <iostream>
using namespace std;
class Student {
public:
int id;//data member (also instance variable)
string name;//data member(also instance variable)
void insert(int i, string n)
{
id = i;
name = n;
}
void display()
{
cout<<id<<" "<<name<<endl;
}
};
int main(void) {
Student s1; //creating an object of Student
Student s2; //creating an object of Student
s1.insert(201, "Sonoo");
s2.insert(202, "Nakul");
s1.display();
s2.display();
return 0;
}

2.4.4 Constructeurs
En C++, le constructeur est une méthode spéciale qui est invoquée automatiquement au moment
de la création de l’objet. Il est utilisé pour initialiser les données membres du nouvel objet en
général. Le constructeur en C++ a le même nom que la classe ou la structure.

Il peut y avoir deux types de constructeurs en C++.


— Constructeur par défaut.
— Constructeur paramétré.

Lotfi ELAACHAK Page 17


Constructeur par défaut C++

Un constructeur qui n’a pas d’argument est appelé constructeur par défaut. Il est invoqué au
moment de la création de l’objet.
Constructeur
#include <iostream>
using namespace std;
class Employee
{
public:
Employee()
{
cout<<"Default Constructor Invoked"<<endl;
}
};
int main(void)
{
Employee e1; //creating an object of Employee
Employee e2;
return 0;
}

Constructeur paramétré C++

Un constructeur qui a des paramètres est appelé constructeur paramétré. Il est utilisé pour fournir
des valeurs différentes à des objets distincts.
Constructeur
#include <iostream>
using namespace std;
class Employee {
public:
int id;//data member (also instance variable)
string name;//data member(also instance variable)
float salary;
Employee(int i, string n, float s)
{
id = i;
name = n;
salary = s;
}
void display()
{
cout<<id<<" "<<name<<" "<<salary<<endl;
}
};
int main(void) {

Lotfi ELAACHAK Page 18


Employee e1 =Employee(101, "Sonoo", 890000); //creating an object of Employee
Employee e2=Employee(102, "Nakul", 59000);
e1.display();
e2.display();
return 0;
}

2.4.5 Constructeur par copie C++


Un constructeur Copy est un constructeur surchargé utilisé pour déclarer et initialiser un objet
à partir d’un autre objet.

Le constructeur par copie est de deux types :


— Constructeur de copie par défaut : le compilateur définit le constructeur de copie par
défaut. Si l’utilisateur ne définit aucun constructeur de copie, le compilateur fournit son
constructeur.
— Constructeur défini par l’utilisateur : le programmeur définit le constructeur défini par
l’utilisateur.

Syntaxe du constructeur de copie défini par l’utilisateur

Constructeur
#include <iostream>
using namespace std;
class A
{
public:
int x;
A(int a) // parameterized constructor.
{
x=a;
}
A(A &i) // copy constructor
{
x = i.x;
}
};

Lotfi ELAACHAK Page 19


int main()
{
A a1(20); // Calling the parameterized constructor.
A a2(a1); // Calling the copy constructor.
cout<<a2.x; \\ 20
return 0;
}

Qunad le copie est appelé

Le constructeur de copie est appelé dans les scénarios suivants :


— Lorsque nous initialisons l’objet avec un autre objet existant du même type de classe. Par
exemple, Student s1 = s2, où Student est la classe.
— Lorsque l’objet du même type de classe est passé par valeur en argument.
— Lorsque la fonction renvoie l’objet du même type de classe par valeur.

Copie superficielle / shallow copy

— Le constructeur de copie par défaut ne peut produire que la copie superficielle.


— Une copie superficielle est définie comme le processus de création de la copie d’un objet
en copiant les données de toutes les variables membres telles qu’elles sont.
shallow copy
#include <iostream>

using namespace std;

class Demo
{
int a;
int b;
int *p;
public:
Demo()
{
p=new int;
}
void setdata(int x,int y,int z)
{
a=x;
b=y;
*p=z;
}
void showdata()
{
std::cout << "value of a is : " <<a<< std::endl;
std::cout << "value of b is : " <<b<< std::endl;

Lotfi ELAACHAK Page 20


std::cout << "value of *p is : " <<*p<< std::endl;
}
};
int main()
{
Demo d1;
d1.setdata(4,5,7);
Demo d2 = d1;
d2.showdata();
return 0;
}

Dans le cas ci-dessus, un programmeur n’a défini aucun constructeur, donc l’instruction Demo
d2 = d1 ; appelle le constructeur par défaut défini par le compilateur. Le constructeur par défaut
crée la copie exacte ou la copie superficielle de l’objet existant. Ainsi, le pointeur p des deux objets
pointe vers le même emplacement mémoire. Par conséquent, lorsque la mémoire d’un champ est
libérée, la mémoire d’un autre champ est également automatiquement libérée car les deux champs
pointent vers le même emplacement mémoire. Ce problème est résolu par le constructeur défini
par l’utilisateur qui crée la copie profonde.

Copie profonde / deep copy

La copie profonde alloue dynamiquement la mémoire pour la copie, puis copie la valeur réelle,
la source et la copie ont des emplacements de mémoire distincts. De cette façon, la source et la
copie sont distinctes et ne partageront pas le même emplacement mémoire. La copie profonde
nous oblige à écrire le constructeur défini par l’utilisateur.
deep copy
#include <iostream>
using namespace std;
class Demo
{
public:
int a;
int b;
int *p;

Demo()

Lotfi ELAACHAK Page 21


{
p=new int;
}
Demo(Demo &d)
{
a = d.a;
b = d.b;
p = new int;
*p = *(d.p);
}
void setdata(int x,int y,int z)
{
a=x;
b=y;
*p=z;
}
void showdata()
{
std::cout << "value of a is : " <<a<< std::endl;
std::cout << "value of b is : " <<b<< std::endl;
std::cout << "value of *p is : " <<*p<< std::endl;
}
};
int main()
{
Demo d1;
d1.setdata(4,5,7);
Demo d2 = d1;
d2.showdata();
return 0;
}

2.4.6 Destructeur C++


Un destructeur fonctionne à l’opposé du constructeur ; il détruit les objets des classes. Il ne peut
être défini qu’une seule fois dans une classe. Comme les constructeurs, il est invoqué automati-

Lotfi ELAACHAK Page 22


quement.
Un destructeur se définit comme un constructeur. Il doit avoir le même nom que la classe. Mais
il est préfixé d’un signe tilde (˜).

Exemple de constructeur et de destructeur C++

Destructeur
#include <iostream>
using namespace std;
class Employee
{
public:
Employee()
{
cout<<"Constructor Invoked"<<endl;
}
~Employee()
{
cout<<"Destructor Invoked"<<endl;
}
};
int main(void)
{
Employee e1; //creating an object of Employee
Employee e2; //creating an object of Employee
return 0;
}

2.4.7 C++ this pointeur


En programmation C++, il s’agit d’un mot-clé qui fait référence à l’instance actuelle de la classe.
Il peut y avoir 3 utilisations principales de ce mot-clé en C++.
— Il peut être utilisé pour passer l’objet courant en tant que paramètre à une autre méthode.
— Il peut être utilisé pour faire référence à la variable d’instance de classe actuelle.
— Il peut être utilisé pour déclarer des indexeurs.
Destructeur
#include <iostream>
using namespace std;
class Employee {
public:
int id; //data member (also instance variable)
string name; //data member(also instance variable)
float salary;
Employee(int id, string name, float salary)
{
this->id = id;

Lotfi ELAACHAK Page 23


this->name = name;
this->salary = salary;
}
void display()
{
cout<<id<<" "<<name<<" "<<salary<<endl;
}
};
int main(void) {
Employee e1 =Employee(101, "Sonoo", 890000); //creating an object of Employee
Employee e2=Employee(102, "Nakul", 59000); //creating an object of Employee
e1.display();
e2.display();
return 0;

2.4.8 C++ static


En C++, static est un mot-clé ou un modificateur qui appartient au type et non à l’instance.
Ainsi, l’instance n’est pas requise pour accéder aux membres statiques. En C++, static peut
être un champ, une méthode, un constructeur, une classe, des propriétés, un opérateur et un
événement.

Avantage du mot-clé statique C++

Mémoire efficace : nous n’avons plus besoin de créer d’instance pour accéder aux membres sta-
tiques, ce qui permet d’économiser de la mémoire. De plus, il appartient au type, il n’obtiendra
donc pas de mémoire à chaque fois que l’instance est créée.

Exemple de champ statique

Static
#include <iostream>
using namespace std;
class Account {
public:
int accno; //data member (also instance variable)
string name;
static int count;
Account(int accno, string name)
{
this->accno = accno;
this->name = name;
count++;
}
void display()
{

Lotfi ELAACHAK Page 24


cout<<accno<<" "<<name<<endl;
}
};
int Account::count=0;
int main(void) {
Account a1 =Account(201, "Sanjay"); //creating an object of Account
Account a2=Account(202, "Nakul");
Account a3=Account(203, "Ranjana");
a1.display();
a2.display();
a3.display();
cout<<"Total Objects are: "<<Account::count;
return 0;
}

2.4.9 Fonction Ami C++


Si une fonction est définie comme une fonction amie en C++, les données protégées et privées
d’une classe sont accessibles à l’aide de la fonction.

En utilisant le mot-clé friend, le compilateur sait que la fonction donnée est une fonction friend.

Pour accéder aux données, la déclaration d’une fonction friend doit se faire à l’intérieur du corps
d’une classe commençant par le mot-clé friend.

Fonction ami Exemple

Fonction Amie
#include <iostream>
using namespace std;
class Box
{
private:
int length;
public:
Box(): length(0) { }
friend int printLength(Box); //friend function
};
int printLength(Box b)
{
b.length += 10;
return b.length;
}
int main()
{

Lotfi ELAACHAK Page 25


Box b;
cout<<"Length of box: "<< printLength(b)<<endl;
return 0;
}

Exemple simple lorsque la fonction est conviviale pour deux classes

Fonction Amie 2 classes


#include <iostream>
using namespace std;
class B; // forward declarartion.
class A
{
int x;
public:
void setdata(int i)
{
x=i;
}
friend void min(A,B); // friend function.
};
class B
{
int y;
public:
void setdata(int i)
{
y=i;
}
friend void min(A,B); // friend function
};
void min(A a,B b)
{
if(a.x<=b.y)
std::cout << a.x << std::endl;
else
std::cout << b.y << std::endl;
}
int main()
{
A a;
B b;
a.setdata(10);
b.setdata(20);
min(a,b);

Lotfi ELAACHAK Page 26


return 0;
}

Classe amie en C++

Une classe amie peut accéder à la fois aux membres privés et protégés de la classe dans laquelle
elle a été déclarée comme amie.
Classe Amie
#include <iostream>

using namespace std;

class A
{
int x =5;
friend class B; // friend class.
};
class B
{
public:
void display(A &a)
{
cout<<"value of x is : "<<a.x;
}
};
int main()
{
A a;
B b;
b.display(a);
return 0;
}

2.5 C++ héritage


En C++, l’héritage est un processus dans lequel un objet acquiert automatiquement toutes les
propriétés et tous les comportements de son objet parent. De cette manière, vous pouvez réuti-
liser, étendre ou modifier les attributs et comportements définis dans d’autres classes.

En C++, la classe qui hérite des membres d’une autre classe est appelée classe dérivée et la classe
dont les membres sont hérités est appelée classe de base. La classe dérivée est la classe spécialisée
de la classe de base.

Lotfi ELAACHAK Page 27


2.5.1 Types d’héritage
C++ prend en charge cinq types d’héritage :
— Héritage unique
— Héritage multiple
— Héritage hiérarchique
— Héritage à plusieurs niveaux
— Héritage hybride

2.5.2 Héritage unique C++


L’héritage simple est défini comme l’héritage dans lequel une classe dérivée est héritée d’une seule
classe de base.

Héritage simple
#include <iostream>
using namespace std;
class Account {
public:
float salary = 60000;

public:
void getCalc() {
cout<<"calc..."<<endl;
}

};
class Programmer: public Account {
public:
float bonus = 5000;
};
int main(void) {
Programmer p1;
cout<<"Salary: "<<p1.salary<<endl;
cout<<"Bonus: "<<p1.bonus<<endl;
p1.getCalc();
return 0;
}

Lotfi ELAACHAK Page 28


Comment rendre un membre privé héritable

Le membre privé n’est pas héritable. Si on modifie le mode de visibilité en le rendant public,
mais cela enlève l’avantage du masquage des données.

C++ introduit un troisième modificateur de visibilité, c’est-à-dire protégé. Le membre déclaré


protégé sera accessible à toutes les fonctions membres de la classe ainsi qu’à la classe qui en
dérive immédiatement.

Les modes de visibilité peuvent être classés en trois catégories :

— Public : Lorsque le membre est déclaré public, il est accessible à toutes les fonctions du
programme.
— Private : lorsque le membre est déclaré comme privé, il est accessible uniquement au sein
de la classe.
— Protected : lorsque le membre est déclaré protégé, il est accessible au sein de sa propre
classe ainsi que de la classe qui en dérive immédiatement.

2.5.3 Héritage multiple


L’héritage multiple est le processus de dérivation d’une nouvelle classe qui hérite des attributs
de deux ou plusieurs classes.

Lotfi ELAACHAK Page 29


Héritage multiple
#include <iostream>
using namespace std;
class A
{
protected:
int a;
public:
void get_a(int n)
{
a = n;
}
};

class B
{
protected:
int b;
public:
void get_b(int n)
{
b = n;
}
};
class C : public A,public B
{
public:
void display()
{
std::cout << "The value of a is : " <<a<< std::endl;
std::cout << "The value of b is : " <<b<< std::endl;
cout<<"Addition of a and b is : "<<a+b;
}
};
int main()
{
C c;
c.get_a(10);
c.get_b(20);
c.display();

return 0;
}

Lotfi ELAACHAK Page 30


Résolution d’ambiquité dans l’héritage

Une ambiguïté peut survenir lors de l’utilisation de l’héritage multiple lorsqu’une fonction portant
le même nom apparaît dans plusieurs classes de base.
Héritage multiple
#include <iostream>
using namespace std;
class A
{
public:
void display()
{
std::cout << "Class A" << std::endl;
}
};
class B
{
public:
void display()
{
std::cout << "Class B" << std::endl;
}
};
class C : public A, public B
{
public :
void view()
{
display();
}
};
int main()
{
C c;
c.view();
return 0;
}

Le problème ci-dessus peut être résolu en utilisant l’opérateur de résolution de classe avec la
fonction. Dans l’exemple ci-dessus, le code de classe dérivé peut être réécrit comme :
Héritage multiple
#include <iostream>
using namespace std;
class A
{
public:

Lotfi ELAACHAK Page 31


void display()
{
std::cout << "Class A" << std::endl;
}
};
class B
{
public:
void display()
{
std::cout << "Class B" << std::endl;
}
};
class C : public A, public B
{
public :
void view()
{
A :: display(); // Calling the display() function of class A.
B :: display(); // Calling the display() function of class B.

}
};
int main()
{
C c;
c.view();
return 0;
}

2.6 C++ Polymorphisme


Le terme « polymorphisme » est la combinaison de « poly » + « morphes » qui signifie de nom-
breuses formes. C’est un mot grec. En programmation orientée objet, nous utilisons 3 concepts
principaux : l’héritage, l’encapsulation et le polymorphisme.

Considérons un exemple réel de polymorphisme. Une dame se comporte comme une enseignante
dans une salle de classe, une mère ou une fille dans une maison et une cliente dans un marché.
Ici, une seule personne se comporte différemment selon les situations.

Il existe deux types de polymorphisme en C++ :

Lotfi ELAACHAK Page 32


2.6.1 Polymorphisme au moment de la compilation
Les fonctions surchargées sont invoquées en faisant correspondre le type et le nombre d’arguments.
Ces informations sont disponibles au moment de la compilation et, par conséquent, le compilateur
sélectionne la fonction appropriée au moment de la compilation. Il est obtenu par une surcharge
de fonction et une surcharge d’opérateur, également appelée liaison statique ou liaison anticipée.
Considérons maintenant le cas où le nom de la fonction et le prototype sont identiques.

2.6.2 Polymorphisme d’exécution

Polymorphisme
class A // base class declaration.
{
int a;
public:
void display()
{
cout<< "Class A ";
}
};
class B : public A // derived class declaration.
{
int b;
public:
void display()
{
cout<<"Class B";
}
};

Dans le cas ci-dessus, le prototype de la fonction display() est le même dans la classe de base
et la classe dérivée. Par conséquent, la liaison statique ne peut pas être appliquée. Ce serait

Lotfi ELAACHAK Page 33


formidable si la fonction appropriée est sélectionnée au moment de l’exécution. C’est ce qu’on
appelle le polymorphisme à l’exécution.

Le polymorphisme à l’exécution est obtenu lorsque la méthode de l’objet est invoquée au moment
de l’exécution au lieu de la compilation. Il est obtenu par substitution de méthode, également
appelée liaison dynamique ou liaison tardive.

2.6.3 Surcharge Fonction et opérateur


Si nous créons deux membres ou plus ayant le même nom mais différents en nombre ou en type
de paramètre, on parle de surcharge C++. En C++, on peut surcharger :
— méthodes.
— constructeurs.
— propriétés indexées.
C’est parce que ces membres n’ont que des paramètres.
Les types de surcharge en C++ sont :
— Surcharge de fonction
— Surcharge d’opérateur

Surcharge de fonction C++

La surcharge de fonction est définie comme le processus consistant à avoir deux fonctions ou
plus avec le même nom, mais différents dans les paramètres est connu sous le nom de surcharge
de fonction en C++. Dans la surcharge de fonction, la fonction est redéfinie en utilisant soit
différents types d’arguments, soit un nombre différent d’arguments. Ce n’est que grâce à ces
différences que le compilateur peut différencier les fonctions.

L’avantage de la surcharge de fonction est qu’elle augmente la lisibilité du programme car vous
n’avez pas besoin d’utiliser des noms différents pour la même action.
Surcharge Fonction

#include <iostream>
using namespace std;
class Cal {
public:
static int add(int a,int b){
return a + b;
}
static int add(int a, int b, int c)
{
return a + b + c;
}
};
int main(void) {
Cal C; // class object
declaration.
cout<<C.add(10, 20)<<endl;
cout<<C.add(12, 20, 23);

Lotfi ELAACHAK Page 34


return 0;
}

Surcharge des opérateurs C++

La surcharge d’opérateur est un polymorphisme au moment de la compilation dans lequel l’opé-


rateur est surchargé pour fournir une signification particulière au type de données défini par
l’utilisateur. La surcharge d’opérateurs est utilisée pour surcharger ou redéfinir la plupart des
opérateurs disponibles en C++. Il est utilisé pour effectuer l’opération sur le type de données
défini par l’utilisateur. Par exemple, C++ offre la possibilité d’ajouter les variables du type de
données défini par l’utilisateur qui est appliqué aux types de données intégrés.

L’avantage de la surcharge d’opérateurs est d’effectuer différentes opérations sur le même opé-
rande.

Les opérateurs qui ne peuvent pas être surchargés sont les suivants :
— Opérateur de portée ( : :)
— Taille de sélecteur de membres(.)
— Sélecteur de pointeur (*)
— Opérateur ternaire ( ? :)

Exemple 1

Surcharge operator ++
#include <iostream>
using namespace std;
class Test
{
private:
int num;
public:
Test(): num(8){}
void operator ++() {
num = num+2;
}
void Print() {
cout<<"The Count is: "<<num;
}
};
int main()
{
Test tt;
++tt; // calling of a function "void operator ++()"
tt.Print();
return 0;
}

Lotfi ELAACHAK Page 35


Exemple 2

Surcharge operator +
#include <iostream>
using namespace std;
class A
{

int x;
public:
A(){}
A(int i)
{
x=i;
}
void operator+(A);
void display();
};

void A :: operator+(A a)
{

int m = x+a.x;
cout<<"The result of the addition of two objects is : "<<m;

}
int main()
{
A a1(5);
A a2(4);
a1+a2;
return 0;
}

2.6.4 Redéfinition
Si la classe dérivée définit la même fonction que celle définie dans sa classe de base, elle est appelée
fonction de substitution en C++. Il est utilisé pour réaliser le polymorphisme d’exécution. Il vous
permet de fournir une implémentation spécifique de la fonction qui est déjà fournie par sa classe
de base.
Redéfinition
#include <iostream>
using namespace std;
class Animal {
public:

Lotfi ELAACHAK Page 36


void eat(){
cout<<"Eating...";
}
};
class Dog: public Animal
{
public:
void eat()
{
cout<<"Eating bread...";
}
};
int main(void) {
Dog d = Dog();
d.eat();
return 0;
}

2.6.5 Virtual
Une fonction virtuelle C++ est une fonction membre de la classe de base que vous redéfinissez
dans une classe dérivée. Il est déclaré à l’aide du mot-clé virtual.
Il est utilisé pour indiquer au compilateur d’effectuer une liaison dynamique ou une liaison tar-
dive sur la fonction. Il est nécessaire d’utiliser le pointeur unique pour désigner tous les objets
des différentes classes. Ainsi, nous créons le pointeur vers la classe de base qui fait référence à
tous les objets dérivés. Mais, lorsque le pointeur de classe de base contient l’adresse de l’objet
de classe dérivée, exécute toujours la fonction de classe de base. Ce problème ne peut être résolu
qu’en utilisant la fonction « virtuelle ».
Un ’virtuel’ est un mot-clé précédant la déclaration normale d’une fonction.
Lorsque la fonction est rendue virtuelle, C++ détermine quelle fonction doit être appelée au
moment de l’exécution en fonction du type de l’objet pointé par le pointeur de la classe de base.

Liaison tardive ou liaison dynamique

En cas de liaison tardive, l’appel de fonction est résolu pendant l’exécution. Par conséquent, le
compilateur détermine le type d’objet au moment de l’exécution, puis lie l’appel de fonction.

Règles de la fonction virtuelle

— Les fonctions virtuelles doivent être membres d’une classe.


— Les fonctions virtuelles ne peuvent pas être des membres statiques.
— Ils sont accessibles via des pointeurs d’objets.
— Ils peuvent être amis d’une autre classe.
— Une fonction virtuelle doit être définie dans la classe de base, même si elle n’est pas utilisée.
— Les prototypes d’une fonction virtuelle de la classe de base et de toutes les classes déri-
vées doivent être identiques. Si les deux fonctions ont le même nom mais des prototypes
différents, C++ les considérera comme les fonctions surchargées.

Lotfi ELAACHAK Page 37


— Nous ne pouvons pas avoir de constructeur virtuel, mais nous pouvons avoir un destructeur
virtuel
— Considérez la situation lorsque nous n’utilisons pas le mot-clé virtual.

Probelem

Probleme sans virtual


#include <iostream>
using namespace std;
class A
{
int x=5;
public:
void display()
{
std::cout << "Value of x is : " << x<<std::endl;
}
};
class B: public A
{
int y = 10;
public:
void display()
{
std::cout << "Value of y is : " <<y<< std::endl;
}
};
int main()
{
A *a;
B b;
a = &b;
a->display();
return 0;
}

Solution

Solution avec virtual


#include <iostream>
{
public:
virtual void display()
{
cout << "Base class is invoked"<<endl;
}

Lotfi ELAACHAK Page 38


};
class B:public A
{
public:
void display()
{
cout << "Derived Class is invoked"<<endl;
}
};
int main()
{
A* a; //pointer of base class
B b; //object of derived class
a = &b;
a->display(); //Late Binding occurs
}

2.6.6 Fonction virtuelle pure et C++ Abstraction


Fonction virtuelle pure

— Une fonction virtuelle n’est pas utilisée pour effectuer une tâche. Il sert uniquement d’es-
pace réservé.
— Lorsque la fonction n’a pas de définition, cette fonction est appelée fonction "ne rien faire".
— La fonction "ne rien faire" est connue comme une fonction virtuelle pure. Une fonction
virtuelle pure est une fonction déclarée dans la classe de base qui n’a pas de définition
relative à la classe de base.
— Une classe contenant la fonction virtuelle pure ne peut pas être utilisée pour déclarer ses
propres objets, de telles classes sont appelées classes de base abstraites.
— L’objectif principal de la classe de base est de fournir les traits aux classes dérivées et de
créer le pointeur de base utilisé pour réaliser le polymorphisme d’exécution.
Pure Virtual
#include <iostream>
using namespace std;
class Base
{
public:
virtual void show() = 0;
};
class Derived : public Base
{
public:
void show()
{
std::cout << "Derived class is derived from the base class." << std::endl;
}
};

Lotfi ELAACHAK Page 39


int main()
{
Base *bptr;
//Base b;
Derived d;
bptr = &d;
bptr->show();
return 0;
}

C++ Abstraction

Les classes abstraites sont le moyen d’atteindre l’abstraction en C++. L’abstraction en C++ est
le processus permettant de masquer les détails internes et d’afficher uniquement les fonctionna-
lités.

dans la classe C++ est rendu abstrait en déclarant au moins une de ses fonctions en tant que
<>strong>fonction virtuelle pure. Une fonction virtuelle pure est spécifiée en plaçant "= 0" dans
sa déclaration. Son implémentation doit être fournie par des classes dérivées.
Abstarct
#include <iostream>
using namespace std;
class Shape
{
public:
virtual void draw()=0;
};
class Rectangle : Shape
{
public:
void draw()
{
cout < <"drawing rectangle..." < <endl;
}
};
class Circle : Shape
{
public:
void draw()
{
cout <<"drawing circle..." < <endl;
}
};
int main( ) {
Rectangle rec;
Circle cir;

Lotfi ELAACHAK Page 40


rec.draw();
cir.draw();
return 0;
}

2.7 C++ Exceptions


La gestion des exceptions en C++ est un processus permettant de gérer les erreurs d’exécution.
Nous effectuons la gestion des exceptions afin que le flux normal de l’application puisse être
maintenu même après des erreurs d’exécution.

En C++, une exception est un événement ou un objet qui est levé au moment de l’exécution.
Toutes les exceptions sont dérivées de la classe std : :exception. Il s’agit d’une erreur d’exécution
qui peut être gérée. Si nous ne gérons pas l’exception, il imprime un message d’exception et
termine le programme.

2.7.1 C++ Exception Classes


Dans la norme C++, les exceptions sont définies dans la classe <exception> que nous pouvons
utiliser dans nos programmes. L’arrangement de la hiérarchie des classes parent-enfant est illustré
ci-dessous :

Lotfi ELAACHAK Page 41


2.7.2 C++ try/catch
En programmation C++, la gestion des exceptions est effectuée à l’aide de l’instruction try/catch.
Le bloc try C++ est utilisé pour placer le code qui peut se produire exception. Le bloc catch est
utilisé pour gérer l’exception.

Exemple sans try/catch

no try catch
#include <iostream>
using namespace std;
float division(int x, int y) {
return (x/y);
}
int main () {
int i = 50;
int j = 0;
float k = 0;
k = division(i, j);
cout << k << endl;
return 0;
}

Exemple avec try/catch

try catch
#include <iostream>
using namespace std;
float division(int x, int y) {
if( y == 0 ) {
throw "Attempted to divide by zero!";
}
return (x/y);
}
int main () {
int i = 25;
int j = 0;
float k = 0;
try {
k = division(i, j);
cout << k << endl;
}catch (const char* e) {
cerr << e << endl;
}
return 0;
}

Lotfi ELAACHAK Page 42


2.7.3 Exceptions personnalisées
La nouvelle exception peut être définie en remplaçant et en héritant de la fonctionnalité de classe
d’exception.
Exception
#include <iostream>
#include <exception>
using namespace std;

class MyException : public exception{


public:
const char * what() const throw()
{
return "Attempted to divide by zero!\n";
}
};

int main()
{
try
{
int x, y;
cout << "Enter the two numbers : \n";
cin >> x >> y;
if (y == 0)
{
MyException z;
throw z;
}
else
{
cout << "x / y = " << ((float) x/y) << endl;
}
}
catch(exception& e)
{
cout << e.what();
}
}

2.8 C++ Templates


Une template C++ est une fonctionnalité puissante ajoutée au C++. Il permet de définir les
classes génériques et les fonctions génériques et fournit ainsi un support pour la programmation

Lotfi ELAACHAK Page 43


générique. La programmation générique est une technique où les types génériques sont utilisés
comme paramètres dans les algorithmes afin qu’ils puissent fonctionner pour une variété de types
de données.

Les templates peuvent être représentés de deux manières :


— template de fonction
— template de classe

2.8.1 template de fonction


— Les fonctions génériques utilisent le concept de template de fonction. Les fonctions gé-
nériques définissent un ensemble d’opérations qui peuvent être appliquées aux différents
types de données.
— Le type des données sur lesquelles la fonction opérera dépend du type des données passées
en paramètre.
— Par exemple, l’algorithme de tri rapide est implémenté à l’aide d’une fonction générique,
il peut être implémenté dans un tableau d’entiers ou un tableau de flottants.
— Une fonction générique est créée à l’aide du template de mot-clé. Le template définit ce
que la fonction fera.

Syntaxe du template de fonction

Template function
#include <iostream>
using namespace std;
template<class T> T add(T &a,T &b)
{
T result = a+b;
return result;

}
int main()
{
int i =2;
int j =3;
float m = 2.3;
float n = 1.2;
cout<<"Addition of i and j is :"<<add(i,j);
cout<<'\n';
cout<<"Addition of m and n is :"<<add(m,n);
return 0;
}

Templates de fonction avec plusieurs paramètres

Template function

Lotfi ELAACHAK Page 44


#include <iostream>
using namespace std;
template<class X,class Y> void fun(X a,Y b)
{
std::cout << "Value of a is : " <<a<< std::endl;
std::cout << "Value of b is : " <<b<< std::endl;
}

int main()
{
fun(15,12.3);

return 0;
}

2.8.2 Template de class


Le modèle de classe peut également être défini de la même manière que le modèle de fonction.
Lorsqu’une classe utilise le concept de modèle, alors la classe est appelée classe générique.
Template Classe
#include <iostream>
using namespace std;
template<class T>
class A
{
public:
T num1 = 5;
T num2 = 6;
void add()
{
std::cout << "Addition of num1 and num2 : " << num1+num2<<std::endl;
}

};

int main()
{
A<int> d;
d.add();
return 0;
}

Template Classe Multiparamètres


#include <iostream>
using namespace std;

Lotfi ELAACHAK Page 45


template<class T1, class T2>
class A
{
T1 a;
T2 b;
public:
A(T1 x,T2 y)
{
a = x;
b = y;
}
void display()
{
std::cout << "Values of a and b are : " << a<<" ,"<<b<<std::endl;
}
};

int main()
{
A<int,float> d(5,6.5);
d.display();
return 0;
}

2.9 C++ STL

2.9.1 Les conteneurs STL


Les conteneurs peuvent être décrits comme les objets qui contiennent les données du même type.
Les conteneurs sont utilisés pour implémenter différentes structures de données, par exemple des
tableaux, des listes, des arbres, etc.

Classement des conteneurs :


— Conteneurs de séquence
— Conteneurs associatifs
— Conteneurs dérivés

Lotfi ELAACHAK Page 46


2.9.2 Les Vecteurs
Un vecteur est une classe conteneur de séquences qui implémente un tableau dynamique, ce qui
signifie que la taille change automatiquement lors de l’ajout d’éléments. Un vecteur stocke les
éléments dans des emplacements de mémoire contigus et alloue la mémoire selon les besoins au
moment de l’exécution.

Un tableau suit une approche statique, cela signifie que sa taille ne peut pas être modifiée pendant
l’exécution tandis que le vecteur implémente un tableau signifie qu’il se redimensionne automa-
tiquement lors de l’ajout d’éléments.

Certaines fonctions associées au vecteur sont :


Itérateurs
— begin() – Renvoie un itérateur pointant sur le premier élément du vecteur end() – Renvoie
un itérateur pointant sur l’élément théorique qui suit le dernier élément du vecteur
— rbegin() – Renvoie un itérateur inverse pointant sur le dernier élément du vecteur (début
inverse). Il passe du dernier au premier élément
— rend() – Renvoie un itérateur inverse pointant sur l’élément théorique précédant le premier
élément du vecteur (considéré comme la fin inverse)
— cbegin() – Renvoie un itérateur constant pointant sur le premier élément du vecteur.
— cend() – Renvoie un itérateur constant pointant sur l’élément théorique qui suit le dernier
élément du vecteur.
— crbegin() – Renvoie un itérateur inverse constant pointant sur le dernier élément du vecteur
(début inverse). Il passe du dernier au premier élément
— crend() – Renvoie un itérateur inverse constant pointant sur l’élément théorique précédant
le premier élément du vecteur (considéré comme une extrémité inverse)
Vector
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<string> v1;
v1.push_back("javaTpoint ");
v1.push_back("tutorial");
for(vector<string>::iterator itr=v1.begin();itr!=v1.end();++itr)
cout<<*itr;
return 0;
}

Intialiser un vecteur

Vector
#include <iostream>
#include <vector>
using namespace std;
int main()

Lotfi ELAACHAK Page 47


{
vector<int> vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
vec.push_back(4);
vec.push_back(5);
vec.push_back(6);
vec.push_back(7);
vec.push_back(8);
vec.push_back(9);
vec.push_back(101);
for (int i = 0; i < vec.size(); i++)
{
cout << vec[i] << " ";
}
return 0;
}

Vector
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> vectr{9,8,7,6,5,4,3,2,1,0};
for (int i = 0; i < vectr.size(); i++)
{
cout << vectr[i] << " \n";
}
return 0;
}

2.9.3 Les Listes


— List est un conteneur contigu tandis que vector est un conteneur non contigu, c’est-à-dire
que la liste stocke les éléments sur une mémoire contiguë et vector stocke sur une mémoire
non contiguë.
— L’insertion et la suppression au milieu du vecteur sont très coûteuses car cela prend beau-
coup de temps pour déplacer tous les éléments. Linklist surmonte ce problème et est
implémenté à l’aide d’un conteneur de liste.
— List prend en charge un bidirectionnel et fournit un moyen efficace pour les opérations
d’insertion et de suppression.

Lotfi ELAACHAK Page 48


— Le parcours est lent dans la liste car les éléments de la liste sont accessibles de manière
séquentielle tandis que le vecteur prend en charge un accès aléatoire.

Exemple

List
#include <iostream>
#include <list>
#include <iterator>
using namespace std;

//function for printing the elements in a list


void showlist(list <int> g)
{
list <int> :: iterator it;
for(it = g.begin(); it != g.end(); ++it)
cout << '\t' << *it;
cout << '\n';
}

int main()
{

list <int> gqlist1, gqlist2;

for (int i = 0; i < 10; ++i)


{
gqlist1.push_back(i * 2);
gqlist2.push_front(i * 3);
}
cout << "\nList 1 (gqlist1) is : ";
showlist(gqlist1);

cout << "\nList 2 (gqlist2) is : ";


showlist(gqlist2);

cout << "\ngqlist1.front() : " << gqlist1.front();


cout << "\ngqlist1.back() : " << gqlist1.back();

cout << "\ngqlist1.pop_front() : ";


gqlist1.pop_front();
showlist(gqlist1);

cout << "\ngqlist2.pop_back() : ";


gqlist2.pop_back();

Lotfi ELAACHAK Page 49


showlist(gqlist2);

cout << "\ngqlist1.reverse() : ";


gqlist1.reverse();
showlist(gqlist1);

cout << "\ngqlist2.sort(): ";


gqlist2.sort();
showlist(gqlist2);

return 0;

List Personnes
#include <iostream>
#include <list>
using namespace std;

class Personne {
public :
string nom;
int age ;

public :
Personne(string nom , int age ){

this->nom = nom ;
this->age = age;
}

};

int main()
{
list<Personne> data;
data.push_back(Personne("toto" , 12 ));
data.push_back(Personne("tota" , 12 ));

std::list<Personne>::iterator it;
for (it = data.begin(); it != data.end(); ++it){
std::cout << it->nom;
}

Lotfi ELAACHAK Page 50


return 0;
}

2.9.4 Les Sets


Les Sets sont un type de conteneurs associatifs dans lesquels chaque élément doit être unique,
car la valeur de l’élément l’identifie. La valeur de l’élément ne peut pas être modifiée une fois
qu’il est ajouté à l’ensemble, bien qu’il soit possible de supprimer et d’ajouter la valeur modifiée
de cet élément. Quelques fonctions de base associées à Set :
— begin() – Renvoie un itérateur au premier élément de l’ensemble.
— end() – Renvoie un itérateur à l’élément théorique qui suit le dernier élément de l’ensemble.
— size() – Renvoie le nombre d’éléments dans l’ensemble.
— max_size() – Renvoie le nombre maximum d’éléments que l’ensemble peut contenir.
— empty() – Retourne si l’ensemble est vide.
Set
#include <iostream>
#include <iterator>
#include <set>

using namespace std;

int main()
{
// empty set container
set<int, greater<int> > s1;

// insert elements in random order


s1.insert(40);
s1.insert(30);
s1.insert(60);
s1.insert(20);
s1.insert(50);

// only one 50 will be added to the set


s1.insert(50);
s1.insert(10);

// printing set s1
set<int, greater<int> >::iterator itr;
cout << "\nThe set s1 is : \n";
for (itr = s1.begin(); itr != s1.end(); itr++)
{
cout << *itr<<" ";
}

Lotfi ELAACHAK Page 51


cout << endl;

// assigning the elements from s1 to s2


set<int> s2(s1.begin(), s1.end());

// print all elements of the set s2


cout << "\nThe set s2 after assign from s1 is : \n";
for (itr = s2.begin(); itr != s2.end(); itr++)
{
cout << *itr<<" ";
}
cout << endl;

// remove all elements up to 30 in s2


cout
<< "\ns2 after removal of elements less than 30 :\n";
s2.erase(s2.begin(), s2.find(30));
for (itr = s2.begin(); itr != s2.end(); itr++) {
cout <<*itr<<" ";
}

// remove element with value 50 in s2


int num;
num = s2.erase(50);
cout << "\ns2.erase(50) : ";
cout << num << " removed\n";
for (itr = s2.begin(); itr != s2.end(); itr++)
{
cout <<*itr<<" ";
}

cout << endl;

// lower bound and upper bound for set s1


cout << "s1.lower_bound(40) : \n"
<< *s1.lower_bound(40)
<< endl;
cout << "s1.upper_bound(40) : \n"
<< *s1.upper_bound(40)
<< endl;

// lower bound and upper bound for set s2


cout << "s2.lower_bound(40) :\n"
<< *s2.lower_bound(40)
<< endl;
cout << "s2.upper_bound(40) : \n"

Lotfi ELAACHAK Page 52


<< *s2.upper_bound(40)
<< endl;

return 0;
}

2.9.5 Les Maps


Les maps sont des conteneurs associatifs qui stockent des éléments de manière mappée. Chaque
élément a une valeur clé et une valeur mappée. Deux valeurs mappées ne peuvent pas avoir les
mêmes valeurs de clé.

Quelques fonctions de base associées à Map :


— begin() – Renvoie un itérateur au premier élément de la carte
— end() – Renvoie un itérateur à l’élément théorique qui suit le dernier élément de la carte
— size() – Renvoie le nombre d’éléments dans la carte
— max_size() – Renvoie le nombre maximum d’éléments que la carte peut contenir
— empty() – Retourne si la carte est vide
— pair insert(keyvalue, mapvalue) – Ajoute un nouvel élément à la carte
— erase(iterator position)- Supprime l’élément à la position pointée par l’itérateur
— erase (const g) - Supprime la valeur de la clé ’g’ de la carte
— clear() – Supprime tous les éléments de la carte
Map
#include <iostream>
#include <iterator>
#include <map>

using namespace std;

int main()
{

// empty map container


map<int, int> gquiz1;

// insert elements in random order


gquiz1.insert(pair<int, int>(1, 40));
gquiz1.insert(pair<int, int>(2, 30));
gquiz1.insert(pair<int, int>(3, 60));
gquiz1.insert(pair<int, int>(4, 20));
gquiz1.insert(pair<int, int>(5, 50));
gquiz1.insert(pair<int, int>(6, 50));
gquiz1.insert(pair<int, int>(7, 10));

// printing map gquiz1


map<int, int>::iterator itr;

Lotfi ELAACHAK Page 53


cout << "\nThe map gquiz1 is : \n";
cout << "\tKEY\tELEMENT\n";
for (itr = gquiz1.begin(); itr != gquiz1.end(); ++itr) {
cout << '\t' << itr->first
<< '\t' << itr->second << '\n';
}
cout << endl;

// assigning the elements from gquiz1 to gquiz2


map<int, int> gquiz2(gquiz1.begin(), gquiz1.end());

// print all elements of the map gquiz2


cout << "\nThe map gquiz2 after"
<< " assign from gquiz1 is : \n";
cout << "\tKEY\tELEMENT\n";
for (itr = gquiz2.begin(); itr != gquiz2.end(); ++itr) {
cout << '\t' << itr->first
<< '\t' << itr->second << '\n';
}
cout << endl;

// remove all elements up to


// element with key=3 in gquiz2
cout << "\ngquiz2 after removal of"
" elements less than key=3 : \n";
cout << "\tKEY\tELEMENT\n";
gquiz2.erase(gquiz2.begin(), gquiz2.find(3));
for (itr = gquiz2.begin(); itr != gquiz2.end(); ++itr) {
cout << '\t' << itr->first
<< '\t' << itr->second << '\n';
}

// remove all elements with key = 4


int num;
num = gquiz2.erase(4);
cout << "\ngquiz2.erase(4) : ";
cout << num << " removed \n";
cout << "\tKEY\tELEMENT\n";
for (itr = gquiz2.begin(); itr != gquiz2.end(); ++itr) {
cout << '\t' << itr->first
<< '\t' << itr->second << '\n';
}

cout << endl;

// lower bound and upper bound for map gquiz1 key = 5

Lotfi ELAACHAK Page 54


cout << "gquiz1.lower_bound(5) : "
<< "\tKEY = ";
cout << gquiz1.lower_bound(5)->first << '\t';
cout << "\tELEMENT = "
<< gquiz1.lower_bound(5)->second << endl;
cout << "gquiz1.upper_bound(5) : "
<< "\tKEY = ";
cout << gquiz1.upper_bound(5)->first << '\t';
cout << "\tELEMENT = "
<< gquiz1.upper_bound(5)->second << endl;

return 0;
}

Lotfi ELAACHAK Page 55


Chapitre 3
La programmation POO : Python
3.1 Introduction
Comme d’autres langages de programmation à usage général, Python est également un langage
orienté objet depuis ses débuts. Il nous permet de développer des applications en utilisant une
approche orientée objet. En Python, nous pouvons facilement créer et utiliser des classes et des
objets.

Un paradigme orienté objet consiste à concevoir le programme en utilisant des classes et des
objets. L’objet est lié à des entités de mots réels telles que livre, maison, crayon, etc. Le concept
oops se concentre sur l’écriture du code réutilisable. C’est une technique très répandue pour ré-
soudre le problème en créant des objets.

Les principes majeurs du système de programmation orienté objet sont donnés ci-dessous.
— Classe
— Objet
— Héritage
— Polymorphisme
— Encapsulation

3.2 Python Classe et Objets

3.2.1 Class
La classe peut être définie comme une collection d’objets. C’est une entité logique qui a des
attributs et des méthodes spécifiques. Par exemple : si vous avez une classe d’employés, elle doit
contenir un attribut et une méthode, c’est-à-dire un identifiant de messagerie, un nom, un âge,
un salaire, etc.
Class
class car:
def __init__(self,modelname, year):
self.modelname = modelname
self.year = year
def display(self):
print(self.modelname,self.year)

3.2.2 Objets
L’objet est une entité qui a un état et un comportement. Il peut s’agir de n’importe quel objet
du monde réel comme la souris, le clavier, la chaise, la table, le stylo, etc.

56
Tout en Python est un objet, et presque tout a des attributs et des méthodes. Toutes les fonctions
ont un attribut intégré , qui renvoie la docstring définie dans le code source de la fonction.
Class
class car:
def __init__(self,modelname, year):
self.modelname = modelname
self.year = year
def display(self):
print(self.modelname,self.year)

c1 = car("Toyota", 2016)
c1.display()

3.2.3 Constructeur Python


Un constructeur est un type spécial de méthode (fonction) qui est utilisé pour initialiser les
membres d’instance de la classe.

En C++ ou Java, le constructeur a le même nom que sa classe, mais il traite le constructeur
différemment en Python. Il est utilisé pour créer un objet.

Les constructeurs peuvent être de deux types.


— Constructeur paramétré
— Constructeur non paramétré

La définition du constructeur est exécutée lorsque nous créons l’objet de cette classe. Les construc-
teurs vérifient également qu’il y a suffisamment de ressources pour que l’objet effectue une tâche
de démarrage.
Constructeur parametre
class Employee:
def __init__(self, name, id):
self.id = id
self.name = name

def display(self):
print("ID: %d \nName: %s" % (self.id, self.name))

emp1 = Employee("John", 101)


emp2 = Employee("David", 102)

# accessing display() method to print employee 1 information

emp1.display()

# accessing display() method to print employee 2 information

Lotfi ELAACHAK Page 57


emp2.display()

Constructeur non parametre


class Employee:
class Student:
# Constructor - non parameterized
def __init__(self):
print("This is non parametrized constructor")
def show(self,name):
print("Hello",name)
student = Student()
student.show("John")

3.3 Python héritage


L’héritage est un aspect important du paradigme orienté objet. L’héritage permet la réutilisation
du code au programme car nous pouvons utiliser une classe existante pour créer une nouvelle
classe au lieu de la créer à partir de zéro.

3.3.1 Héritage simple

héritage simple
class Animal:
def speak(self):
print("Animal Speaking")
#child class Dog inherits the base class Animal
class Dog(Animal):
def bark(self):
print("dog barking")
d = Dog()
d.bark()
d.speak()

3.3.2 Héritage multiple

héritage simple
class Calculation1:
def Summation(self,a,b):
return a+b;
class Calculation2:
def Multiplication(self,a,b):
return a*b;
class Derived(Calculation1,Calculation2):
def Divide(self,a,b):

Lotfi ELAACHAK Page 58


return a/b;
d = Derived()
print(d.Summation(10,20))
print(d.Multiplication(10,20))
print(d.Divide(10,20))

3.3.3 La méthode issubclass(sub,sup)


La méthode issubclass(sub, sup) est utilisée pour vérifier les relations entre les classes spécifiées.
Elle renvoie true si la première classe est la sous-classe de la deuxième classe et false dans le cas
contraire.
issubclass
class Calculation1:
def Summation(self,a,b):
return a+b;
class Calculation2:
def Multiplication(self,a,b):
return a*b;
class Derived(Calculation1,Calculation2):
def Divide(self,a,b):
return a/b;
d = Derived()
print(issubclass(Derived,Calculation2))
print(issubclass(Calculation1,Calculation2))

3.3.4 La méthode isinstance (obj, class)


La méthode isinstance() est utilisée pour vérifier la relation entre les objets et les classes. Il renvoie
vrai si le premier paramètre, c’est-à-dire obj est l’instance du deuxième paramètre, c’est-à-dire
la classe.
isinstance
class Calculation1:
def Summation(self,a,b):
return a+b;
class Calculation2:
def Multiplication(self,a,b):
return a*b;
class Derived(Calculation1,Calculation2):
def Divide(self,a,b):
return a/b;
d = Derived()
print(isinstance(d,Derived))

Lotfi ELAACHAK Page 59


3.3.5 Redéfinition de la méthode
Nous pouvons fournir une implémentation spécifique de la méthode de la classe parente dans
notre classe enfant. Lorsque la méthode de la classe parente est définie dans la classe enfant avec
une implémentation spécifique, le concept est appelé substitution de méthode. Nous pouvons
avoir besoin d’effectuer une substitution de méthode dans le scénario où la définition différente
d’une méthode de classe parent est nécessaire dans la classe enfant.
Redéfinition
class Bank:
def getroi(self):
return 10;
class SBI(Bank):
def getroi(self):
return 7;

class ICICI(Bank):
def getroi(self):
return 8;
b1 = Bank()
b2 = SBI()
b3 = ICICI()
print("Bank Rate of interest:",b1.getroi());
print("SBI Rate of interest:",b2.getroi());
print("ICICI Rate of interest:",b3.getroi());

3.3.6 Abstraction
L’abstraction est utilisée pour masquer la fonctionnalité interne de la fonction aux utilisateurs.
Les utilisateurs n’interagissent qu’avec l’implémentation de base de la fonction, mais le fonction-
nement interne est caché. L’utilisateur est familier avec "ce que fait la fonction" mais il ne sait
pas "comment il le fait".
En termes simples, nous utilisons tous le smartphone et connaissons très bien ses fonctions telles
que l’appareil photo, l’enregistreur vocal, la numérotation des appels, etc., mais nous ne savons
pas comment ces opérations se déroulent en arrière-plan. Prenons un autre exemple - Lorsque
nous utilisons la télécommande du téléviseur pour augmenter le volume. Nous ne savons pas
comment appuyer sur une touche augmente le volume du téléviseur. On sait seulement appuyer
sur le bouton "+" pour augmenter le volume.
Abstraction
# Python program demonstrate
# abstract base class work
from abc import ABC, abstractmethod
class Car(ABC):
def mileage(self):
pass

class Tesla(Car):

Lotfi ELAACHAK Page 60


def mileage(self):
print("The mileage is 30kmph")
class Suzuki(Car):
def mileage(self):
print("The mileage is 25kmph ")
class Duster(Car):
def mileage(self):
print("The mileage is 24kmph ")

class Renault(Car):
def mileage(self):
print("The mileage is 27kmph ")

# Driver code
t= Tesla ()
t.mileage()

r = Renault()
r.mileage()

s = Suzuki()
s.mileage()
d = Duster()
d.mileage()

Points à retenir

— Une classe abstraite peut contenir à la fois la méthode normale et la méthode abstraite.
— Une classe abstraite ne peut pas être instanciée.
L’abstraction est essentielle pour cacher la fonctionnalité de base aux utilisateurs. Nous avons
couvert tous les concepts de base de l’abstraction en Python.

3.4 Try Except


Une exception peut être définie comme une condition inhabituelle dans un programme entraînant
l’interruption du déroulement du programme.

Chaque fois qu’une exception se produit, le programme arrête l’exécution et le code suivant n’est
donc pas exécuté. Par conséquent, une exception concerne les erreurs d’exécution qui ne peuvent
pas être gérées par le script Python. Une exception est un objet Python qui représente une erreur.

Python fournit un moyen de gérer l’exception afin que le code puisse être exécuté sans aucune
interruption. Si nous ne gérons pas l’exception, l’interpréteur n’exécute pas tout le code qui existe
après l’exception.

Python a de nombreuses exceptions intégrées qui permettent à notre programme de s’exécuter

Lotfi ELAACHAK Page 61


sans interruption et de donner la sortie.

— ZeroDivisionError : se produit lorsqu’un nombre est divisé par zéro.


— NameError : Cela se produit lorsqu’un nom n’est pas trouvé. Il peut être local ou global.
— IndentationError : si une indentation incorrecte est donnée. erreur d’espace
— IOError : Cela se produit lorsque l’opération Input Output échoue.
— EOFError : Cela se produit lorsque la fin du fichier est atteinte, et pourtant des opérations
sont en cours d’exécution.

3.4.1 Le problème sans gérer les exceptions

No Exception
a = int(input("Enter a:"))
b = int(input("Enter b:"))
c = a/b
print("a/b = %d" %c)

#other code:
print("Hi I am other part of the program")

Le programme ci-dessus est syntaxiquement correct, mais il passe par l’erreur en raison d’une
entrée inhabituelle. Ce type de programmation peut ne pas être adapté ou recommandé pour les
projets car ces projets nécessitent une exécution ininterrompue. C’est pourquoi une gestion des
exceptions joue un rôle essentiel dans la gestion de ces exceptions inattendues. Nous pouvons
gérer ces exceptions de la manière suivante.

3.4.2 Gestion des exceptions en python


Si le programme Python contient du code suspect susceptible de lever l’exception, nous devons
placer ce code dans le bloc try. Le bloc try doit être suivi de l’instruction except, qui contient un
bloc de code qui sera exécuté s’il y a une exception dans le bloc try.

Exception
try:
a = int(input("Enter a:"))
b = int(input("Enter b:"))
c = a/b
except:

Lotfi ELAACHAK Page 62


print("Can't divide with zero")

Exception
try:
a = int(input("Enter a:"))
b = int(input("Enter b:"))
c = a/b
print("a/b = %d"%c)
# Using Exception with except statement. If we print(Exception) it will return
exception class
except Exception:
print("can't divide by zero")
print(Exception)
else:
print("Hi I am else block")

Exception
try:
fileptr = open("file2.txt","r")

Lotfi ELAACHAK Page 63


try:
fileptr.write("Hi I am good")
finally:
fileptr.close()
print("file closed")
except:
print("Error")

3.5 Collections

3.5.1 List
Une liste en Python est utilisée pour stocker la séquence de différents types de données. Les
listes Python sont de type mutable, ce qui signifie que nous pouvons modifier son élément après
sa création. Cependant, Python se compose de six types de données capables de stocker les
séquences, mais le type le plus courant et le plus fiable est la liste.
Une liste peut être définie comme une collection de valeurs ou d’éléments de différents types. Les
éléments de la liste sont séparés par la virgule (,) et entourés de crochets [].
List
# Python3 code here creating class
class geeks:
def __init__(self, name, roll):
self.name = name
self.roll = roll

# creating list
list = []

# appending instances to list


list.append( geeks('Akash', 2) )
list.append( geeks('Deependra', 40) )
list.append( geeks('Reaper', 44) )

for obj in list:


print( obj.name, obj.roll, sep =' ' )

Lotfi ELAACHAK Page 64


Indexation et fractionnement des listes

List
list = [1,2,3,4,5]
print(list[-1])
print(list[-3:])
print(list[:-1])
print(list[-3:-1])

3.5.2 Set
Un Set Python est la collection des éléments non ordonnés. Chaque élément de Set doit être
unique, immuable et les Sets suppriment les éléments en double. Les Sets sont mutables, ce qui
signifie que nous pouvons le modifier après sa création.

Contrairement aux autres collections en Python, il n’y a pas d’index attaché aux éléments de Set,
c’est-à-dire que nous ne pouvons accéder directement à aucun élément de l’ensemble par l’index.
Cependant, nous pouvons les imprimer tous Set, ou nous pouvons obtenir la liste des éléments
en parcourant le Set.
Set

Lotfi ELAACHAK Page 65


Days = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday
"}
print(Days)
print(type(Days))
print("looping through the set elements ... ")
for i in Days:
print(i)

Set
Days = set(["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "
Sunday"])
print(Days)
print(type(Days))
print("looping through the set elements ... ")
for i in Days:
print(i)

Elements non dupliqués

Set
set5 = {1,2,4,4,5,8,9,9,10}
print("Return set with unique elements:",set5)

Ajout d’un element

Set
Months = set(["January","February", "March", "April", "May", "June"])
print("\nprinting the original set ... ")
print(months)
print("\nAdding other months to the set...");
Months.add("July");
Months.add ("August");
print("\nPrinting the modified set...");
print(Months)
print("\nlooping through the set elements ... ")
for i in Months:
print(i)

3.5.3 Dictionary
Le dictionnaire Python est utilisé pour stocker les données dans un format de paire clé-valeur.
Le dictionnaire est le type de données en Python, qui peut simuler l’arrangement des données
réelles où une valeur spécifique existe pour une clé particulière. C’est la structure de données
mutables. Le dictionnaire est défini en éléments Clés et valeurs.

Lotfi ELAACHAK Page 66


— Les clés doivent être un seul élément
— La valeur peut être de n’importe quel type tel que liste, tuple, entier, etc.
Dic
Employee = {"Name": "John", "Age": 29, "salary":25000,"Company":"GOOGLE"}
print(type(Employee))
print("printing Employee data .... ")
print("Name : %s" %Employee["Name"])
print("Age : %d" %Employee["Age"])
print("Salary : %d" %Employee["salary"])
print("Company : %s" %Employee["Company"])

Ajout/Modification d’un element

Dic Add
# Creating an empty Dictionary
Dict = {}
print("Empty Dictionary: ")
print(Dict)

# Adding elements to dictionary one at a time


Dict[0] = 'Peter'
Dict[2] = 'Joseph'
Dict[3] = 'Ricky'
print("\nDictionary after adding 3 elements: ")
print(Dict)

# Adding set of values


# with a single Key
# The Emp_ages doesn't exist to dictionary
Dict['Emp_ages'] = 20, 33, 24
print("\nDictionary after adding 3 elements: ")
print(Dict)

# Updating existing Key's Value


Dict[3] = 'JavaTpoint'
print("\nUpdated key value: ")
print(Dict)

Dic Add
Employee = {"Name": "John", "Age": 29, "salary":25000,"Company":"GOOGLE"}
print(type(Employee))
print("printing Employee data .... ")
print(Employee)
print("Enter the details of the new employee....");
Employee["Name"] = "XXX";

Lotfi ELAACHAK Page 67


Employee["Age"] = 12;
Employee["salary"] = 1000;
Employee["Company"] = "Comp";
print("printing the new data");
print(Employee)

Dictionnaire itératif

Dic
Employee = {"Name": "John", "Age": 29, "salary":25000,"Company":"GOOGLE"}
for x in Employee:
print(x)

Employee = {"Name": "John", "Age": 29, "salary":25000,"Company":"GOOGLE"}


for x in Employee:
print(Employee[x])

Employee = {"Name": "John", "Age": 29, "salary":25000,"Company":"GOOGLE"}


for x in Employee.values():
print(x)

Employee = {"Name": "John", "Age": 29, "salary":25000,"Company":"GOOGLE"}


for x in Employee.items():
print(x)

Employee={"Name":"John","Age":29,"Salary":25000,"Company":"GOOGLE","Name":"John"}
for x,y in Employee.items():
print(x,y)

Lotfi ELAACHAK Page 68


Bibliographie
http ://ee402.eeng.dcu.ie/introduction/chapter-1—introduction-to-object-oriented-programming
https ://openclassrooms.com/en/courses/1894236-programmez-avec-le-langage-c
http ://tvaira.free.fr/bts-sn/poo-c++/cours-poo-c++/
https ://openclassrooms.com/fr/courses/4302126-decouvrez-la-programmation-orientee-objet-avec-
python
https ://www.javatpoint.com/python-oops-concepts
https ://www.javatpoint.com/cpp-tutorial

69

Vous aimerez peut-être aussi