2013-06-25 35 views
11

當我寫下面的代碼就被編譯並正確執行:爲什麼在全局範圍和局部範圍內使用指令的行爲有所不同?

#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; 
} 

但如果我寫使用的主要功能之外的指令如下,

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

它給出了這樣的編譯錯誤:

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 

任何人都可以解釋爲什麼在main和之外使用指令時,使用指令的行爲會有所不同?

回答

10

使用聲明就是這個聲明。 main中的using second::y;類似於聲明該範圍內的變量y,該變量隱藏了全局名稱空間範圍內的任何其他y。當您在全球範圍內使用using second::y;時,您並未隱藏任何名稱,因爲兩個ys在相同的範圍內。

想象一下你的第一個例子是這樣(請參閱下面的評論作出解釋):

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 
} 

然而,第二個例子是這樣的:

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

謝謝Jesse的快速回復......請糾正我,如果我錯了......但是當使用指令在主函數中仍然會有2個y的聲明。如果是這樣,爲什麼編譯器只能在第二種情況下出現問題? – Amrit

+1

@ user2235938:有兩個'y'的聲明,但using-declaration在main內部聲明'second :: y',而first :: y'在全局命名空間範圍內聲明。由於'second :: y'在main中被聲明,它隱藏了'first :: y'。你熟悉名稱隱藏嗎? –

+0

對不起傑西......但我無法理解。當兩個語句「首先使用命名空間; using second :: y;」在main函數內部,它應該在本地作用域中聲明first :: y和second :: y,並給出編譯錯誤。但它並沒有和程序編譯和運行成功。當兩種語句都是主要的時候,由於含糊不清,它甚至不會被編譯。請解釋... – Amrit

6

有兩個主要區別在使用聲明和使用指令之間。

第一差異:(明顯不同)。

namespace first{ 

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

這將允許您使用的變量x沒有命名空間名稱作爲一個明確的限定,並注意這不包括y

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

這將允許您使用所有變量的命名空間內first命名空間名稱作爲一個明確的限定。


第二差:(這是你不明白)。

我會向你解釋爲什麼當你在main函數中使用using指令和using聲明時你沒有錯誤,但是當你嘗試在全局名字空間中使用它們時,你會得到一個編譯時錯誤。

比方說,我們在全局命名空間中定義的這樣的命名空間:

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

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


例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; 
} 

的原因是使用指示符using second::y將使你的變量y看起來像是一個局部變量,範圍是using-directive是你的範圍sed,在這種情況下,它在主函數內部使用。而使用聲明using namespace first將使得在此名稱空間first內定義的變量看起來像是全局變量,並且這僅在使用using-directive的作用域內有效,在這種情況下,它位於主函數內。

所以如果你申請搞什麼名堂上面說的,你就會知道,如果你做了這樣的事情:

例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; 
} 

你會得到一個錯誤,因爲這兩個first::ysecond::y的行爲就好像它們是在全局名稱空間中定義的一樣,所以您將最終打破「一個定義規則」。