Почему метод класса не может вызвать глобальную функцию с тем же именем?

Следующий код показывает, как функция вызывает другую функцию.
У обеих функций одинаковое имя, но разные подписи.
Это работает, как и ожидалось.

//declarations
void foo();
void foo(int);

int main(){
  foo();
}

//definitions
void foo(){
    foo(1);
}
void foo(int){}

Единственное отличие, которое я сейчас сделаю, это обернуть одну из функций в структуру:

//declarations
struct Bar{
    void foo();
};
void foo(int);

int main(){
  Bar bar;
  bar.foo();
}

//definitions
void Bar::foo(){
    foo(1);
}
void foo(int){}

Это не удается скомпилировать.

In member function ‘void Bar::foo()’:
error: no matching function for call to ‘Bar::foo(int)’
         foo(1);
              ^
note: candidate: void Bar::foo()
     void Bar::foo(){
          ^
note:   candidate expects 0 arguments, 1 provided

Я не понимаю, почему он хочет вызвать foo(int) как метод, когда существует глобальная функция.
Он ничего не говорит о двусмысленности, он просто не может найти функцию.

Почему это происходит, и как я могу это исправить?

примечание: я оборачиваю старый код C в оболочку C++, и большинство методов C++ являются вызовами глобальных функций C, которые неявно передаются в обернутой структуре. Это похоже на то, что происходит выше (с точки зрения ошибок компилятора).


person Trevor Hickey    schedule 22.10.2015    source источник
comment
Именно так работает неквалифицированный поиск имени, я уверен, что у нас есть несколько дубликатов, если вы будете искать это.   -  person Praetorian    schedule 23.10.2015
comment
stackoverflow.com/questions/7149922/   -  person Ozair Kafray    schedule 04.04.2017


Ответы (1)


Функция-член скрывает файл global. Он находит имя в контексте класса, поэтому не продолжает искать его в других контекстах.

Вам нужно вызвать его так:

::foo(1);

Другим решением является использование предварительного объявления внутри функции, например:

void Bar::foo()
{
    void foo(int);
    foo(1);
}

Как предлагает Преториан, вот еще один вариант:

void Bar::foo()
{
    using ::foo;
    foo(1);
}
person SHR    schedule 22.10.2015
comment
Или добавьте using ::foo; в Bar::foo - person Praetorian; 23.10.2015
comment
В Visual Studio нельзя добавлять using без имени класса. он дает следующую ошибку: foo: символ не может использоваться в объявлении использования члена только внутри разрешенной функции и работает как объявление fw. - person SHR; 23.10.2015
comment
Какая версия ВС? Это компилируется на VS2015. - person Praetorian; 23.10.2015
comment
@Praetorian внутри функции работает (так же, как и предварительное объявление), в классе, который он не компилируется, я добавлю ваше решение в ответ... - person SHR; 23.10.2015
comment
Да, не могу сделать это в рамках класса. В этом случае объявление using может использоваться только для включения членов базового класса в область видимости. - person Praetorian; 23.10.2015