Один и тот же идентификатор для типа и объекта в объявлении

Я наткнулся на реализацию функции, которая повторяет имя типа для параметра того же типа. Код компилируется и, кажется, делает именно то, что задумано. Вот минимизированная версия:

#include <iostream>

using namespace std;

struct X {
    int v;
};

void print_X(const X& X)   // <--- here the identifier X has *two different meanings*
{
    cout << "X.v:" << X.v << endl;
}

Код был разработан против Borland C++ 5.6.4

Я пробовал несколько разных и более современных компиляторов:

Все принимают это без жалоб.

Я не думаю, что это хороший C++, но...

Это действительно C++? И если да, будет ли это в силе в будущем?

Обновить

Как ужасно! Только теперь я вижу, что то же самое верно для простого объявления переменной:

X X;

Демо: http://ideone.com/a9GM49

Обновление № 2

C++ разделяет эту функцию с языком C:

#include <stdio.h>

typedef struct X {
    int v;
} X;

int main()
{
    X X;
    X.v = 7;
    printf("X.v:%d\n", X.v);
    return 0;
}

Демо: http://ideone.com/nheZTa

3 ответа

Да, это действительно. Вы объявляете переменную (параметр) во внутренней области видимости, которая скрывает имя от внешней области видимости.

Конечно, не очень хорошая идея в этом случае.

Это действительно. Он скрывает переменную от внешней области видимости. Такое скрытие обычно называется теневым копированием, и ваш компилятор, вероятно, имеет предупреждение, которое вы можете включить, чтобы сообщить вам, когда это происходит (gcc имеет -Wshadow).

Вот еще один пример:

int x; // global variable - always accessible as ::x
int main(int x, char** argv) { // this 'x' hides global 'x'
    // This is the only place you can get at the argument 'x'
    // before it is hidden by the line below.
    int x; // this subsequently hides the function argument 'x'
    {
        int x; // hides the 'x' at function scope
        for (int x = 0; x < 42; ++x) { // this 'hides 'x' in our nested scope
            // The for loop induction variable 'x' is what's in scope here
        }
        // Now 'x' is again the nested-scope 'x'
    }
    // Here 'x' again refers to the function scope 'x'
}
// At any point in time you can get access to the 'x' that is directly
// in scope *or* the global 'x' (as '::x')
// But you cannot access the other 'x's until you are back in
// their respective scopes.

Но старайтесь избегать подобных вещей. Это быстро приводит к путанице и ошибкам.

Делая это, вы скрываете глобальное имя внутри функционального блока.

void print_X(const X& X, const X& Y)  //won't compile

void print_X(const X& X){
   X myX;    //again, won't compile
}

В словах Страуструпа:*

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


* Stroustrup: язык программирования C++, 4-е издание; Раздел 6.3.4 Область применения; Страница 157

Другие вопросы по тегам