Section
1
Correspondance entre le UML et le C++ Exemples de codage
Introduction
Ce document présente quelques exemples de codage qui traduisent la correspondance entre le modèle exprimé en UML et les instructions en langage C++. Ces exemples sont donnés sous forme tabulaire afin de faciliter leur compréhension.
Les classes représentées sont dotées de deux constructeurs (un constructeur par défaut et un constructeur de copie), d’un destructeur et de trois opérateurs. Il s’agit là d’une pratique courante et recommandée par les praticiens du domaine. Évidemment, l’implantation concrète de ces fonctions membres dépendra de l’application réelle des classes. Le rôle des opérateurs d’assignation (=), d’égalité (==) et de l’inégalité (!=) est de simplifier l’insertion des objets dans des classes collections. Cette manipulation et d’autres seront nécessaires lorsque la multiplicité des objets dans une relation est supérieure à 1.
Il existe plusieurs façons de réaliser les relations UML. Le codage présenté dans ce document ne montre que le principe de base de l’implantation des relations. Ainsi, une association, une agrégation et une composition sont toutes réalisées à l’aide de pointeurs d’objet. Certaines de ces relations auraient pu être réalisées par des variables membres ordinaires. L’importance dans ces cas est le respect de la nature des relations et la durée de vie des objets.
À noter également que certains exemples codage supposent que les classes sont déclarées dans un seul fichier d’en-tête tandis que d’autres exemples supposent que les classes sont déclarées dans des fichiers .h séparés. Un commentaire C++ vous donnera l’indication lorsque les classes sont déclarées dans des fichiers séparés.
Classes simples
Classe Simple
A
class A { public: // constructeur A(); A(const A& droit); // Destructeur ~A(); // Opérateur d’assignation
Classe avec attributs et opérations
A
A1 : string A2 : string
op1() op2()
const A& operator = (const A& droit); // Autres opérations bool operator == (const A& droit) const; bool operator != (const A& droit) const; };
class A { public: // constructeur A(); A(const A& droit); // Destructeur ~A(); // Opérateur d’assignation const A& operator = (const A& droit); // Autres opérations bool operator == (const A& droit) const; bool operator != (const A& droit) const; // Opérations spécifiques à la classe const string get_A1() const; void set_A1(const string valeur); const string get_A2() const; void set_A2(const string valeur); private: string A1; string A2; }; // Quelques implantations const string A::get_A1() const { return A1; } void A::set_A1(const string valeur) { A1 = valeur; } const string A::get_A2() const { return A2; } void A::set_A2(const string valeur) { A2 = valeur; }
Classe paramétrisée
Type
A
template <class Type> class A { public: A(); A(const A<Type>& droit); ~A();
const A<Type>& operator = (const A<Type>& droit); bool operator == (const A<Type>& right) const; bool operator != (const A<Type>& right) const; };
Classe utilitaire
«utility» A
class A { public: static void op1(); static void op2(); };
op1() op2()
3
Relations d’association
Association 1 à 1
1
1
A
B
RoleA
RoleB
// Déclaration anticipée de la classe B class B; // Classe A class A { public: A(); A(const A& droit); ~A();
const A& operator = (const A& droit); bool operator == (const A& right) const; bool operator != (const A& right) const;
// Pour la relation d’association const B* get_RoleB() const; void Set_RoleB(B* const value);
private: B * Rb; };
const B* A::get_RoleB() const { return Rb; } void A::set_RoleB(B* const value) { Rb = value; }
// Classe B class B { public: B(); B(const B& droit); ~B();
const B& operator = (const B& droit); bool operator == (const B& right) const; bool operator != (const B& right) const;
// Pour la relation d’association const A* get_RoleA() const; void Set_RoleA(A* const value);
private: A* Ra; };
const A* B::get_RoleA() const { return Ra; } void B::set_RoleA(A* const value) { Ra = value; }
Association N à 1
Publicité
Classe A identique à celle d’une association 1 à 1
#include <set> using namespace std; // Classe B class B { public:
4
A
0..*
RoleA
1
RoleB
B
Association N à 1 avec contrainte
{ordered}
A
0..*
RoleA
1
RoleB
B
B(); B(const B& droit); ~B();
const B& operator = (const B& droit); bool operator == (const B& right) const; bool operator != (const B& right) const;
// Pour la relation d’association de // multiplicité 0..* const set<A*> get_RoleA() const; void Set_RoleA(const set<A*> value);
private: set<A*> Ra; };
const set<A*> B::get_RoleA() const { return Ra; } void B::set_RoleA(const set<A*> value) { Ra = value; }
Classe A identique à celle d’une association 1 à 1
#include <list> using namespace std; // Classe B class B { public: B(); B(const B& droit); ~B();
const B& operator = (const B& droit); bool operator == (const B& right) const; bool operator != (const B& right) const;
// Pour la relation d’association de // multiplicité 0..* avec contrainte d’ordre const list<A*> get_RoleA() const; void Set_RoleA(const list<A*> value);
private: list<A*> Ra; };
const list<A*> B::get_RoleA() const { return Ra; } void B::set_RoleA(const list<A*> value) { Ra = value; }
5
Classe d’association
A
B
1
1
C
// Fichier C.h // Déclaration anticipée class A; class B;
class C { // constructeurs, destructeur et // opérateurs idem aux classes // précédentes //
// relation d’association const B* get_B() const; void set_B(B* const value);
const A* get_A() const; void set_A(A* const value); private: A* _A; B* _B; };
// Fichier A.h #include “C.h”
class A { // constructeurs, destructeur et // opérateurs idem aux classes // précédentes //
// relation d’association const C* get_C() const; void set_C(C* const value);
private: C* _C; };
// Fichier B.h #include “C.h”
class B { // constructeurs, destructeur et // opérateurs idem aux classes // précédentes //
// relation d’association const C* get_C() const; void set_C(C* const value);
private: C* _C; };
Publicité
6
Classe d’association N à N
A
0..*
0..*
B
C
// Fichier C.h // Déclaration anticipée class A; class B;
class C { // constructeurs, destructeur et // opérateurs idem aux classes // précédentes //
// relation d’association const B* get_B() const; void set_B(B* const value);
const A* get_A() const; void set_A(A* const value); private: A* _A; B* _B; };
// Fichier A.h #include <set> #include “C.h” using namespace std; class A { // constructeurs, destructeur et // opérateurs idem aux classes // précédentes //
// relation d’association N à N const set<C*> get_C() const; void set_C(const set<C*> value);
private: set<C*> _C; };
7
// Fichier B.h #include <set> #include “C.h” using namespace std; class B { // constructeurs, destructeur et // opérateurs idem aux classes // précédentes //
// relation d’association N à N const set<C*> get_C() const; void set_C(const set<C*> value);
private: set<C*> _C; };
Relations d’agrégation
Agrégation 1 à 1
// Déclaration anticipée class B;
RoleA
1
1
A
B
class A { // constructeurs, destructeur et // opérateurs idem aux classes // précédentes //
// relation d’agrégation const B* get_B() const; void set_B(B* const value); private: B *_B; };
class B { // constructeurs, destructeur et // opérateurs idem aux classes // précédentes //
// relation d’agrégation const A* get_RoleA() const; void set_RoleA(A* const value); private: A *RoleA; };
8
Agrégation avec navigation
Classe A ne peut pas atteindre classe B
RoleA
1
1
A
B
class A { // constructeurs, destructeur et // opérateurs idem aux classes // précédentes //
private: // aucun objet de type B (pointeur ou autre) // dans A };
// Fichier B.h #include “A.h” class B { // constructeurs, destructeur et // opérateurs idem aux classes // précédentes //
// relation d’agrégation avec navigation const A* get_RoleA() const; void set_RoleA(A* const value); private: A *RoleA; };
Relations de composition
Composition
// Déclaration anticipée class B;
RoleA
1
Publicité
1
A
B
class A { // constructeurs, destructeur et // opérateurs idem aux classes // précédentes //
// relation de composition const B* get_B() const; void set_B(B* const value); private: B *_B; };
class B { // constructeurs, destructeur et // opérateurs idem aux classes // précédentes //
// relation de composition
9
const A get_RoleA() const; void set_RoleA(const A value); private: A RoleA; };
Une réalisation alternative de la composition
// Déclaration anticipée class B;
class A { // constructeurs, destructeur et // opérateurs idem aux classes // précédentes //
// relation de composition const B* get_B() const; void set_B(B* const value); private: B *_B; };
class B { B() { // effectuer les tâches utiles ici…
// créer l’objet RoleA RoleA = new A; } A(const A& droit) { // effectuer les tâches utiles ici…
// créer l’objet RoleA RoleA = new A; }
// Destructeur ~A() { // effectuer les tâches utiles ici…
// détruire l’objet RoleA delete RoleA; }
// Autres opérateurs idem aux classes // précédentes //
// relation de composition const A* get_RoleA() const; void set_RoleA(A* const value); private: A *RoleA; };
10
Composition 1 à N
Classe A identique à celle d’une composition 1 à 1
A
0..*
RoleA
1
B
#include <set> using namespace std;
class B { // constructeurs, destructeur et // opérateurs idem aux classes // précédentes //
// relation de composition 1 à N const set<A> get_RoleA() const; void set_RoleA(const set<A> value); private: set<A> RoleA; };
Héritage
Héritage simple
A
B
#include “A.h” class B : public A { // declaration de la classe B //
};
Héritage multiple
#include “A.h” #include “B.h”
A
B
class C : public A, public B { // declaration de la classe C //
};
C
11