C++ - TP1
Du C au C++
Vous allez, dans ce premier TD-TP, (re)découvrir les notions fondamentales que sont : la gestion de la mémoire, la visibilité et la durée de vie des objets, la modularité et la gestion de projets.
Les notions qui distinguent C++ de C, sans pour autant parler de programmation orientée objet, seront étudiées telles que : constantes, référence, valeurs de paramètres par défaut, fonctions surdéfinies, flux d'entrée-sortie.
Exercice 1 : référence, modularité.
Soit a une variable quelconque, la valeur de &a correspond à l'adresse mémoire de la variable a. L'élément syntaxique & associé à un type introduit quant à lui la notion de référence.
Ecrire une procédure qui prend en paramètres deux références à des entiers et qui échange leur valeur :
void Permuter(int&, int&);Encapsuler cette première procédure dans un module nommé « echangiste.cc ». Ecrire le fichier à en-têtes correspondant. Ecrire dans un troisième fichier la fonction qui testera votre procédure et qui doit aussi constituer le point d'entrée de votre programme.
Créer votre premier makefile, celui-ci devant gérer le source du module echangiste.cc, son fichier à en-têtes correspondant, le source de votre programme principal ainsi que leurs inter-dépendances.
Ajouter le prototype de fonction suivant dans echangiste.h :
void Permuter(Complexe&, Complexe&);Utiliser votre makefile : comment doit-il réagir ? Quelle règle en déduire (si ce n'est déjà fait) ?
Exercice 2 : structure, définition de type, surdéfinition de fonctions.
Construire dans un fichier indépendant, nommé complexe.h, la structure
Complexe, contenant les attributs a (partie réel) et b (partie imaginaire) tous deux de type float. En faire un type. Ecrire la procédure :void AfficherComplexe(const Complexe&);Quel(s) rôle(s) joue(nt) l'attribut const et l'opérateur & ? Aurait-on pu s'en passer (justifier la réponse) ? Où doit-on inclure le fichier d'en-têtes iostream ?
Implanter la fonction :
void Permuter(Complexe&, Complexe&);en utilisant exclusivement des variables de type
Complexe.Tester la surdéfinition de la procédure
Permuterde l'exercice 1 ainsi que la procédureAfficherComplexedans votre programme principal.
Exercice 3 : le module « Complexe »
Implanter la fonction somme de deux complexes :
Complexe Somme(const Complexe&, const Complexe&);Rappel : soit \(z_1 = a_1 + i\ b_1\) et \(z_2 = a_2 + i\ b_2\), alors :
\[z_1 + z_2 = (a_1 + a_2) - i\ (b_1 + b_2)\]
Implanter la fonction produit de deux complexes :
Complexe Produit(const Complexe&, const Complexe&);Rappel : soit \(z_1 = a_1 + i\ b_1\) et \(z_2 = a_2 + i\ b_2\), alors :
\[z_1 . z_2 = (a_1.a_2 - b_1.b_2) + i\ (b_1.a_2 + a_1.b_2)\]
Implanter la fonction module d'un complexe :
float Module(const Complexe&);Rappel : soit \(z = a + i\ b\), alors :
\[\|z\| = \sqrt{a^2 + b^2}\]
Implanter le conjugué d'un complexe :
Complexe Conjuge(const Complexe&);Rappel : soit \(z = a + i\ b\), alors :
\[\bar{z} = a - i\ b\]
Tester toutes ces fonctions dans votre programme principal. En particulier, vérifier que \(z . \bar{z} = \|z\|^2\).
Exercice 4 : variation sur le thème des complexes - initialisation, gestion de la mémoire
Modifier la structure qui définit les complexes en lui ajoutant un champ « ident » (pour identificateur) de type entier non signé, qui doit jouer le rôle d'identificateur unique pour chaque complexe. Comment optimiser le coût mémoire de cette fonctionnalité ?
Implanter la procédure
void Init(complexe&);qui initialise le champ ident à un entier unique et les champs a et b à 0. Cette fonction sera appelée systématiquement après la déclaration d'un complexe.Remarque : il est bien entendu que cette stratégie n'empêche pas l'existence de deux complexes ayant le même identificateur (par l'affectation par exemple) mais sachez que C++ est en mesure de résoudre ce cas particulier.
Visualiser à l'écran l'adresse d'une variable statique de type Complexe ainsi que celles de ses champs.
Déclarer une référence à cette variable et faire de même avec cette référence.
Créer une fonction
Complexe Bidon(Complexe&);et faire de même avec le paramètre formel et la variable qui réceptionne la valeur retournée par la fonction. Conforter ainsi vos connaissances.Créer une fonction void
CreerComplexe(Complexe**);qui alloue l'espace mémoire correspondant au pointeur de Complexe passé en paramètre et initialise correctement chacun de ses champs.Transformer cette fonction en
void CreerComplexe(ptComplexe&);avec le typetypedef Complexe* ptComplexe;Réécrire la fonction CreerComplexe en
Complexe* CreerComplexe();.Écrire la fonction
Complexe* CreerVecteurComplexes(unsigned int);qui alloue dynamiquement un vecteur de Complexe.Afficher chacune des adresses des composants de ce vecteur.