Search code examples
c++ambiguous-callusing-declaration

Why there's no ambiguity in the expression `d.f(1);` below in main()?


Why there's no ambiguity in the expression d.f(1); below in main() between Base::f(int) and Derived::f(int) ?

class Base
{
    public:
    void f(int i) {}
    void f(int i, int j) {}
};

class Derived : public Base
{
    public:
    using Base::f;
    void f(int i) {}
};

int main()
{
    Derived d;
    d.f(1);
}

Solution

  • As others have written, there is no ambiguity because Derived::f(int) hides Base::f(int). You were probably expecting this to be the case only in the absence of the using declaration:

    using Base::f;
    

    But hiding still applies. Paragraph 7.3.3/15 of the C++11 Standard specifies:

    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 (8.3.5), cv-qualification, and ref-qualifier (if any) in a base class (rather than conflicting).

    It also provides an example quite similar to yours (see how the expression p->f(1) does not result in ambiguity, and D::f is picked instead):

    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)
    }