6

Ran into an interesting issue today and am trying to understand why.

Consider the following:

class Base
{
public:
    Base(){}
    ~Base(){}
    static void function1(){}
        void function2()
        {
           int function1;
           function1 = 0;
           function1();   //<-compiler error
           function1 = 1;
        }
};

I am getting the following error:

expression preceding parentheses of apparent call must have (pointer-to-) function type

I think I understand why I am getting this error:

  1. When function1 is called by itself outside of function2(), it is actually a function pointer to function1().

  2. Inside the scope of function2, when int function1 is declared, 'function1 the variable' shadows 'function1 the function pointer'.

  3. When function1() is called inside function2(), it is assuming function1 is the variable and is giving an error.

  4. This is fixed by calling Base::function1(); inside function2().

My question is this: Why doesn't the compiler give an error when declaring int function1;? Shouldn't this not be allowed?

curiousguy
  • 8,038
  • 2
  • 40
  • 58
  • 2
    You're almost correct, except that there are no function *pointers* involved, only functions. Name shadowing is allowed, which is why it's not an error. – molbdnilo Jan 19 '16 at 21:20
  • 1
    `-Wshadow`, or whatever your compiler calls it. – Biffen Jan 19 '16 at 21:21
  • 2
    You can always declare any name in a new scope, it will hide the same name if that name already existed in an outer scope – M.M Jan 19 '16 at 21:27
  • Why do you think function1 must be a pointer? function1 is an identifier, and if you use it inside `function2` it resolves to a variable of type `int`, and you can't call a variable of type `int`. – user253751 Jan 19 '16 at 21:31
  • The compiler has the needed information to make this code sample compile correctly. If the variable `function1` was a functor or a lambda though, that would be ambiguous. And it would get very confusing and have a fair number of ambiguous usage cases depending on how you use `function1`, so it's easier/nicer to have simpler name lookup rules which prohibit this instead of trying to figure out your intention. – David Jan 19 '16 at 22:12

2 Answers2

13

The local variable overwrites the designator for the method in the local block. Try this->function1() to call it nevertheless.

Or better yet, rename the one or the other to help people reading your code avoiding confusion (and this includes your future yourself).

Murphy
  • 3,827
  • 4
  • 21
  • 35
3

To answer your question: "Should this be allowed":

In c++ you can have different entities with the same name if they exist in different scopes (like in your example). This is very useful feature in general, because it allows you to use whatever names you like for your entities assuming that you provide them in scope e.g. in namespace. Said that, compiler needs some algorithm to select entity when it sees name in code. In c++ standard process of matching name to declaration is called 'name lookup'. You can see description of this algorithm e.g. here cppreference or directly in standard draft.

robal
  • 368
  • 2
  • 8