2013-05-16 16 views
7

C'è questo codice:Definizione di classe e variabile con lo stesso nome

int x; 

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

class x {}; // works ok 

int main() { 
    return 0; 
} 

Perché è legale per definire variabile e classe con lo stesso nome, ma non è legale per definire variabile e funzione con lo stesso nome?

+1

Che cosa si intende per 'e x' per la coppia funzione-variabile? – chris

risposta

5

Quello che sta succedendo è specifico per C++. L'uso di x come nome di classe è nascosto.

sezione 3.3.7 (nome Nascondere) il paragrafo 2:

A nome della classe (9.1) o il nome di enumerazione (7.2) possono essere nascosti con il nome di un oggetto, una funzione o enumeratore dichiarate nel stesso ambito Se un nome di classe o di enumerazione e un oggetto, funzione o enumeratore sono dichiarati nello stesso ambito (in qualsiasi ordine) con lo stesso nome, il nome della classe o dell'enumerazione è nascosto ovunque l'oggetto, la funzione o il nome dell'enumeratore siano visibili.

13

primo caso: 2 identificatori

int x; 
void x(); 

Secondo caso: 1 Identifier, 1 TypeName

int x; 
class x {}; 

Il compilatore non può gestire il primo caso, perché si hanno 2 identificatori con lo stesso nome, quindi potrebbe esserci un'ambiguità. (Esempio: prova ad ottenere l'indirizzo di memoria di uno di questi.Questo è un caso in cui potrebbe sorgere un'ambiguità)

Il compilatore può gestire il secondo caso perché uno è un tipo e l'altro è un identificatore, e perché sa dove aspettarsi un tipo e dove aspettarsi un identificatore, non c'è ambiguità.

2

union, enum e struct (e suppongo anche class) hanno insieme separate "nome secchi" (non ha nulla a che fare con C++ namespace!) Da identificatori ordinari. Questo diventa chiaro in C, perché si deve precedere i nomi con struct ecc

io non ce l'ho per C++, ma questo è da C di serie:

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

Questo è completamente sbagliato. Gli unici "namespace" in C++ sono quelli che usano la parola chiave 'namespace' (o lo spazio dei nomi globale). Questo è un caso in cui C e C++ sono piuttosto diversi. –

+0

Questa non dovrebbe essere la risposta selezionata.Questo è sbagliato al 100% per C++ e questa domanda è codificata solo in C++. –

+0

@JamesKanze DavidHammen Lo so, "namespace" è la parola sbagliata, ma come dovrei chiamarla invece? Si prega di fare un backup della dichiarazione che queste regole di disambiguazione sono completamente sbagliate per C++. – typ1232

4

Ciò è necessario per le versioni precedenti -compatibilità con C (se ricordo, alcune intestazioni UNIX definiscono sia una struct che una variabile con lo stesso nome).

È possibile disambiguare tra una classe e un/funzione di variabili:

int x; 

class x {}; 

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

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

Ma non si può disambiguare tra una variabile e una funzione.

Vedere anche il libro "The Design and Evolution of C++" di Bjarne Stroustrup, §2.8.2.

Problemi correlati