Что происходит, когда класс и функция имеют одно и то же имя?

#include <iostream>
using namespace std;

struct test
{
test(){cout<<"class"<<endl;}
};
void test(){cout<<"function"<<endl;}

int main()
{
test();
return 0;
}

Выход:

function

(VS2013 и gcc 4.8.1)

Почему функция выбрана? Разве это не двусмысленность?

18

Решение

Это называется сокрытие имени и описано в

3.3 Область действия [basic.scope]

3.3.1 Декларативные регионы и области действия [basic.scope.declarative]

4) Учитывая набор деклараций в одном декларативном регионе, каждый из
который указывает то же безоговорочное имя,
— все они относятся к
один и тот же объект или все относятся к функциям и шаблонам функций; или же

— ровно одно объявление должно объявлять имя класса или перечисление
имя, которое не является именем typedef, и другие объявления должны все
ссылаются на одну и ту же переменную или перечислитель, или все ссылаются на функции
и шаблоны функций; в этом случае имя класса или перечисление
имя скрыто
(3.3.10). […]

Акцент мой.

Обратите внимание, что изменение порядка объявления не влияет на результат:

void test(){cout<<"function"<<endl;}

struct test
{
test(){cout<<"class"<<endl;}
};

int main()
{
test();
return 0;
}

все еще распечатывает function,

Если это не очевидно, не делай этого 🙂

18

Другие решения

Из N3485 §3.3.10 [basic.scope.hiding] / 2:

Имя класса (9.1) или имя перечисления (7.2) можно скрыть по имени переменной, члена данных,
Функция или перечислитель объявлены в той же области видимости.

Следовательно, функция имеет приоритет над классом.

Как уже упоминалось в Комментарии, класс по-прежнему доступен через class или же struct ключевое слово. Если бы класс имел приоритет, функция была бы недоступна.

9

Я не уверен, что любой из предыдущих ответов является «почему» для вашего конкретного случая.

Не пойми меня неправильно; Они правдивы и точны.

Я просто думаю, что это проще.

В вашем примере вы никогда не создаете экземпляр структуры.

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

Поскольку вы никогда не ссылались на него, он никогда не называется.

Приоритет имени и тому подобное здесь не применяются, поскольку вы никогда не создавали экземпляр структуры.

Надеюсь это поможет,

-Джон

-3