«Объекты с одинаковыми именами, определенными во внешней области видимости, скрыты» не содержит - PullRequest
0 голосов
/ 09 февраля 2020

В пятом издании книги "C ++ Primer" на второй странице Раздела 18.2.2 есть строка "Объекты с одинаковыми именами, определенными во внешней области видимости, скрыты". Это предложение подчеркнуто красным следующим образом:

enter image description here

Я попытался повторить утверждение в эксперименте. Экспериментальный код выглядит следующим образом:

#include <cstdlib>
#include <iostream>
#include <cmath>

int abs(int n) {
    std::cout << "here" << std::endl;
    return 0; 
}

void test() {
    using std::abs;
    std::cout << abs(7) << std::endl;    
}

int main(int argc, char** argv) {
    test();

    return 0;
}

using std::abs является объявлением об использовании, поэтому, если утверждение в «C ++ Primer» является правильным, пользовательская функция abs() должна быть скрыта с помощью std::abs(). Но в результате вызывается определяемая пользователем функция abs(). Так что, если книга верна, в моем эксперименте должно быть что-то не так. Как мне написать экспериментальный код для подтверждения предложения в «C ++ Primer»? Если книга неверна, какой должна быть правильная экспозиция, которая может заменить предложение? Спасибо.

PS: я пробовал как в Windows10 + VS2015, так и в Ubuntu 18.04 + g ++ 7.4. Оба вызвали пользовательский abs() и распечатали «здесь».

1 Ответ

0 голосов
/ 09 февраля 2020

Книга могла бы лучше объяснить это, но это не так. Просто правила поиска для перегрузок являются несколько более нюансированными, потому что перегрузки с одинаковыми именами могут сосуществовать в одной и той же области видимости, поэтому объявление использования хорошо сочетается с этим.

Если бы вы действительно определяли новый объект, который не является перегрузкой, например

void test() {
    int abs = 0;
    std::cout << abs(7) << std::endl;    
}

Тогда это выражение вызова будет неправильно сформировано, поскольку внешние вызываемые объекты скрыты внутренней переменной int. Обойти это можно было бы с помощью объявления об использовании

void test() {
    int abs = 0;
    {
      using std::abs; // Let the name refer to the functions again
      using ::abs;    // the variable abs is hidden
      std::cout << abs(7) << std::endl;    
    }
}

Этот эксперимент должен проиллюстрировать, что означала книга.

...