Cours Poo
Cours Poo
Cours Poo
C++/Python
2021 — 2022
Table des matières
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
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.
Réutilisation du logiciel : où une application peut être composée de modules existants et nou-
veaux.
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.
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’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.
Pour le programmeur :
— Le programmeur peut modifier l’implémentation, mais n’a pas besoin d’en informer l’uti-
lisateur.
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.
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.
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.
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.
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é.
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
10
— Application de Bureau
— Application client-serveur
— Pilotes de périphérique
— Micrologiciel intégré, Programmation embarquée, etc.
int main(){
cout << "hello word" << endl ;
return 0 ;
}
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.
int main(){
int age;
cout << "Enter your age: ";
cin >> age;
cout << "Your age is: " << age << endl;
return 0 ;
}
int main(){
cout << "C++ Tutorial";
cout << " Javatpoint"<<endl;
cout << "End of line"<<endl;
return 0 ;
}
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
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
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;
}
return 0;
}
void funcvalue(int m)
{
m=8;
}
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.
};
int main()
{
return 0;
}
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 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;
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.
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;
}
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) {
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;
}
};
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;
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.
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()
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;
}
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.
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()
{
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 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()
{
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>
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;
}
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.
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;
}
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.
— 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.
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;
}
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:
}
};
int main()
{
C c;
c.view();
return 0;
}
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.
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
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.
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);
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;
}
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:
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.
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.
Probelem
Solution
— 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;
}
};
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;
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.
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;
}
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;
}
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();
}
}
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;
}
Template function
int main()
{
fun(15,12.3);
return 0;
}
};
int main()
{
A<int> d;
d.add();
return 0;
}
int main()
{
A<int,float> d(5,6.5);
d.display();
return 0;
}
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.
Intialiser un vecteur
Vector
#include <iostream>
#include <vector>
using namespace std;
int main()
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;
}
Exemple
List
#include <iostream>
#include <list>
#include <iterator>
using namespace std;
int main()
{
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;
}
int main()
{
// empty set container
set<int, greater<int> > s1;
// 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<<" ";
}
return 0;
}
int main()
{
return 0;
}
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.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()
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.
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.display()
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()
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):
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):
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.
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.
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.
Exception
try:
a = int(input("Enter a:"))
b = int(input("Enter b:"))
c = a/b
except:
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")
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 = []
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
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)
Set
set5 = {1,2,4,4,5,8,9,9,10}
print("Return set with unique elements:",set5)
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.
Dic Add
# Creating an empty Dictionary
Dict = {}
print("Empty Dictionary: ")
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";
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","Name":"John"}
for x,y in Employee.items():
print(x,y)
69