天天看點

初步認識c++之命名空間詳解(千字長文帶你刨析你命名空間的細節)

初識c++之命名空間詳解

前言:c++是在c語言的基礎上進一步發展出來的用于彌補c語言缺陷的語言,是c語言的超集,添加了很多新的特性,使其程式設計更加友善!下面就讓我們開始初步認識c++吧!

1.命名空間 :namespace

我們在c語言的程式設計中經常出現一個問題——當我們的==變量名/函數名/類型==不小心重複命名的時候,或者==不小心使用了與庫中函數相同的名字==當做變量名,那麼就會出現編譯報錯!
初步認識c++之命名空間詳解(千字長文帶你刨析你命名空間的細節)
初步認識c++之命名空間詳解(千字長文帶你刨析你命名空間的細節)
這很不友善,當我們多人合作寫一個大型的項目的時候,就很容易出現這種問題,c++為此引入了namespace(命名空間)來解決這個問題
當我們使用命名空間的時候
初步認識c++之命名空間詳解(千字長文帶你刨析你命名空間的細節)
就會發現原本的報錯就消失了!這就是命名空間的功能:==影響編譯查找規則==!

1.1域作用限定符 ::

在詳細搞懂namespace之前我們要先了解域作用限定符 ==::==

這個符号有什麼作用呢?

#include <stdio.h>
int a = 10;
int main()
{
    int a = 0;
    printf("%d",a);
}
           
初步認識c++之命名空間詳解(千字長文帶你刨析你命名空間的細節)

上面的程式我們可以看如果進行列印,列印出來的一定會是0 ,因為局部優先原則,當局部和全局都存在相同變量名的時候,局部變量會優先選擇!但是如果我們一定要列印全局變量a而不是局部變量a呢?且不對局部變量進行删除!

這時候就要用到我們的域作用限定符了!

#include <stdio.h>
int a = 10;
int main()
{
    int a = 0;
    printf("%d",::a);
}
           
初步認識c++之命名空間詳解(千字長文帶你刨析你命名空間的細節)

我們可以看到我們成功的列印出了全局變量a!

==當::左邊為空的時候就是預設為全局域==,而且我們可以看出其實編譯的時候預設遵循一套查找規則先找局部,再找全局,局部沒有了,才回去全局找!但是域作用限定符可以改變這個規則,讓它去我們想要的域去尋找變量!

1.2命名空間的本質

命名空間就相當于是建立了一個域,通過域作用限定符讓程式在指定的域中查找我們在命名空間裡面定義的變量/函數/類型!==這相當于就是影響了編譯查找規則!記住程式也隻會在這個域中進行查找!不會說這個域找不到就去全局,局部找!如果這個域沒有你所定義的變量/函數/類型!就會編譯報錯!==
初步認識c++之命名空間詳解(千字長文帶你刨析你命名空間的細節)
初步認識c++之命名空間詳解(千字長文帶你刨析你命名空間的細節)
1.2.1命名空間中的變量!

我們已知命名空間中可以定義變量,那麼命名空間中的變量是局部變量還是全局變量呢?

這個問題我們得回到局部變量和全局變量的定義去看

  • 函數裡面的局部變量是定義在棧幀上的,隻有去調用函數才會去建立棧幀!
  • 而全局變量是建立在靜态區!整個工程都可以使用!

那麼命名空間中的變量是定義在哪裡呢?

**在靜态區中!**是以命名空間裡面變量的本質就是一個全局變量!

一般的全局變量毫無遮掩,我們直接就能看到,==但是命名空間裡面的變量相當于在四周被加了圍牆,我們隻能到牆裡面才能看到它!(使用作用域限定符)==,這樣子來了解可能會比較直覺!

1.3命名空間的合并和嵌套

當我們遇到多個頭檔案使用命名空間時都命名為同一個名字時會發生什麼?

答案是會發生合并!==或者是說同一級的同名命名空間會發生合并==因為當我們調用多個頭檔案時候,在預編譯階段就會将頭檔案裡面的内容都拷貝到該源檔案的位置!

初步認識c++之命名空間詳解(千字長文帶你刨析你命名空間的細節)
//上面的程式等同于
namespace test
{
	struct  ListNode
	{
		int val;
		struct ListNode* next;
	};
}
namespace test
{
	struct stack
	{
		int* a;
		int top;
		int capacity;
	};
}

int main()
{
	test::ListNode a;
	a.val = 0;
	a.next = NULL;

	test::stack b;
	b.capacity = 0;
	b.top = 0;
	b.a = NULL;
	printf("val:%d capacity:%d top:%d", a.val, b.capacity, b.top);
}
           
但是不同一級的命名空間就不會發生合并!
namespace test
{
	struct  ListNode
	{
		int val;
		struct ListNode* next;
	};
	namespace test
	{
		struct stack
		{
			int* a;
			int top;
			int capacity;
		};
	}
}
int main()
{
	test::ListNode a;
	a.val = 0;
	a.next = NULL;

	test::stack b;//test::test::stack b;這才是正确寫法
	b.capacity = 0;
	b.top = 0;
	b.a = NULL;
	printf("val:%d capacity:%d top:%d", a.val, b.capacity, b.top);
}//這樣寫的話程式就會出現報錯!
           
同樣的這也是我們要說的命名空間的嵌套!==命名空間裡面是可以嵌套命名空間的!==

1.4官方命名空間std

c++官方為了防止出現沖突,于是将c++标準庫裡面的東西都放進了std這個命名空間裡面!

是以我們經常看到寫c++代碼的時候會出現以下兩行代碼

#include <iostream>
using namespace std;
           
這就是在使用std這個命名空間,将其全部展開!

1.4.3命名空間的使用方式

首先就是将其全部展開就是我們上面看到的那個方法
#include <iostream>
using namespace std;
int main()
{
   	cout << "hello world" << endl;
}
           

全部展開後我們就不用那麼麻煩的在使用命名空間定義的變量名/函數名/類型前面加上 std::

==但是!這樣其實是不好的!因為這樣子舍棄了命名空間原本最大的用處!防止出現沖突!==是以我們應該盡量的防止進行全部展開!特别是在進行多人合作的時候!

#include <iostream>
using std::cout;
int main()
{
   	cout << "hello world" << std::endl;
}
           
#include <iostream>
int main()
{
   	std::cout << "hello world" << std::endl;
}
           

繼續閱讀