Я наткнулся на реализацию функции, которая повторяет имя типа для параметра того же типа. Код компилируется и, кажется, делает именно то, что задумано. Вот минимизированная версия:
#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
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
Да, это действительно. Вы объявляете переменную (параметр) во внутренней области видимости, которая скрывает имя от внешней области видимости.
Конечно, не очень хорошая идея в этом случае.
Это действительно. Он скрывает переменную от внешней области видимости. Сокрытие, как это обычно называют слежка и ваш компилятор, вероятно, имеет предупреждение, которое вы можете включить, чтобы сообщить вам, когда это происходит (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
}
В словах Страуструпа:*
Объявление имени в блоке может скрыть объявление в
включающий блок или глобальное имя. То есть имя может быть переопределено как
ссылаются на другую сущность в блоке. После выхода из блока,
имя возобновляет свое прежнее значение.
* Страуструп: язык программирования C ++, 4-е издание; Раздел 6.3.4 Область применения; Страница 157