10
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)?

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • 2
    In this case, you can use `:: foo(42)` to access the external foo. [Ideone demo](http://ideone.com/6HljO). But I don't know much about namespaces. – Aaron McDaid Jan 28 '12 at 12:23
  • I consider this to be one Achilles heel of C++. It makes elegant use of common overloaded free function names impossible, such as isempty(thing), where there are many overloads for isempty given types of things, while allowing a thing.isempty() to also exist. Stupid, unfortunate, clunky. – Mordachai Feb 07 '14 at 20:01

6 Answers6

12

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);
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
5

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);
}
iammilind
  • 68,093
  • 33
  • 169
  • 336
  • 1
    If someone later adds foo(int) member, then they're explicitly intending this. Bad language design, IMO. – Mordachai Feb 07 '14 at 20:02
2

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.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
1

Really like your question. Also I could say, use this syntax:

::foo(42);

But I can say that in my opinion it's more elegant and good programming, set namespaces, so you can write something like this:

namespace MyNameSpace
{
   void foo(int){}

   class X
   {
        void foo(){}

        void bar()
        {
            MyNameSpace::foo(42);
        }
   };
};

This is a good thing because Namespaces allow to group classes, objects and functions under a name.

PS: Then this help you to understand the meaning of write ::foo(42); when you haven't any namespace.

Omar
  • 16,329
  • 10
  • 48
  • 66
0

I cannot answer the why part of your question -- I do not know what was the rationale behind that in the language spec.

To call the global function in your example, use the :: syntax:

::foo(42);
0

The reason for this is the fact, that the compiler will look for a matching function name first, ignoring return values and parameters. When inside a class, it will try to look for a matching member there (in fact, it will look through all scopes going "upwards"; local scope(s), function scope, class scope, namespace scope, global scope, etc.).

X::foo is the first matching name. THEN (not before) it will try to pick the right overload (if there are multiple declarations) based on the parameters (which is the reason you can overload the same function with different parameters but not different return values only) and then it will check the return value (if there's any).

Mario
  • 35,726
  • 5
  • 62
  • 78