個人主頁:平行線也會相交
歡迎 點贊?? 收藏? 留言? 加關(guān)注??本文由 平行線也會相交 原創(chuàng)
收錄于專欄【C++之路】
C++關(guān)鍵字(C++98)
在C++中,總共有63個關(guān)鍵字,大家還記得在C語言中有多少個關(guān)鍵字嗎,沒錯,在C語言中總共有32個關(guān)鍵字。
下面是C++的關(guān)鍵字:
asm | do | if | auto |
---|---|---|---|
return | try | continue | double |
inline | short | typedef | for |
bool | dynamic_cast | int | signed |
typeid | public | break | else |
long | sizeof | typename | throw |
case | enum | mutable | static |
union | wchar_t | catch | explicit |
namespace | static_cast | unsigned | default |
char | export | new | struct |
using | friend | class | extern |
operator | switch | virtual | register |
const | false | private | template |
void | true | const_cast | float |
protected | this | volatile | while |
delete | goto | reinterpret_cast |
命名沖突
可以看到:上述代碼我們可以通過。
那現(xiàn)在這段代碼呢?請看:
我們發(fā)現(xiàn)rand出現(xiàn)了重定義的錯誤:那為什么rand
發(fā)生了沖突了呢?其實rand
這里是跟庫
發(fā)生了沖突。std中有一個函數(shù)也叫rand
,所以就會發(fā)生命名沖突的問題。
發(fā)生命名沖突的原因有兩種:
1.跟庫里發(fā)生沖突。
2.互相之間發(fā)生沖突。
其實命名沖突這個問題挺麻煩的,我們并不知道庫中是否有這個變量,在這個基礎(chǔ)上,如果我們又重新定義了這個變量,此時就會出現(xiàn)命名沖突的問題。為了解決命名沖突的問題,就引出了命名空間
。
命名空間
嗯,namespace
就是命名空間的意思,也是C++中的一個關(guān)鍵字,就是用來解決命名沖突的問題的。
這里,我們先來引出一個問題,請看下面代碼:
#include<iostream>
using namespace std;
int main()
{
return 0;
}
在C++中,為什么我們一般要加上using namespace std;
呢?
命名空間的定義
命名空間,即namespace
,后面跟著命名空間的名字,然后接一對{}
,{}中的內(nèi)容就是命名空間的成員
。
命名空間namespace
可以定義一個域
出來。
舉個例子:
我們可以看到上圖的代碼出現(xiàn)了rand重定義
的問題,我們?nèi)绻幌氤霈F(xiàn)這個問題,就可以用namespace
定義一個域出來以解決重定義
這個問題。
請看解決方法:
#include<stdio.h>
#include<stdlib.h>
//域
namespace hello
{
//hello這個域就會把域中的內(nèi)容(rand)進(jìn)行一個隔離
//這里要注意,域中的rand與主函數(shù)中的rand不是一回事。
int rand = 0;
}
int main()
{
printf("%d\n", rand);
return 0;
}
這個運行結(jié)果也說明了域中的rand
與主函數(shù)中的rand
不是一回事。
局部域和全局域的關(guān)系
#include<stdio.h>
#include<stdlib.h>
int a = 0;
int main()
{
int a = 1;
printf("%d\n", a);
return 0;
}
上面這個代碼中的兩個a就可以同時存在
。
我們把主函數(shù)外面的a
看作是全局域中的a
,把主函數(shù)里面中的a
看作是局部域中的a
。同時,我們還要知道一個點局部域和全局域既影響訪問,也影響生命周期。域分為好幾種,作用域只是域中的一種。域總共分為下面四種:
類域
命名空間域
局部域
全局域
我們來運行上面的代碼:
因為局部域中的a
優(yōu)先,所以這里打印出來的是局部域中變量a
的值,即打印出來的是1,如果我們想打印全局域中的a中的值怎么辦呢?我們可以這樣:
#include<stdio.h>
#include<stdlib.h>
int a = 0;
int main()
{
int a = 1;
printf("%d\n", a);
// ::稱為域作用限定符
printf("%d\n",::a);
return 0;
}
運行結(jié)果如上圖,我們看到我們打印出來的0
就是全局域中的a
的值。
關(guān)于局部域和全局域的關(guān)系是這樣的:
我們是默認(rèn)從局部域開始搜索的,即局部優(yōu)先;當(dāng)然,如果局部沒有的話,我們就會去全局域進(jìn)行搜索,所以有局部先訪問局部,沒有局部才會去訪問全局。
我們通過域作用限定符::
可以去直接訪問全局域。即上面的代碼,注意觀察,::
的前面是不加任何東西的(注意前面不需要我們加空格),意思就是我們直接去訪問全局域。
命名空間域
上圖代碼中總共有三個域(局部域、全局域、命名空間域),每個域中都有一個變量a,我們如何去訪問這三個作用域中的a呢,請看下面:
我們現(xiàn)在把全局域中的變量a
注釋掉看看運行結(jié)果,所以來看下面這段代碼的運行結(jié)果:
我們發(fā)現(xiàn)程序根本運行不了,所以這里就報錯了。
所以我們通過這個程序發(fā)現(xiàn),這個程序并不會去到命名空間里去進(jìn)行搜索;那這里就會引出一個新的問題,程序什么時候才會去到命名空間域中去進(jìn)行搜索呢?
這里有兩種可能性會去搜索命名空間域中的內(nèi)容:
1.我們展開了命名空間域
2.指定訪問命名空間
我們先來看第一種(展開命名空間):
如果我們不展開的話:
#include<stdio.h>
#include<stdlib.h>
int a = 2;
namespace hello
{
int a = 1;
}
//展開命名空間
//using namespace hello;
int main()
{
int a = 0;
printf("%d\n", a);
return 0;
}
上面就是我們不對命名空間進(jìn)行展開,上面代碼中的3個變量a
依然可以同時存在。
補充一點,我們C++中常用的using namespace std;
展開的是std標(biāo)準(zhǔn)庫中的命名空間
。
現(xiàn)在如果我們想訪問命名空間中的變量a
,我們可以采用第二種方式(指定訪問命名空間):
#include<stdio.h>
#include<stdlib.h>
int a = 2;
namespace hello
{
int a = 1;
}
//展開命名空間
//using namespace hello;
int main()
{
int a = 0;
printf("%d\n", a);
printf("%d\n", ::a);
printf("%d\n", hello::a);
return 0;
}
上面的代碼中我們雖然沒有對命名空間進(jìn)行展開,但是我們指定了命名空間。
現(xiàn)在新的問題來了,如果我們把命名空間展開會發(fā)生什么呢?請看:
上述代碼中,我們把命名空間里的內(nèi)容進(jìn)行展開,展開的意思就是編譯時把命名空間里的內(nèi)容暴露到全局,是是否會到命名空間里面去搜索,
,而此時全局域中已經(jīng)有一個變量a
了,所以會出現(xiàn)上圖a不明確的
問題。
所以我們現(xiàn)在再來看namespace
這個關(guān)鍵字發(fā)現(xiàn)它并不友好,它會把我們的命名空間進(jìn)行展開,而我們?yōu)槭裁匆衙臻g進(jìn)行展開呢?命名空間進(jìn)行展開的意義何在?
命名空間就是為了防止自己的內(nèi)容與其它域發(fā)生沖突而設(shè)立的。
小結(jié)
我們雖然可以指定指定命名空間里面的內(nèi)容,但是這樣不是很方便,所以有些地方有些時候我們會把命名空間進(jìn)行展開,一旦我們把命名空間進(jìn)行展開,就可能會出現(xiàn)一系列問題。比如,重定義問題、某個變量不明確等等問題。所以,我們以后不要輕易使用using namespace
。
現(xiàn)在,我們再來看開頭還沒有解決的問題:
我們既然無法把rand
定義在全局域中,那就直接把rand
定義在一個命名空間域并不對這個域進(jìn)行展開就好了,請看:
所以我們利用命名空間就可以解決開頭rand
重定義的問題,但是這個問題C語言無法解決,而C++中的命名空間就可以解決。
命名空間中可以定義哪些內(nèi)容
在命名空間中,我們可以定義很多東西,比如結(jié)構(gòu)體類型、定義變量、定義函數(shù)等都是可以的。請看舉例:
#include<stdio.h>
#include<stdlib.h>
namespace hello
{
int rand = 10;
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int data;
};
}
int main()
{
return 0;
}
嵌套命名空間
命名空間是可以進(jìn)行嵌套的,比如:
//嵌套命名空間
#include<stdio.h>
#include<stdlib.h>
namespace N1
{
int a = 0;
int b = 1;
int Add(int left, int right)
{
return left + right;
}
namespace N2
{
int a = 1;
int c = 0;
int d = 0;
int Sub(int left, int right)
{
return left - right;
}
}
}
補充一點:C++中的C++庫里的所有東西都會被分裝在std命名空間中
。stl是C++標(biāo)準(zhǔn)庫的一部分
,cout等都在C++標(biāo)準(zhǔn)庫中
。
我們?nèi)绾卧L問嵌套命名空間呢?請看舉例:
我們知道不同的域可以有同名名變量,但是同一個域不能有同名變量。我們同一個命名空間如若給非要給同樣的變量,這個時候嵌套命名空間
就派上用場了。
我們在平常最常見的C++代碼大體是長這樣的,請看:
#include<iostream>
using namespace std;
int main()
{
return 0;
}
其實這樣直接展開的話會有風(fēng)險,我們定義的如果跟庫中的重名,就報錯了。所以項目里面盡量不要去進(jìn)行展開。注意,展開不一定會報錯。如果是日常練習(xí)的話(代碼少),就可以直接展開;那如果是項目中的話,前往不要隨意對命名空間進(jìn)行展開。建議直接訪問指定命名空間,比如:
但是如果我們一個項目中有非常多cout
的話,我們不可能要輸入非常多次的std::
,所以這里推薦一種非常實用的方式,請看:
這樣的話,我們就不需要把整個命名空間進(jìn)行展開了,我們直接把最常用的展開就可以了。文章來源:http://www.zghlxwxcb.cn/news/detail-417860.html
總結(jié)
命名空間的存在是為了解決C語言的一個缺陷,我們知道C語言存在命名沖突的問題,為了解決命名沖突問題,于是C++就引入了命名空間的內(nèi)容。命名空間是對全局域的比如變量、函數(shù)、類型就行分裝,以防止之間發(fā)生沖突
。再次強調(diào)命名空間解決的是全局域的沖突,局部域基本上沒有命名空間的問題,局部域的話就相當(dāng)于在函數(shù)里面,函數(shù)本身就是一個局部域
,不同的函數(shù)之間可以定義同名的變量(因為不同的域里面可以定義同名的變量)。
我們對命名空間進(jìn)行搜索主要有三種方式:第一:展開命名空間;第二:直接訪問命名空間;第三:訪問某個。(其中第二種第三種都是通過域作用限定符來進(jìn)行操作的)。
同時,我們在對命名空間進(jìn)行展開的時候需要格外小心,不要輕易的對命名空間進(jìn)行展開。
好了,以上就是C++中命名空間
的內(nèi)容,算是C++中的開頭。
就到這里吧,下次見嘍各位,再見啦?。。?/strong>文章來源地址http://www.zghlxwxcb.cn/news/detail-417860.html
到了這里,關(guān)于詳解C++中的命名空間(namespace)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!