int Fraction::pgcd(int x, int y)
 int r;
 if (x <= 0 || y <= 0)
 r = -1;
 else
 while (x != 0 && y != 0 && x != y)
 if (y > x)
 y = y % x;
 else
 x = x % y;
 if (x == 0)
 r = y;
 else
 r = x;
 return r;
void Fraction::normalise()
 int s, n, d, p;
 if (den < 0)
 s = -1;
 d = -den;
 else
 s = 1;
 d = den;
 if(num < 0)
 s = -s;
 n = -num;
 else
 n = num;
 if(n != 0)
 if(d != 0)
 p = pgcd(n, d);
 n = n/p;
 d = d/p;
 num = n*s;
 den = d;
 } 
 else
 num = 0;
 den = 1;
} 
Fraction Fraction::operator+(const Fraction & f) const
 Fraction r;
 r.num = f.den*num + den*f.num;
 r.den = f.den*den;
 r.normalise();
 return r;
Fraction Fraction::operator-(const Fraction & f) const
 Fraction r;
 r.num = f.den*num - den*f.num;
 r.den = f.den*den;
 r.normalise();
 return r;
Fraction Fraction::operator*(const Fraction & f) const
 Fraction r;
 r.num = f.num*num;
 r.den = f.den*den;
 r.normalise();
 return r;
Fraction Fraction::operator/(const Fraction & f) const
 Fraction r;
 r.num = f.den*num;
 r.den = f.num*den;
 r.normalise();
 return r;
using namespace std;
int main()
 Fraction f1, f2, f3, f4, E;
 cout « "SAISIE de f1 " « endl; cin » f1;
 cout « "SAISIE de f2 " « endl; cin » f2;
 f3 = Fraction(3, 4);
 f4 = Fraction(5, 8);
 E = (f1 + f3 - f2) / (f1*f2 - f4) + 4;
 cout « "E = " « E « endl;
 return 0;
Héritage.
Présentation.
Dans la conception orientée objet, la généralisation consiste à modéliser des concepts communs à un ensemble d'autres concepts. Les autres concepts deviennent dès lors des spécialisations de la généralisation. Cette manière de modéliser s'appelle l'héritage, car les spécialisations héritent de la généralisation. En C++, les classes peuvent hériter d'autres classes et la relation d'héritage est exprimée à l'aide de l'opérateur de dérivation ":".
À partir d'une classe A, on peut créer une classe B qui possède toutes les caractéristiques de la classe A, à laquelle on ajoute un certain nombre de méthodes qui sont spécifiques à B. Cette notion orientée objet fondamentale s'appelle l'héritage.
On dit que :
On dit aussi que:
Il existe en fait trois types d'héritage "public", "private" ou "protected" qui permet de spécifier si oui ou non une méthode de la classe B peut modifier une donnée membre de la classe A, selon qu'elle soit "public", "private" ou "protected".
Syntaxe.
class B : "type_héritage" A
 "..."
"type_héritage" est l'un des mots clés d'accès codice_1, codice_3 ou codice_2.
Les membres de A sont alors à la fois accessibles à la classe dérivée B et en dehors de ces classes selon la valeur utilisée pour "type_héritage" :
Pour résumer, "type_héritage" ne peut que restreindre l'accès des membres de la classe A, ou le conserver.
Exemple.
class VehiculeRoulant
public:
 VehiculeRoulant();
 void avancer();
 void accelerer();
protected:
 int position, vitesse;
// Initialement à l'arrêt
VehiculeRoulant::VehiculeRoulant()
 : position(0)
 , vitesse(0)
void VehiculeRoulant::avancer()
 position += vitesse;
void VehiculeRoulant::accelerer()
 vitesse++;
class Automobile : public VehiculeRoulant
public:
 Automobile(int places);
protected:
 int m_places;
Automobile::Automobile(int places)
 : VehiculeRoulant() // <--- pour initialiser les variables héritées
 // position et vitesse
 , m_places(places) // initialiser le nombre de places
L'appel explicite au constructeur de la classe de base dans cet exemple n'est pas nécessaire car par défaut, le constructeur (sans paramètres) est appelé.
Dans le cas où il est nécessaire d'appeler un autre constructeur, il faut le faire dans la liste d'initialisation du constructeur de la classe dérivée.
Méthodes virtuelles.
Dans l'exemple précédent, si l'on ajoute une autre méthode à la classe codice_28 :
class VehiculeRoulant
public:
 void accelererEtAvancer();
};
void VehiculeRoulant::accelererEtAvancer()
 accelerer();
 avancer();
et que l'on modifie la façon d'avancer d'une automobile :
class Automobile : public VehiculeRoulant
public:
 void avancer();
};
void Automobile::avancer()
 position += vitesse - frottementRoues;
Alors si on utilise la méthode codice_29 sur un objet de classe codice_30, le résultat sera incorrect, car la méthode codice_31 appelée sera celle définie par la classe codice_28.
Pour que ce soit celle de la classe codice_30 qui soit appelée, il faut que la méthode codice_31 soit définie comme virtuelle dans la classe de base codice_28 :
class VehiculeRoulant
public:
 virtual void avancer();
};
virtual void VehiculeRoulant::avancer()
 position += vitesse;
