3

For example in below program I undo name hiding by "using" keyword. If I have base and one derived class "im getting expected ambiguous call error". But if I have two derived class(child and grand child) now child and grand child having same overloaded function here also I undo name hiding by "using" keyword. But It is getting compiled and got output. My question is why im not getting error as "ambiguous call to overloaded function".

class baseNameHiding
{
protected:
int nameHidingexample(int t)
{
    cout<<"im baseeeeeeeeeeee"<<endl;
    return 0;
}
};
class derivedNameHiding:public baseNameHiding
{   
public:
    float nameHidingexample(float s)
    {
        cout<<"im derived"<<endl;
        return 0;
    }
    using baseNameHiding::nameHidingexample;

};
class grandDerivedNameHiding:public derivedNameHiding
{
public:
    float nameHidingexample(float f)
    {
        cout<<"im grand derived"<<endl;
        return 0;
    }
    using baseNameHiding::nameHidingexample;
    using derivedNameHiding::nameHidingexample;

};
int main()
{
    char a;float f = 0.0;
    derivedNameHiding derived;
    derived.nameHidingexample(0);
    grandDerivedNameHiding grandchild;
    grandchild.nameHidingexample(f);
    cin>>a;
} 


//output
im baseeeeeeeeeeee
im grand derived
  • 1
    The key is `nameHidingexample(0)` vs `nameHidingexample(f)`: the first `0` is an `int`, while the second one is a `float`. If I turn the first `0` into `f`, I get a consistent behavior (output: derived/grand derived). My guess is that promotion is applied at an unexpected time, but I'm not an expert on C++ argument dependent lookup to know the details. (And honestly the code tries quite hard to involve some corner case of the spec in a confusing/lawyer-ish way.) – chi Mar 28 '15 at 13:53

1 Answers1

3

You have encountered a special rule of using-declarations. C++14 [namespace.udecl]/15:

When a using-declaration brings names from a base class into a derived class scope, member functions and member function templates in the derived class override and/or hide member functions and member function templates with the same name, parameter-type-list, cv-qualification, and ref-qualifier (if any) in a base class (rather than conflicting). [...] [ Example:

struct B {
    virtual void f(int);
    virtual void f(char);
    void g(int);
    void h(int);
};

struct D : B {
    using B::f;
    void f(int);    // OK: D::f(int) overrides B::f(int);

    using B::g;
    void g(char);   // OK

    using B::h;
    void h(int);    // OK: D::h(int) hides B::h(int)
};

void k(D* p)
{
    p->f(1);        // calls D::f(int)
    p->f(’a’);      // calls B::f(char)
    p->g(1);        // calls B::g(int)
    p->g(’a’);      // calls D::g(char)
}

end example ]

dyp
  • 38,334
  • 13
  • 112
  • 177
  • The `;` in the comment *OK: D::f(int) overrides B::f(int);* is in fact in the C++14 IS. – dyp Mar 28 '15 at 14:31