#include <string>
#include <iostream>
using namespace std;
class Ami {
public:
//arghh.. il y a un attribut statique:
// cet attribut est commun à toutes les
// instances de la classe et peut être
// utilisé indépendamment de la création de
// tout objet de la classe.
int static nombre_ami_Lausanne;
// l' initialisation d'un attribut statique doit toujours de faire
// à l'exterieur de la classe en utilisant l'opérateur ::
int Ami::nombre_ami_Lausanne = 0;
int main(){
Ami a1("Toto", "Lausanne");
a1.afficher();
Ami a2(a1);
a2.setVille("Brazzaville");
a2.afficher();
cout << "J'ai " << Ami::nombre_ami_Lausanne << " ami(s) vivant à Lausanne" << endl;
return 0;
}
/* Définition exteriorisée des méthodes de la classe Ami */
// le constructeur:
// si l'ami "construit" habite à Lausanne
// il faut incrémenter le compteur d'amis.
Ami::Ami(string nom, string ville)
:nom(nom), ville(ville)
{cout<< "Un nouvel ami" << endl;
if (ville == "Lausanne") ++nombre_ami_Lausanne;}
// constructeur de copie
// là encore il faut augmenter le nombre
// d'amis vivant à Lausanne (si l'ami "copié"
// vit à Lausanne bien sûr)
Ami::Ami(const Ami& ami)
:nom(ami.nom), ville(ami.ville)
{cout << "Clone d'un ami" << endl;
if (ville == "Lausanne") ++nombre_ami_Lausanne;}
// destructeur "standard"
// avec le comptage approprié du nombre d'ami.
// prenez la bonne habitude de toujours déclarer
// vos destructeurs comme virtuels (voir cours)
Ami::~Ami(){
cout << "Sniff, fin d'une amitie" << endl;
if (ville == "Lausanne") --nombre_ami_Lausanne;
}
// Ici il fallait penser à mettre à jour le
// compteur d'ami dans deux situations possibles:
// l'ami (this en fait) s'établit à Lausanne
// après avoir été dans une autre ville ou alors
// il s'établit dans une autre ville après avoir
// été à Lausanne.
void Ami::setVille(string ville){
if ((this->ville == "Lausanne") && (ville != "Lausanne")) --nombre_ami_Lausanne;
if ((this->ville != "Lausanne") && (ville == "Lausanne")) ++nombre_ami_Lausanne;
this->ville = ville;
}
// on ne peut plus classique
void Ami::afficher() const{
cout << "Mon ami s'appelle " << nom << endl;
cout << "Il habite " << ville <<endl;
}
Exercice 5 : un peu d'algèbre élémentaire (niveau 2)
Cet exercice est niveau 2, non pas en raison de sa difficulté informatique mais pour le niveau d'abstraction mis en oeuvre.
Il est donc en fait très facile si l'on suit rigoureusement les directives d'implémentation.
Définissez la classe EnsembleFini, représentant l'ensemble des entiers naturels entre 0 et p comme l'entier (non-signé) p.
class EnsembleFini
{
protected:
unsigned int p;
};
p est protected car il est propre à la classe (i.e. pas d'accès public), mais on souhaite tout de même pouvoir y avoir accès dans les sous-classes (héritage).
Ajoutez le constructeur correspondant.
class EnsembleFini
{
public:
EnsembleFini(unsigned int p) { this->p = p; }
protected:
unsigned int p;
};
On aurait aussi pu écrire :
EnsembleFini(unsigned int p) : p(p) {}
Définissez ensuite la classe Groupe qui hérite de la classe EnsembleFini et contient une méthodeadd
Il suffit de l'écrire :
class Groupe : public EnsembleFini
{
public:
unsigned int add(unsigned int x, unsigned int y) const
{
return (x+y) % p;
}
};
Mais il ne faut pas oublier le constructeur :
class Groupe : public EnsembleFini
{
public:
Groupe(unsigned int p) : EnsembleFini(p) {}
...
};
Définissez ensuite la classe Anneau
Cela se fait de la même façon :
class Anneau : public Groupe
{
public:
Anneau(unsigned int p) : Groupe(p) {}
unsigned int mult(unsigned int x, unsigned int y) const
{
return (x*y) % p;
}
};
Terminez par la classe Corps
class Corps : public Anneau
{
public:
Corps(unsigned int p) : Anneau(p) {}
unsigned int inv(unsigned int x) const;
unsigned int div(unsigned int x, unsigned int y) const
{
return mult(x, inv(y));
}
};
Pour l'implémentation de inv, il suffit de réutiliser la division d'Euclide généralisée donnée dans le "petit coup de pouce" de l'énoncé.
Elle juste un tout petit peu adaptée ici:
unsigned int Corps::inv(unsigned int x) const
{
// algorithme d'Euclide pour resoudre l'equation de Bezout
// x * u + v * p = 1
// voir exercice 1 de la serie 11
if (x != 0)
{
// algorithme d'Euclide
int prev_u(1), prev_v(0), y(p), u(0), v(1),
new_u, new_v, q, r;
while (y != 1)
{
q = x/y;
r = x%y;
x = y;
y = r;
new_u = prev_u - q * u;
prev_u = u;
u = new_u;
new_v = prev_v - q * v;
prev_v = v;
v = new_v;
}
return (u + p) % p; // u % p seul. ne fonctionne pas à cause de signed/unsigned
}
else
return 0; // lever une exception ici
}
Testez votre programme
Le résultat est le suivant :