Main menu:

Site search

Categories

mars 2008
L M M J V S D
 12
3456789
10111213141516
17181920212223
24252627282930
31  

Archive

C++ – Redéfinition vs surcharge

La confusion entre ces deux termes existe plus en anglais (overriding vs overloading)qu’en français. Néanmoins il est intéressant de rappeler les différences entre ces deux termes et leurs particularités surtout lorsque cela concerne des fonctions membres et qu’en plus, la redéfinition ou la surcharge se fait dans une classe dérivée.
Dans les deux cas, il s’agit d’avoir plusieurs fonctions avec le même nom.
Prenons l’exemple d’une classe de base Base qui possède deux fonctions f() et g() dont l’une est virtuelle.

class Base
{
  public:
    void f();
    virtual void g();
};

Dérivons maintenant une classe de notre classe Base et créons dans cette classe dérivée une fonction qui a la même signature que nos fonctions dans la classe Base:

class Derived1 : public Base
{
  public:
    void f();            // Redéfinit Base::f()
    virtual void g();    // Redéfinit Base::g()
};

La même signature signifie que la fonction a le même nom et les mêmes paramètres que la fonction originale. C’est bien le cas ici. f() et g() ont bien le même nom et les mêmes paramètres (ou abscence de paramètre). Notez que pour avoir la même signature qu’une fonction virtuelle, la fonction doit aussi être virtuelle ce qui est bien le cas ici. La fonction hérite de la classe de base son caractère virtuel et donc, le virtual devant la fonction pourrait être omis. Cependant, c’est une bonne pratique que de le mettre ne fut-ce que pour des raisons de code bien documenté.

class Derived2 : public Base
{
  public:
    void f(int);         // surcharge de Base::f()
    virtual void g(int); // surcharge de Base::g()
};

Si comme dans notre classe Derived2, le nom est le même mais que la signature est différente, on parle de surcharge de fonction.
Attention: dans le cas de Derived2, les deux fonctions f() et g() non seulement surchargent les deux fonctions f() et g() de Base mais en plus elles les cachent. Ce qui veut dire que f() et g() de Base ne sont plus accessibles. Par exemple, vous ne pouvez plus écrire ceci:

Derived2 d2;
d2.f();                  // erreur Base::f() est cachée

L’erreur donnée par g++ est l’erreur: no matching function for call to Derived2::f()

Si vous tenez à pouvoir utiliser la fonction f() dans la classe de base malgré le fait que la surcharge de cette fonction cache la fonction f() dans Base, vous devez réécrire votre classe Derived2 de cette façon:

class Derived2 : public Base
{
  public:
    using Base::f;       // permet d'utiliser Base::f()
    void f(int);         // surcharge de Base::f()
    virtual void g(int); // surcharge de Base::g()
};

La clause using vous permet de l’utiliser en spécifiant au compilateur qu’il s’agit de la fonction présente dans la classe de base.