En C++, l'ordre de recherche des noms est régi par des règles de résolution des noms (name lookup), qui prennent en compte les zones de visibilité (scope), la dissimulation (hiding) et les spécificités de l'héritage. Points clés :
Résolution des conflits :
class Base { public: void foo(int) {} }; class Derived : public Base { public: using Base::foo; void foo(double) {} // Version surchargée };
Base::x ou Base::foo().Exemple d'ambiguïté en héritage diamond :
struct A { int x; }; struct B : virtual A {}; struct C : virtual A {}; struct D : B, C { void test() { x = 42; } // OK : x est unique, grâce au virtuel };
Si une méthode foo(int) est déclarée dans la classe de base, et foo(double) dans la classe dérivée, foo(int) est-il accessible depuis l'objet de la classe dérivée ?
Réponse : Non, la méthode foo(double) "masque" toutes les versions surchargées de foo dans la classe de base. Pour accéder à foo(int), il faut écrire explicitement using Base::foo ou Base::foo dans l'appel.
Exemple :
class Base { public: void foo(int) { } }; class Derived : public Base { public: void foo(double) {} }; Derived d; d.foo(3); // Erreur ! foo(int) n'est pas visible
Utilisons :
class Derived : public Base { public: using Base::foo; void foo(double) {} }; d.foo(3); // Tout fonctionne
Histoire
Dans un projet avec héritage multiple, une classe a été héritée de deux bases avec des méthodes foo() identiques. Les auteurs n'ont pas utilisé l'héritage virtuel, ce qui a créé deux copies de la classe de base — tous les appels à foo() devenaient ambigus, le compilateur refusait de compiler le code. Cela a été résolu par l'utilisation de l'héritage virtuel et l'indication explicite de Base::foo() lors de l'appel.
Histoire
Dans un moteur graphique, une classe dérivée définissait son propre draw(), sans faire using pour draw() de la classe de base. Lors du refactoring, la mauvaise version de draw() était appelée — certaines parties de l'interface ne se dessinaient plus. L'erreur a été trouvée seulement après un examen approfondi de la structure des classes.
Histoire
Lors du passage à un nouveau compilateur, la compilation est devenue impossible en raison de l'ambiguïté des noms lors de l'héritage multiple et virtuel. Une implémentation auparavant fonctionnelle ne prenait pas en compte les différentes chaînes d'inclusion, conduisant à des ensembles de noms différents dans l'unité de traduction.