L'héritage

La syntaxe de l’héritage en C++ est semblable à celle de Java. En C++, nous utilisons : public au lieu de extends pour indiquer l’héritage.

Si nous partons du principe qu’un pixel est un point avec de la couleur, nous pouvons alors définir la classe Pixel ainsi :

class Pixel : public Point {
public:
    Pixel(int x, int y, uint16_t color);
    void Paint();
private:
    uint16_t color_;
};

En Java, on appelle le constructeur de la classe parente avec le mot clé super. En C++, on appelle simplement le constructeur de la classe parente directement avec son nom :

Pixel::Pixel(int x, int y, uint16_t color) : Point(x, y) {
    color_ = color;
}

Dans l’exemple ci-dessus, l’appel du constructeur de la classe parente est à l’extérieur du body et l’attribut color_ est initialisé à l’intérieur.

On peut aussi initialiser l’attribut à l’extérieur :

Pixel::Pixel(intx, inty, uint16_tcolor)
    : Point(x, y)
    , color_(color)
{}

Il n’est cependant pas possible d’appeler le constructeur de la classe parente à l’intérieur du body; l’appel doit être à l’extérieur,

Une autre caractéristique de C++ est que par défaut, les méthodes ne peuvent pas être redéfinies dans une classe dérivée. C’est l’équivalent d’une méthode final de Java. Pour permettre une redéfinition d’une méthode, il faut préfixer la déclaration avec le mot clé virtual.

class Pixel : public Point {
public:
    Pixel(int x, int y, uint16_t color);
    virtual void Paint();
private:
    uint16_t color_;
};

On peut maintenant définir un SuperPixel qui hérite de Pixel et qui redéfinit Paint :

class SuperPixel : public Pixel {
public:
    SuperPixel(int x, int y, uint16_t color) : Pixel(x, y, color) {};
    void Paint();
};

void SuperPixel::Paint() {
    ...
}

Pour bien montrer qu’une méthode est redéfinie, on peut ajouter le mot clé override après la déclaration :

class SuperPixel : public Pixel {
public:
    SuperPixel(int x, int y, uint16_t color) : Pixel(x, y, color) {};
    void Paint() override;
};

Comme en Java, les attributs privés ne sont pas accessibles dans les classes dérivées. On peut les déclarer public, mais si on ne souhaite pas ouvrir autant et n’autoriser l’accès qu’aux classes dérivées, on peut utiliser le modificateur protected.

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

Le langage C++ est très complexe et cette courte introduction n’en a effleuré que la surface, mais ça devrait vous permettre de réaliser les TPs. Si vous souhaitez vous perfectionner en C++, vous trouverez beaucoup de références en lignes ainsi que de nombreux ouvrages spécialisés.

Note

Notez que le C++ supporte l’héritage multiple. C’est-à-dire qu’une classe peut avoir plusieurs parents et contrairement à Java, il n’y a pas de syntaxe spécifique pour une interface. Par contre, vous pouvez déclarer une méthode abstraite (l’équivalent de abstract en Java) en mettant = 0 après la signature de la méthode. Par exemple :

virtual int f() = 0;

En plus des méthodes, le C++ permet aussi de redéfinir les opérateurs tels que + ou =.

Ces concepts sont intéressants, mais leurs détails dépassent le cadre de ce chapitre.