Function with same name but different signature in derived class not found

It is because name lookup stops if it finds a name in one of your bases. It won’t look beyond in other bases. The function in B shadows the function in A. You have to re-declare the function of A in the scope of B, so that both functions are visible from within B and C:

class A
{
    public:
    void foo(string s){};
};

class B : public A
{
    public:
    int foo(int i){};
    using A::foo;
};

class C : public B
{
    public:
    void bar()
    {
        string s;
        foo(s);
    }
};

Edit: The real description the Standard gives is (from 10.2/2):

The following steps define the result of name lookup in a class scope, C. First, every declaration for the
name in the class and in each of its base class sub-objects is considered. A member name f in one sub-
object B hides a member name f in a sub-object A if A is a base class sub-object of B. Any declarations
that are so hidden are eliminated from consideration. Each of these declarations that was introduced by a
using-declaration is considered to be from each sub-object of C that is of the type containing the declara-
tion designated by the using-declaration.96) If the resulting set of declarations are not all from sub-objects
of the same type, or the set has a nonstatic member and includes members from distinct sub-objects, there is
an ambiguity and the program is ill-formed. Otherwise that set is the result of the lookup.

It has the following to say in another place (just above it):

For an id-expression [something like “foo”], name lookup begins in the class scope of this; for a qualified-id [something like “A::foo”, A is a nested-name-specifier], name lookup begins in the scope of the nested-name-specifier. Name lookup takes place before access control (3.4, clause 11).

([…] put by me). Note that means that even if your foo in B is private, the foo in A will still not be found (because access control happens later).

Leave a Comment