Les classes

En Java, les classes permettent de regrouper des attributs et des méthodes dans un nouveau type de données. En C/C++, si on n’a que des attributs et pas de méthode, on peut utiliser le type struct. Ce type permet de regrouper des attributs et est aussi disponible en C :

struct point {
    int x;
    int y;
}

On peut ensuite déclarer une variable de ce type :

point myPoint;
point myPoint = {12, 42};

ou en spécifiant les attributs :

point myPoint = {.x = 12, .y = 42};

On peut aussi combiner la déclaration du type et de la variable :

struct point {
    int x;
    int y;
} myPoint = {.x = 12, .y = 42};

Si on souhaite ajouter des méthodes à un type, nous pouvons le faire en C avec des pointeurs de fonctions, mais c’est une technique assez lourde et sujette aux erreurs. On préfère passer à C++ qui propose un vrai concept de classes et d’objets.

Nous pouvons déclarer une classe (par exemple, dans un fichier point.hpp) de la manière suivante :

class Point {
public:
  Point();
  Point(int x, int y);
  void Move(int dx, int dy);
private:
  int x_;
  int y_;
};

La convention d’ajouter un underscore à la fin d’un attribut vient du “Google C++ Style Guide”.

Nous implémentons ensuite les méthodes dans un fichier point.cpp :

#include "point.hpp"

Point::Point() {
    x_ = 0;
    y_ = 0;
}

Point::Point(int x, int y) {
    x_ = x;
    y_ = y;
}

void Point::Move(int dx, int dy) {
    x_ += dx;
    y_ += dy;
}

Notez que les constructeurs (Point::Point) peuvent initialiser les attributs avec une syntaxe simplifiée :

Point::Point() : x_(0), y_(0) {};
Point::Point(int x, int y) : x_(x), y_(y) {};

Tout comme en Java, il est possible de définir des membres de classe statiques. Il suffit d’utiliser le mot clé static1.

Si un constructeur alloue des ressources (des fichiers, de la mémoire, …), il faut aussi retourner ces ressources au système. Cette opération se fait en général avec un destructeur. C’est comme en Java, sauf qu’en Java le destructeur s’appelle finalize et en C++, est le nom de la classe précédé du symbole ~. C’est une bonne pratique de toujours ajouter un destructeur virtuel, même s’il est vide2 :

class Point {
public:
  Point();
  virtual ~Point() {}; // destructor
  Point(int x, int y);
  void Move(int dx, int dy);
private:
  int x_;
  int y_;
};