Search code examples
c++inheritanceargument-dependent-lookup

Compiler can't find base class method by ADL


What's going on here -- why does this not compile?

#include <iostream>
class Base {
    void print(double d) {
        std::cout << "Base: " << d << std::endl;
    }
};

class Derived : public Base {
void print(std::string const & str) {
        std::cout << "Derived: " << str << std::endl;
    }
};

int main(int argc, char* argv[]) {
    Derived d;
    d.print(2.);
    d.print("junk");
}

(Errors in both MinGW and VC11 with something equivalent to No conversion from double to std::string.)

If I change the name of the print function in Derived, it compiles successfully, so clearly Derived::print(string const &) is masking Base::print(double) somehow. But I was under the impression that the function signature included the argument type(s) and so this masking should occur here. Is that not correct in the case of base class methods?


Solution

  • No, it is not correct : name hiding occurs when a function with the same name is declared in the same scope : here print in Derived hides the print of Base.

    Arguments names/types are ignored in this (first) step of functions lookup.

    You can bring the declaration of the Base function within the Derived one with a using declaration:

    using Base::print
    

    If you do so, regular overload resolution will take place.

    For details about why hiding occurs in this Derived/Base situation, I suggest this other SO post that perfectly answers it.

    As for the standard, this particular rule is defined in section 3.3.1 :

    Name hiding [basic.scope.hiding]

    A name can be hidden by an explicit declaration of that same name in a nested declarative region or derived class (10.2).