2013-06-25 12 views
11

gdy piszę następujący kod pobiera skompilowany i wykonany prawidłowo:Dlaczego stosowanie dyrektywy zachowuje się inaczej w zasięgu globalnym i zasięgu lokalnym?

#include <iostream> 
using namespace std; 

namespace first 
{ 
    int x = 5; 
    int y = 10; 
} 

namespace second 
{ 
    double x = 3.1416; 
    double y = 2.7183; 
} 

int main() { 
    using namespace first; //using derective 
    using second::y; 
    cout << x << endl; 
    cout << y << endl; 
    return 0; 
} 

Ale jeśli piszę używając dyrektyw poza funkcją głównego następująco,

using namespace first; //using derective 
using second::y; 
int main() { 
    cout << x << endl; 
    cout << y << endl; 
    return 0; 
} 

Daje ten błąd kompilacji:

g++  namespace03.cpp -o namespace03 
namespace03.cpp: In function ‘int main()’: 
namespace03.cpp:20:11: error: reference to ‘y’ is ambiguous 
namespace03.cpp:13:10: error: candidates are: double second::y 
namespace03.cpp:7:7: error:     int first::y 
make: *** [namespace03] Error 1 

Czy ktoś może wyjaśnić, dlaczego używanie dyrektywy zachowuje się inaczej, gdy jest używane wewnątrz main i poza main?

Odpowiedz

10

Deklaracja użycia jest po prostu deklaracją. using second::y; wewnątrz głównej jest podobna do deklaracji zmiennej y w tym zakresie, która ukrywa wszystkie inne y w zasięgu globalnego obszaru nazw. Gdy używasz using second::y; w zasięgu globalnym, nie ukryłeś żadnych nazw, ponieważ oba y są w tym samym zakresie.

Wyobraź sobie Pierwszym przykładem jest jak następuje (patrz komentarze objaśniającą):

namespace first 
{ 
    int x = 5; 
    int y = 10; 
} 

int main() { 
    using namespace first; // This makes first::y visible hereafter 
    int y = 20; // This hides first::y (similar to using second::y) 
    cout << x << endl; 
    cout << y << endl; // Prints 20 
} 

Jednak Drugim przykładem jest jak:

namespace first 
{ 
    int x = 5; 
    int y = 10; 
} 
using namespace first; // This makes first::y visible in global scope 
int y = 20; // This is global ::y 
int main() { 
    cout << x << endl; 
    cout << y << endl; // Error! Do you mean ::y or first::y? 
} 
+0

Dziękuję Jesse za szybką odpowiedź ... Proszę, popraw mnie, jeśli się mylę ... Ale kiedy używa się dyrektyw, to w głównej funkcji wciąż będą 2 deklaracje y. Jeśli tak, to dlaczego kompilator daje problem tylko w drugim przypadku? – Amrit

+1

@ user2235938: Istnieją dwie deklaracje typu "y", ale deklaracja użycia deklaruje "second :: y" wewnątrz głównej, a "first :: y" jest zadeklarowana w zasięgu globalnego obszaru nazw. Ponieważ 'second :: y' jest zadeklarowane wewnątrz main, ukrywa' first :: y'. Czy znasz ukrywanie nazwy? –

+0

Przepraszam Jesse ... Ale nie jestem w stanie zrozumieć. gdy obie instrukcje "najpierw używają przestrzeni nazw, używając second :: y;" znajdują się w głównej funkcji, która powinna zadeklarować zarówno first: y jak i second :: y w zasięgu lokalnym i dać błąd kompilacji. Ale nie działa i programuje kompilację i działa poprawnie. A jeśli oba stwierdzenia są poza głównym źródłem, to nawet nie są kompilowane z powodu niejednoznaczności. Wyjaśnij proszę ... – Amrit

6

Istnieją dwie główne różnice między używaniem-deklaracją a użyciem-dyrektywy.

Pierwsza różnica: (Oczywista różnica).

namespace first{ 

int x=1; 
int y=2; 
} 
using first::x; //using declaration 

To pozwoli Ci wykorzystać zmienną x bez nazw nazwa jako wyraźnej kwalifikacjach i zauważ, że nie dotyczy to y.

namespace first{ 
int x=1; 
int y=2; 
} 
using namespace first;// using directive 

To pozwoli Ci wykorzystać wszystkie zmienne wewnątrz przestrzeni nazw first bez nazwy przestrzeni nazw jako wyraźnej kwalifikacjach.


Druga różnica: (co jest to, czego nie rozumiem).

Wyjaśnię ci, dlaczego podczas używania zarówno dyrektywy użycia, jak i deklaracji użycia wewnątrz głównej funkcji, nie otrzymasz błędu, ale gdy spróbujesz użyć ich obu w globalnej przestrzeni nazw, otrzymasz błąd podczas kompilacji.

Powiedzmy mamy dwa nazw zdefiniowane w globalnej przestrzeni nazw tak:

namespace first 
{ 
    int x = 5; 
    int y = 10; 
} 

namespace second 
{ 
    double x = 3.1416; 
    double y = 2.7183; 
} 


Przykład 1:

int main() {  
using namespace first; 
using second::y; 
    cout << x << endl; // this will output first::x; 
    cout << y << endl; // this will output second::y; 
    return 0; 
} 

Powodem jest to, że korzystając z dyrektywą using second::y sprawi, że zmienna y będzie wyglądać jak lokalna zmienna do zakresu, w którym znajduje się using-directive sed, w tym przypadku jest używany wewnątrz głównej funkcji. Podczas gdy deklaracja użycia using namespace first sprawi, że zmienne zdefiniowane w tym obszarze nazw będą wyglądały jak zmienne globalne i jest to ważne tylko w zakresie, w którym zastosowano dyrektywę use, w tym przypadku jest to funkcja główna.

więc jeśli stosuje what've powiedziane wyżej, będziesz wiedzieć, że jeśli zrobił coś takiego:

Przykład 2:

using namespace first; 
using second::y; 

int main() {  
    cout << x << endl; 
    cout << y << endl; // two definitions of y. first::y and second::y 
    return 0; 
} 

dostaniesz błąd, ponieważ zarówno first::y i second::y zachowa się tak, jakby zostały zdefiniowane w globalnej przestrzeni nazw, a więc skończy się łamaniem reguły One Defintion.

Powiązane problemy