Le mot clé codice_36 indique une méthode virtuelle, c'est-à-dire que son adresse n'est pas fixe, mais dépend de la classe de l'objet (le compilateur construit une table interne des méthodes virtuelles pour chaque classe).
Il est possible d'accéder à une méthode précise de la table des méthodes virtuelles, en indiquant la classe de la méthode à appeler. Par exemple, pour appeler la méthode codice_31 de codice_28 à partir d'une méthode de automobile:
void Automobile::avancer()
 VehiculeRoulant::avancer();
 position -= frottementRoues;
Destructeur virtuel.
Il est important d'utiliser un destructeur virtuel pour toute classe qui sera dérivée. Dans le cas contraire seul celui de la classe de base est appelé, sans libérer les membres des sous-classes.
Ne pas déclarer un destructeur comme virtuel interdit donc de dériver cette classe.
Héritage multiple.
L'héritage multiple permet à une classe d'hériter de plusieurs super-classes. Ceci permet d'intégrer dans la sous-classe plusieurs concept d'abstractions qui caractérisent cette sous-classe. Pour cela, il suffit de déclarer les super-classes les unes après les autres. Si une classe C hérite de A et de B, la syntaxe sera la suivante:
class C : "type_héritage" A, "type_héritage" B "..."
 ...
Par exemple, si l'on possède une classe décrivant un véhicule roulant, et une classe décrivant un navire, on pourrait créer une classe décrivant un véhicule amphibie qui hériterait des propriétés et méthodes de véhicule roulant et de navire.
L'héritage multiple peut poser des problèmes de définitions multiples de méthodes virtuelles. Supposons que l'on ait une classe codice_39 ayant les sous-classes codice_40 et codice_41 qui en dérivent. Si l'on crée une classe codice_42 héritant à la fois de codice_40 et de codice_41, alors, les instanciations des objets de classe provoqueront des appels successifs des constructeurs. D'abord codice_45, puis pour ses parents codice_46 et codice_47, puis, le parent de codice_40 codice_49, et enfin codice_50 pour le parent de codice_41. On remarque alors que le constructeur de la classe codice_39 est appelé à toute instanciation d'un objet de classe codice_42. En C++, il existe un moyen d'éviter cela et de ne faire appel au constructeur de codice_39 qu'une seule fois. Pour cela, il suffit d'indiquer lors des héritages le mot-clé codice_36 pour indiquer au compilateur que les constructeurs des classes multi-héritées ne doivent être appelées qu'une seule fois.
class Base
 Base::Base()
 cout « "+++ Construction de Base" « endl;
 virtual Base::~Base()
 cout « "--- Destruction de Base" « endl;
};
class H1 : virtual public Base
 H1::H1() : Base()
 cout « "+++ Construction de H1" « endl;
 virtual H1::~H1()
 cout « "--- Destruction de H1" « endl;
};
class H2 : virtual public Base
 H2::H2() : Base()
 cout « "+++ Construction de H2" « endl;
 virtual H2::~H2()
 cout « "--- Destruction de H2" « endl;
};
class Finale : virtual public H1, virtual public H2
 Finale::Finale() : H1(), H2()
 cout « "+++ Construction de Finale" « endl;
 Finale::~Finale()
 cout « "--- Destruction de Finale" « endl;
};
Classes abstraites.
Présentation.
Une classe abstraite est une classe pour laquelle on a défini une méthode mais on a explicitement indiqué qu'on ne fournira aucune implémentation de cette méthode.
Il est interdit de créer une instance d'une classe abstraite.
Ce mécanisme est extrêmement puissant pour manipuler des concepts abstraits.
On peut même avoir une classe pour laquelle toutes les méthodes sont abstraites, on parle alors de classe abstraite pure.
Une classe héritant d'une classe abstraite doit fournir une implémentation des méthodes abstraites ou bien elle sera à son tour une classe abstraite.
Syntaxe.
virtual type nom_méthode(paramètres)=0;
Une telle méthode définie uniquement dans une sous-classe est nécessairement virtuelle.
Le mot-clé codice_36 est donc optionnel.
type nom_méthode(paramètres)=0; // Méthode d'une sous classe encore abstraite
type nom_méthode(paramètres); // Méthode d'une sous classe plus abstraite
Exemple.
class Animal
public:
 // méthode à implémenter par les sous-classes
 virtual cstring cri() = 0;
Pointeur de membre.
Un pointeur de membre pointe un membre d'un objet (variable ou méthode).
Ce genre de pointeur, rarement utilisé, possède une syntaxe spéciale.
L'étoile codice_57 est remplacée par codice_58 signifiant un pointeur sur un membre de cette classe, ou d'une classe dérivée.
Ce genre de pointeur occupe plus de place qu'un pointeur classique, et occupe un nombre d'octets variable selon la classe.
Exemple.
int CBox::* pBoxInt;
// pBoxInt pointe un entier dans les objets de la classe CBox
L'utilisation d'un tel pointeur nécessite un objet de la classe concernée (ou classe dérivée).
L'opérateur de déréférencement codice_57 est alors remplacé par codice_60 ou bien par codice_61.
Exemple.
pBoxInt = &CBox::length; // désigne l'adresse du membre length de la classe
CBox mybox(10, 12, 15);
cout « "length = " « mybox.*pBoxInt;
CBox* pbox = new CBox(20, 24, 30);
cout « "length = " « pbox->*pBoxInt;