I.I LES CLASSES

  1. Notion de Classes :

Nous avons vu précédemment qu'avec les structures un "programme externe" pouvait facilement accéder aux données membre de la structure. Pour palier à ce problème nous allons utiliser un autre type de C++ : la Classe (mot clé : class).

L'exemple de la structure point devient :


class point{
  private:
    int x;
    int y;

  public:
    void initialise(int,int);
    void deplace(int,int);
    void affiche();
     };

void point::initialise(int abs,int ord)
    {
     x=abs;
     y=ord;
    }

void point::deplace(int dx,int dy)
    {
     x+=dx;
     y+=dy;
    }

void point::deplace()
    {
     cout<<"je suis en "<<x<<" "<<y<<endl;
    }

La définition est à peu près la même que pour la structure, sauf que nous remplaçons le mot clé struct par le mot clé class. Vous remarquerez aussi que nous avons introduit le mot private avant la déclaration des données membres et le mot public avant la déclaration des fonctions membre.

Le mot clé private empêche tout accès extérieur aux données membre(ou aux fonctions membre), seules les fonctions déclarées dans la classe peuvent accéder aux données membres de celle-ci.

Le mot clé public autorise quant à lui l'accès par l'extérieur aux données ou aux fonctions membre.

Si aucun mot clé n'est précisé, c'est le mot clé private qui est pris par défaut. Ainsi la présence de ce mot n'était pas indispensable dans notre exemple.

  1. Constructeur et Destructeur :
  1. Introduction :

Nous avons vu dans l'exemple précédent que l'initialisation des données membre était subordonné par l'utilisation par le programmeur de la fonction initialise. Donc si cela n'est pas fait, il peut par erreur utiliser des données qui non pas de valeur, il en va de même si un objet avant d'être utilisé doit s'allouer automatiquement de la mémoire.

C++ offre un mécanisme très performant pour palier a ce problème: le constructeur. C'est une fonction membre comme les autres qui sera appelée automatiquement lors de la création d'un objet de la classe et cela quelque soit sa classe d'allocation (statique, automatique ou dynamique). Les objets automatiques sont ceux qui sont "crées" par une déclaration et les dynamique par le mot clé new.

De même un objet pourra posséder un destructeur; c'est aussi une fonction membre appelée lors de la "destruction" de l'objet. Pour les objets automatiques, la destruction a lieu lorsque l'on quitte le bloc ou à la fonction où l'objet à été déclaré.

Par convention le constructeur se reconnaît à ce qu'il porte le même nom que la classe, et le destructeur porte le même nom que le constructeur précédé du symbole tilda (~).

  1. Mise en place d'un constructeur :

Nous allons modifier notre classe point afin de remplacer la fonction membre initialise par un constructeur :

class point{
    int x;
    int y;

  public:
    point(int,int);  //constructeur
    void deplace(int,int);
    void affiche();
     };

point::point(int abs,int ord)
    {
     x=abs;
     y=ord;
    }

void point::deplace(int dx,int dy)
    {
     x+=dx;
     y+=dy;
    }

void point::deplace()
    {
     cout<<"je suis en "<<x<<" "<<y<<endl;
    }

Un constructeur peut comporter un nombre quelconque d'arguments voir aucun. Mais il ne retourne aucune valeur donc aucun type ne peut figurer devant son nom, même pas void(sinon il y a erreur!!).

Attention la déclaration suivante ne convient plus :

point a;

En effet, dès qu'un constructeur a été défini, il doit pouvoir être appelé (automatiquement) lors de la création de l'objet a. Nous avons déclaré un constructeur avec deux paramètres, nous devons donc les lui fournir lors de la déclaration d'un nouvel objet :

point a(5,6);

Ainsi lorsqu'une classe possède un constructeur il n'est plus possible de créer un objet sans fournir les arguments demandés par le constructeur.

  1. Rôle du constructeur et du destructeur :

Nous avons vu précédemment un constructeur limité à l'initialisation de données membre, son rôle peut être plus actif avec une allocation dynamique de mémoire. C'est particulièrement ici que va intervenir le destructeur car il va falloir libérer la mémoire allouée. Voici un exemple de programme définissant une classe hasard qui tire un certain nombre de chiffre aléatoire dans un intervalle définit :


class hasard
    { 
     int nbval //nombre de valeur
     int *vecteur_val //vecteur contenant les valeur

public:
     hasard(int nb_val,int val_max);
     ~hasard();
     void affiche();
    };

hasard::hasard(int nb_val,int val_max)
    {
     vecteur_val=new int[nbval=nb_val];
     for(int i=0;i nb_val;i++)
        {
         vecteur_val[i]= double (rand())
                / (RAND_MAX*val_max);
        }
    }

hasard::~hasard()
    {
     delete vecteur_val;
    }

void hasard::affiche()
    {
     for(int i=0;i nb_val;i++)
        {
         cout<<vecteur_val[i]<<" ";
        }
     cout<<endl;
    }

void main(void)
    {
     hasard suite1(10,6);
     suite1.affiche();
     hasard suite2(6,12);
     suite2.affiche();
    }

2 0 1 2 4 0 5 3 1 2 0
1 4 3 2 5 11  

En théorie le constructeur peut être aussi bien public que privée. Un destructeur privé ne pourra plus être appelé directement, ce qui n'est pas important. Mais avec un constructeur déclaré en privé vous ne pourrez plus créer des objets de cette classe, à moins que la classe ne soit destinée à donner naissance, par héritage, à une classe dérivée.