2013-05-16 3 views
7

Существует этот код:Определение класса и переменной с тем же именем

int x; 

//void x(); // error: redefinition of 'x' as different kind of symbol 

class x {}; // works ok 

int main() { 
    return 0; 
} 

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

+1

Что вы предлагаете '& x' для пары функций-переменных? – chris

ответ

5

Что здесь происходит, характерно для C++. Использование x в качестве имени класса скрыто.

Раздел 3.3.7 (Имя Скрытие) пункт 2:

Имя класса (9,1) или имя перечисления (7,2) может быть скрыто по имени объекта, функция или переписчик объявлен в такой же объем. Если имя класса или перечисления, а также объект, функция или перечислитель объявлены в той же области (в любом порядке) с тем же именем, имя класса или перечисления скрыто везде, где вид объекта, функции или перечислителя является видимым.

13

Первый случай: 2 Идентификаторы

int x; 
void x(); 

Второй случай: 1 Идентификатор, 1 Имя типа

int x; 
class x {}; 

Компилятор не может обрабатывать первый случай, потому что у вас есть 2 идентификаторы с одно и то же имя, поэтому может быть двусмысленность. (Пример: попробуйте получить адрес памяти одного из них. Это один случай, когда может возникнуть неоднозначность)

Компилятор может обрабатывать второй случай, поскольку он является типом, а другой является идентификатором, и потому, что он знает, где ожидать типа и где ожидать идентификатора, нет никакой двусмысленности.

2

union, enum и struct (и я полагаю, class тоже) вместе имеет раздельное «имя ведро» (не имеет ничего общего с пространствами имен C++!) Из обычных идентификаторов. Это становится ясным в C, потому что вы должны префикс имен с struct и т.д.

У меня нет его на C++, но это от стандарта C:

6.2.3 Name spaces of identifiers 

If more than one declaration of a particular identifier is visible at 
any point in a translation unit, the syntactic context disambiguates uses 
that refer to different entities. 

Thus, there are separate name spaces for various categories of identifiers, 
as follows: 
— label names (disambiguated by the syntax of the label declaration and use); 

— the tags of structures, unions, and enumerations (disambiguated by 
following any32) of the keywords struct, union, or enum); 

— the members of structures or unions; each structure or union has a 
separate name space for its members (disambiguated by the type of the 
expression used to access themember via the . or -> operator); 

— all other identifiers, called ordinary identifiers (declared in ordinary 
    declarators or as enumeration constants). 
+0

Это совершенно неправильно. Единственными «пространствами имен» на C++ являются те, которые определены с использованием ключевого слова 'namespace' (или глобального пространства имен). Это один случай, когда C и C++ совершенно разные. –

+0

Это не должен быть выбранный ответ.Это 100% неправильно для C++, и этот вопрос отмечен только C++. –

+0

@JamesKanze DavidHammen Я знаю, что «пространства имен» - неправильное слово, но что я должен называть? Пожалуйста, создайте резервную копию своего заявления о том, что эти правила неоднозначности являются неполными для C++. – typ1232

4

Это необходимо для назад -совместимость с C (если я помню, некоторые заголовки UNIX определяют как структуру, так и переменную с тем же именем).

Вы можете неоднозначность между классом и переменной/функции:

int x; 

class x {}; 

int main() 
{ 
    x = 42; // global int x 

    //x obj; // error 
    class x obj; // use class-tag to disambiguate 
} 

Но вы не можете неоднозначность между переменной и функции.

См. Также книгу «Дизайн и эволюция C++» by Bjarne Stroustrup, §2.8.2.

Смежные вопросы