In C++ wordt de volgorde van naamzoeken geregeld door de regels voor naamresolutie (name lookup), die rekening houden met scopes, verbergen (hiding) en de specifics van overerving. Belangrijke punten:
Conflict resolutie:
class Base { public: void foo(int) {} }; class Derived : public Base { public: using Base::foo; void foo(double) {} // Overloaded versie };
Base::x of Base::foo().Voorbeeld van ambiguïteit bij diamond inheritance:
struct A { int x; }; struct B : virtual A {}; struct C : virtual A {}; struct D : B, C { void test() { x = 42; } // OK: x is er maar één, dankzij virtual };
Als in de basis class een methode foo(int) is gedeclareerd en in de afgeleide class foo(double), is foo(int) toegankelijk vanuit een object van de afgeleide class?
Antwoord: Nee, de methode foo(double) "verbergt" alle overloaded versies van foo uit de basis class. Voor toegang tot foo(int) moet expliciet using Base::foo of Base::foo in de aanroep worden geschreven.
Voorbeeld:
class Base { public: void foo(int) { } }; class Derived : public Base { public: void foo(double) {} }; Derived d; d.foo(3); // Fout! foo(int) is niet zichtbaar
Gebruik:
class Derived : public Base { public: using Base::foo; void foo(double) {} }; d.foo(3); // Alles werkt
Verhaal
In een project met meervoudige overerving verscheen er een class, geërfd van twee basisklassen met dezelfde methoden foo(). De auteurs gebruikten geen virtual overerving, waardoor er twee kopieën van de basis class werden aangemaakt — alle verwijzingen naar foo() werden ambigu, de compiler weigerde de code te compileren. Dit werd opgelost door virtual overerving toe te passen en expliciete aanroep van Base::foo() te gebruiken.
Verhaal
In een grafische engine definieerde een afgeleide class zijn eigen draw(), zonder using voor draw() van de basis class. Bij het refactoren van de code werd de verkeerde versie van draw() aangeroepen — delen van de interface stopten met renderen. De fout werd pas gevonden na grondige analyse van de klasstructuur.
Verhaal
Bij de overstap naar een nieuwe compiler werd compilatie onmogelijk door ambiguïteit van namen bij meervoudige en virtuele overerving. Een eerder werkende implementatie hield geen rekening met verschillende ketens van include, wat leidde tot verschillende sets van namen in de translatie-eenheid.