Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

member function hiding free function

void foo(int)
{
}

class X
{
    void foo()
    {
    }

    void bar()
    {
        foo(42);
        // error: no matching function for call to 'X::foo(int)'
        // note: candidate is:
        // note: void X::foo()
        // note:   candidate expects 0 arguments, 1 provided        
    }
};

Why is C++ unable to call the free function (which is the only one with the correct signature)?

like image 700
fredoverflow Avatar asked Jan 28 '12 12:01

fredoverflow


3 Answers

Because the two identifiers are defined in different scopes, and overload resolution only concerns about functions in the same scope. Once the compiler finds that the class has a foo, it stops climbing up to wider scopes (C++11 §3.4.1/1), so the free function foo is hidden.

You need to use a qualified name to refer to the global foo:

::foo(42);
like image 59
kennytm Avatar answered Nov 04 '22 15:11

kennytm


The logical reason is Consistency.

  • Suppose as per the suggestion, compiler resolves foo(42) to ::foo(int).
  • Now after sometime, if you change X::foo() to X::foo(int) then foo(42) will be resolved to X::foo(int). Which is not consistent.

That is the also the reason why derived class function hides base class function when there are similar names.

Such cases can be resolved in 2 ways;

(1) Give fully qualified name (e.g. ::foo(42))

(2) Use using utility; e.g.

void bar()
{
  using ::foo;
  foo(42);
}
like image 38
iammilind Avatar answered Nov 04 '22 16:11

iammilind


A name in an inner scope hides names in outer scopes. It doesn't matter if it is a function or something else, or if you are in a class or a namespace.

Only if the name lookup finds several functions with the same name will the overload resolution kick in to try to select the one that is the best match for the call.

like image 2
Bo Persson Avatar answered Nov 04 '22 16:11

Bo Persson