Summary

Cours de programmation C++ décrivant des concepts fondamentaux comme la programmation procédurale et orientée objet, les points forts et limites de la programmation procédurale, la forme de la mémoire d'un programme C/C++, etc.

Full Transcript

Assili Mohamed – CPI2 Groupe de discussion sur Discord: https://discord.gg/gncxVNBQ4y Écrire le Décomposer le Définir les IMPLEMENTER - Identifier le progra...

Assili Mohamed – CPI2 Groupe de discussion sur Discord: https://discord.gg/gncxVNBQ4y Écrire le Décomposer le Définir les IMPLEMENTER - Identifier le programme problème en fonctions EXECUTER - problème principale en sous problèmes correspondantes DEBUGGER pseudo code Approche descendante 2 ▪ Difficulté de réutilisation du code ( modifications des paramètres selon le cas) ▪ Difficulté de maintenir les grandes applications ▪ Risque du phénomène « spaghetti code » ▪ Critères de qualité du code facilement violés: lisibilité, modularité, … 3 En OO, le logiciel est considéré comme une collection d’objets dissociés définis par des propriétés. Un objet comprend à la fois une structure de données et une collection d’opérations (son comportement). Approche ascendante les méthodes orientées objets sont ascendantes. 4 ▪ Modularité : les objets forment des modules compacts regroupant des données et un ensemble d'opérations. ▪ Abstraction : Les entités objets de la POO sont proches de celles du monde réel. Les concepts utilisés sont donc proches des abstractions familières que nous exploitons. ▪ Productivité et réutilisabilité : Plus l'application est complexe et plus l'approche POO est intéressante en terme de productivité. ▪ Sûreté : L'encapsulation et le typage des classes offrent une certaine robustesse aux applications. 5 Segment de code (text segment) : les instructions du programme Segment des données initialisées : les variables globales et statiques initialisées par le programmeur Segment des données non-initialisées : contient les données globales et statiques qui sont par défaut (initialisé par le kernell) 0 ou non initialisée explicitement. Heap : allocation dynamique des objets (le programmeur alloue et désalloue la mémoire) Stack : allocation temporaire des objets (existent seulement durant l’exécution d’une fonction) 6 Stack Heap Allocation contiguë Allocation non contiguë (en général) Accès plus rapide Accès moins rapide LIFO Allocation / Désallocation manuelle Allocation / Désallocation automatique Taille à la demande Taille limitée Exemple: int* creerTab() int* creerTab() { { int tab; int* tab = new int; return tab; return tab; } } 7 8 9 10 Directive préprocesseur. Utiliser une bibliothèque standard iostream Utilisation d’une bibliothèque personnelle Utilisation des objets prédéfinis dans le nom de domaine std Fonction principale du programme cout : la sortie standard du programme (console) cin : l’entrée standard des données saisies au clavier endl : fin de la ligne > : opérateur d’entrée du flux de données 11 ▪ 3 manières d’initialiser une variable : Plus de détails via ce lien: https://en.cppreference.com/w/cpp/language/initialization 12 Allocation Statique Allocation Dynamique les variables ne sont allouées que si votre unité de Les variables sont allouées de manière permanente programme est active L’allocation est faite avant l’exécution du programme L’allocation est faite pendant l’exécution du programme Pas de possibilité de réutilisation de la mémoire La mémoire est réutilisable et peut être libérée lorsqu’elle n’est pas nécessaire (opérateur delete). En c/c++, la gestion de la mémoire est à la charge du programmeur. Il doit libérer de la mémoire à chaque fois qu’elle n’est plus pointée. 13 Déclaration et initialisation Une variable de type bool ne peut avoir que deux états. true (1) ou false (0) 14 Opérateurs et fonctions : + : concaténation length() / size() : longeur == / != : comparaison compare(str) : comparer at(index) : lire un caractère insert(index,str) : insèrer Pus de fonctions via ce lien: https://devdocs.io/cpp/ 15 cin >> : arrête la lecture au premier caractère espace getline(cin,str): arrête la lecture au premier retour à a ligne 16 Deux types de constantes; compile-time constant et runtime constant 17 18 Stack Memory Allocation Heap Memory Allocation 19 Autre façon de parcourir Stack Memory Allocation 20 Une taille dynamique (non connue à l’avance). Augmente sa taille par duplication. Dispose de plusieurs méthodes Allocation contiguë On peut connaitre la quantité de mémoire allouée et faire retourner la mémoire en excès vers le système (capacity(), shrink_to_fit() ). Références : https://en.cppreference.com/w/cpp/cont ainer/vector 21 Inclure la bibliothèque vector. Voir : https://cplusplus.com/reference/vector/vector/ Création statique d’un tableau d’entiers Insérer des éléments dans le tableau Début du tableau partant de la gauche Fin du tableau partant de la gauche Début et fin du tableau partant de la droite. 22 Conteneur Ordonné clé valeur Gabes Gabes, 150000 Gafsa Gafsa, 110000 Mednine Mednine, 120000 Sfax Sfax, 900000 Tunis Tunis, 900000 Structured bindings depuis c++17 (Espace mémoire structuré) pour manipuler des pairs ou des tuples 23 Etant donner un tableau d’entiers « tab » contenant les N (saisie au clavier) premiers entiers partant de 0. on veut l’éclater en deux autres tableaux de manière à avoir un tableau d’entiers premiers et un tableau pour les entiers non premiers. Ecrire la fonction « estPremier » qui retourne un booléen indiquant si l’entier est premier ou non. Ecrire une fonction « remplir » qui lit la valeur maximale N et remplit le tableau passé en paramètre. Ecrire une fonction « afficher » qui affiche les éléments d’un tableau. Ecrire la fonction principale main qui créée et remplie le tableau « tab » et l’éclater en deux autres tableaux telle que demander. 24 25 26 Depuis c++17, il est possible d’avoir une seule variable capable d’avoir plusieurs types. std::variant Accès aux membres du variant 27 Soit f une fonction définie par La fonction retourne une valeur réelle lorsqu’elle est définie, sinon elle retourne un message d’erreur « la fonction n’est pas définie !! ». Ecrire une fonction principale qui appelle la fonction f avec une valeur saisie au clavier. 28 Vérifier si le premier objet est actif Accéder (lire) le contenu du variant 29 Un std::tuple est un objet qui peut contenir plusieurs objets. Les objets peuvent être de différents types. Les objets contenus dans un tuple sont construit dans leur ordre d’accès. #include Un std::pair est utilisé pour combiner deux objets qui peuvent être de types différents. #include On utilise first et second pour accéder aux objets contenus dans le pair 30 Espace mémoire structuré (en général utilisé une seule fois, pour éviter de créer un objet Personne par exemple) 31 Exercice Ecrire une fonction décomposer qui prend en paramètre une chaine de caractère et retourne le jour, le mois et l’année séparément. Ecrire une fonction principale main qui saisie la date sous forme mm/jj/aaaa et appelle la fonction décomposer, puis affiche le résultat. On peut utiliser std::stoi pour convertir un string en un int 32 Solution 33 En général, on les utilise selon l'expression suivante: lvalue = rvalue Lvalue est un objet qui a une location identifiée en mémoire (a une adresse en mémoire). - Capable de stocker une information - Ne peut pas être une fonction, une constante ou une expression Rvalue est un objet n’ayant pas un identifiant en mémoire (désigne la valeur dans un espace mémoire). - Toute chose pouvant retourner une expression constante ou une valeur. 34 35 Contient l’adresse de l’objet, mais se comporte comme un objet. Si & est précédé par un type de données alors c’est une référence de l’objet. Sinon on l’utilise comme adresse de l’objet. 36 impossible de modifier une référence lvalue une référence lvalue ne peut être initialisée qu'une seule fois (à la déclaration); ce qui implique qu'elle ne peut pas être nulle. Une référence lvalue ne peut référencer qu'une seule variable tout au long de sa durée de vie. 37 Une référence rvalue est destinée à référencer seulement des rvalues (des valeurs temporaires). On peut réaffecter une nouvelle valeur à une référence rvalue, un emplacement mémoire est alors créé pour y stocker la valeur. Donc la référence rvalue va référencer l'espace mémoire créé et non pas la rvalue elle même. 38 data qui est un objet temporaire créé dans la fonction getData() sera référencé par la référence sur rvalue, vec. Donc l'espace temporaire persistera tant qu'il est référencé. 39 Les modèles de fonction sont des fonctions spéciales qui peuvent fonctionner avec des types génériques. Un paramètre de modèle est un type spécial de paramètre qui peut être utilisé pour passer un type comme argument On peut écrire aussi: On peut définir plusieurs parameters templates pour une fonction 40 Un pointeur de fonction contient l'adresse du début du code binaire constituant la fonction. Le nom de la fonction représente son adresse de début. Nom de la fonction type (*identificateur)(paramètres); Les paramètre de la fonction Type renvoyé par la fonction 41 Etant donner un tableau d’entiers tab, on se propose de faire différentes manipulations sur ce tableau: Ecrire une fonction « affichePair » qui affiche un entier s’il est pair. Ecrire une fonction « afficheImpair » qui affiche un entier s’il est impair. Ecrire une fonction « pourChaque » qui applique une fonction (passée en paramètre) sur les éléments des tableaux. Ecrire une fonction principale main qui créée un tableau d’entiers et affiche pour chaque élément pair du tableau puis chaque élément impair du tableau. 42 43 [zone de capture](paramètres de la lambda) -> type de retour { instructions } La zone de capture : par défaut, une lambda est en totale isolation et ne peut manipuler aucune variable de l’extérieur. Grace à cette zone, la lambda va pouvoir modifier des variables extérieures. Les paramètres de la lambda : exactement comme pour les fonctions, les paramètres de la lambda peuvent être présents ou non, avec utilisation de références et/ou const possible. Le type de retour : encore un élément qui nous est familier. Il est écrit après la flèche 44 Passage par référence des objets externes capturés par le lambda 45 Les arguments par défaut d’une fonction permettent à cette dernière d’être appeler sans fournir tout ses paramètres. Les paramètres ayant une valeur par défaut devront être placés à la fin de la liste des paramètres de la fonction 46 47 Nom de la classe Visibilité des attributs (en général privée) Attributs de la classe (données) Visibilité des méthodes (en général publique ) Méthode prédicat (ne change pas les valeurs des attributs) Méthode action (peut changer les valeurs des attributs) Si jamais une méthode déclarée const doit changer la valeur d’une variable alors on devrait déclarer cette variable mutante (mutable). 48 En cas d'ambiguïté de nom entre les attributs et d'autres variables dans les méthodes, on dispose du pointeur sur l'instance courante, this, qui nous aide à pointer les attributs de la classe. 49 Pour une meilleure représentation d'une classe en C++, on peut définir un prototype de la classe dans un fichier.h et la définition de ses méthodes dans un autre fichier.cpp. 50 Les constructeurs sont des méthodes particulières qui ont pour responsabilité d'initialiser les attributs de la classe. Le constructeur porte le même nom que la classe, n'a pas de type de retour et est invoqué automatiquement où on créé une instance. Une classe peut avoir plusieurs constructeurs Si aucun constructeur n'est spécifié le compilateur fournit un constructeur par défaut à la classe ( attention : laisse non initialisé les attributs de type de base). 51 52 les listes d'initialisation servent pour initialiser les attributs et/ou d'appeler leurs constructeurs (s'ils sont des objets). 53 Constructeur par Constructeur défaut qui par défaut initialise les implicite attributs à 0 Constructeur par défaut qui Pas de initialise les constructeur attributs à 0 par défaut 54 ▪ On désire représenter l’objet Point caractérisé par un abscisse et un ordonné de type réel. Un point est construit de deux manières: ▪ Les coordonnés sont par défaut à 0 ▪ Les coordonnés sont initialisés par des valeurs utilisateurs ▪ Un point devrait être afficher sous cette forme (1.3 , 2.9) ▪ Un point peut être déplacer selon l’axe des abscisses et/ou l’axe des ordonnés. Définir la classe point. Ecrire une fonction main qui créée un point A à l’origine du repère. Puis on créé un autre point B ayant des coordonnés saisis au clavier. Afficher les deux points. En fin, faire confondre les deux points et les afficher de nouveau. 55 point.cpp point.h 56 57 Ce genre de constructeur permet d'initialiser un objet avec un autre objet. Le compilateur génère automatiquement un constructeur de copie par défaut en absence d'un fourni par le développeur. Ce constructeur de copie par défaut il est semblable au constructeur de copie définie en haut. Pour cela, on se contente en général par celui fourni par le compilateur et on ne définit pas de constructeur de copie. 58 59 Cette fonction créé une copie tmp (via le constructeur de copie fournit par défaut). À la fin de l'exécution de cette fonction l'objet tmp sera détruit, ce qui provoque la perte des espaces mémoires de largeur et hauteur. De ce fait, l'objet initial (utilisé lors de l'appel de la fonction afficher_largeur() sera biaisé). 60 On peut marquer un constructeur comme un constructeur par défaut en utilisant le mot clé default. Indiquer explicitement que c’est un constructeur par défaut On peut interdire l’accès à un constructeur ou à une méthode avec l’opérateur delete. Interdire le copiage d’un objet 61 62 Il est important de pouvoir gérer l'espace mémoire alloué pour les objets de notre programme après usage. Le C++ offre une méthode appelée destructeur invoquée automatiquement en fin de vie de l'instance. Le destructeur d'une classe est une méthode ayant le même nom de la classe précédé par le signe ~, sans paramètres et ne supporte pas de surcharge. Donc pour une classe il y a un seul destructeur. Si on définit pas un destructeur explicitement pour une classe, le compilateur nous fournit un par défaut. Destructeur qui libère l’espace alloué dynamiquement 63 A local (automatic) object with block scope goes out of scope. An object allocated using the new operator is explicitly deallocated using delete. The lifetime of a temporary object ends. A program ends and global or static objects exist. The destructor is explicitly called using the destructor function's fully qualified name. 64 L'intérêt de la surcharge des opérateurs est d'adapter leur comportement à des cas particuliers voulus par le développeur. La surcharge des opérateurs peut être une surcharge externe ou interne par rapport à la classe où ils s'appliquent. Surcharge externe (via une fonction) 65 66 Un code moins facile à entretenir Redondance de code (données et traitements) Regrouper les informations et les comportements en commun Plus intuitif Plus facile à maintenir Permettre la réutilisation du code Une forte capacité d’évolution Héritage (Eng: inheritance) 67 68 Attention les attributs protected ne sont accessibles dans les classes filles que s'ils sont dans la portée de cette classe fille (c-à-d directement via this ou indirectement via une instance de la classe fille). 69 Lors de l'instanciation d'une sous classe, il faut initialiser: – les attributs de la sous classe – les attributs hérités des super-classes Syntaxe 70 Remarques: Lorsque la super classe admet un constructeur par défaut, alors son invocation explicite au niveau de la sous-classe ne sera pas obligatoire. Le compilateur réalise implicitement l'invocation du constructeur par défaut. L'appel du constructeur de la super classe doit se faire en premier lieu dans la liste d’initialisation Il n'est pas nécessaire que la sous classe ait ses propres attributs (supplémentaires) Le constructeur de copie d'une sous-classe doit invoquer explicitement le constructeur de copie de la super-classe (sinon c'est le constructeur par défaut qui sera invoqué par le compilateur). 71 72 La destruction des objets se fait dans le sens inverse de la construction. 73 Résolution statique des liens L’objet est reconnu par son type de déclaration 74 Résolution dynamique des liens La résolution dynamique des lien permet de choisir la méthode à exécuter au moment de l'exécution selon la nature réelle des instances dans la mémoire. – Déclarer la méthode comme virtuelle avec le mot clé virtual, cette déclaration se fait dans la classe la plus générale qui admet cette méthode. – Utiliser les références et/ou les pointeurs pour invoquer les méthodes virtuelles (passage par références ou par adresse, la construction dynamique des instances avec new) 75 La virtualité est transmise par transitivité à la méthode de la classe fille. Lorsque la méthode virtuelle est invoquée à partir d'une référence ou d’un pointeur vers une instance, c'est la méthode du type réel de l'instance qui sera exécutée. Il est conseillé de toujours définir des destructeurs comme virtuels (pour éviter la destruction partielle des objets) Un constructeur ne peut pas être virtuel (s'il utilise des méthodes virtuelles le caractère virtuel de ces méthodes sera ignoré) 76 ▪ Depuis C++11, si une classe est déclarée final alors on ne peut pas dériver d’elle une autre classe. ▪ Une méthode déclarée final ne peut pas être redéfinie au niveau des classes dérivées. 77 Une méthode virtuelle pure dans une classe n'a pas de comportement significatif. On ne sait son comportement que dans les classes dérivées de la classe où elle est définit. Exemple: 78 L’appel des constructeurs des superclasses se fait dans l’ordre d’héritage. 79 Solution 1 Solution 2 80 Héritage en Diamond virtual Un seul objet A est hérité pour la classe D D a deux copies de A 81 Si la classe Animal ne possède pas un constructeur par défaut alors la classe la plus dérivée doit Invoquer explicitement le constructeur de la classe de Base (Animal). Alors les appels dans les classes intermédiaires seront ignorés. 82 83 84

Use Quizgecko on...
Browser
Browser