Surdéfinition du gestionnaire de signal par défaut

Jusqu'ici nous vous avons montré la réalisation d'actions en réponse à une pression de bouton à l'aide d'un gestionnaire de signal. C'est assurément un bon moyen de réaliser les choses, mais ce n'est pas le seul.

Au lieu de connecter laborieusement les gestionnaires de signal aux signaux, vous pouvez simplement créer une nouvelle classe qui hérite d'un élément graphique — disons, un bouton —, puis surdéfinir le gestionnaire de signal par défaut, tel que Button::on_clicked(). Cela peut se révéler plus simple que d'accrocher des gestionnaires de signal pour chaque chose.

Le sous-classement n'est pas toujours la meilleure façon de réaliser les choses. Il est uniquement utile quand vous souhaitez que l'élément graphique gère son propre signal par lui-même. Si vous souhaitez qu'une autre classe gère le signal, il faut se connecter à un gestionnaire séparé. C'est encore plus vrai si vous voulez que plusieurs objets gèrent le même signal ou si vous voulez qu'un seul gestionnaire de signal réponde au même signal à partir d'objets différents.

Les classes gtkmm ont été conçues dans l'optique de surdéfinitions ; elles comportent des fonctions membres virtuelles spécialement pensées pour être surdéfinies.

Regardons un exemple de surdéfinition :

#include <gtkmm/button.h>

class OverriddenButton : public Gtk::Button
{
protected:
    virtual void on_clicked();
}

void OverriddenButton::on_clicked()
{
    std::cout << "Hello World" << std::endl;

// appeler la version de la classe de base de la fonction membre:
    Gtk::Button::on_clicked();
}

Ici nous définissons une nouvelle classe nommée OverriddenButton qui hérite de Gtk::Button. La seule chose que nous modifions est la fonction membre on_clicked() ; cette fonction membre est appelée chaque fois qu'un objet Gtk::Button émet le signal clicked. Elle affiche « Hello World » sur stdout, puis appelle la fonction membre originelle pour que Gtk::Button fasse ce qu'il a à faire quand il n'est pas surdéfini.

Il n'est pas toujours nécessaire d'appeler la fonction membre du parent ; certaines fois vous ne le souhaiterez pas. Notez que nous avons appelé la fonction membre du parent après avoir écrit « Hello World », mais nous aurions pu l'appeler avant. Dans cet exemple simple, cela n'a pas beaucoup d'importance, mais parfois si. Avec les signaux, il n'est pas facile de modifier des détails de ce type, et vous pouvez ici faire des choses que vous ne pourrez absolument pas faire avec des gestionnaires de signal connectés : vous pouvez appeler la fonction membre du parent au milieu de votre code personnalisé.