C++_命名空間(namespace)

????????

目錄

1、namespace的重要性

2、?namespace的定義及作用

2.1 作用域限定符

?3、命名空間域與全局域的關系

4、命名空間的嵌套

?5、展開命名空間的方法

5.1 特定展開

5.1 部分展開

5.2 全部展開

結語:


前言:

????????C++作為c語言的“升級版”,其在語法上相對于c語言有了諸多升級、優化,比如在C++中有一個全新的概念:命名空間(namespace)。在使用C++時,該語法很好的解決了對標識符命名重名的問題。

1、namespace的重要性

? ? ? ? 在使用c語言寫代碼時,常常會遇到標識符命名重名的問題。比如我們自己寫了一個函數,該函數名可能與庫函數中的某個函數發生重名,或者與他人一起寫項目時,也存在與他人代碼中的標識符同名的現象,然而以上情況的解決方法只有對標識符進行改名。

? ? ? ? 舉例說明:

#include <stdio.h>
#include <time.h>
int time = 12;int main()
{printf("%d\n", time);return 0;
}
//程序編譯時會報錯,原因是預處理階段會展開全部的頭文件(.h文件)
//被展開頭文件里面的內容是具有“全局性的”,即全局都能使用里面的內容
//然而time.h的文件中存在一個名為time的函數
//在編譯階段,編譯器會發現全局中有兩個time的名稱,并且報錯

? ? ? ? 因此針對重定義、重命名的這類問題,C++就提出了一個新的概念namespace。

2、?namespace的定義及作用

????????namespace又稱命名空間,他是一塊獨立于全局范圍內的區域,在namespace區域中定義各種標識符的名稱和全局中是分割開的,換句話說就是對命名空間內的標識符名稱進行本地化管理,這樣就不會與全局作用域中的同名標識符起沖突了。

? ? ? ? 比如,創建兩個頭文件first.h和second.h,并且把這兩個頭文件都包含到主函數文件main.cpp中:

//first.h文件:
#pragma once
int a = 10;//second.h文件:
#pragma once
int a = 101;//main.cpp文件:
//包含上述兩個.h文件
#include"first.h"
#include"second.h"
#include<stdio.h>int main()
{printf("%d ",a);//a重定義了return 0;
}//會報錯:a重定義

? ? ? ? 上述代碼若運行,則會發生編譯報錯,原因就是再展開這兩個頭文件后,會出現兩個a多重定義的報錯。這時候可以將其中一個頭文件的變量a換另一個名稱,或者main.cpp中只包含其中一個頭文件。但是如果這兩個文件都要包含而且也不想對變量a的名稱進行更改,那么只能用namespace將兩個頭文件下的變量a存到命名空間內。

2.1 作用域限定符

? ? ? ? 使用namespace進行對上述代碼的優化:

//first.h文件:
#pragma once
namespace first//namespace用法:namespace+自定義名稱
{int a = 10;}//second.h文件:
#pragma once
namespace second
{int a = 101;}//main.cpp文件:
//包含上述兩個.h文件
#include"first.h"
#include"second.h"
#include<stdio.h>int main()
{printf("%d ", second::a);//::表示作用域限定符,左邊跟作用域名稱return 0;
}//會報錯:a重定義

? ? ? ? 上述代碼則將兩個頭文件下的變量a都放在了兩塊不一樣的命名空間內,這樣一來他們的名稱就不會互相干涉了,只不過在使用變量a的時候要多一個步驟:使用作用域限定符去特指的命名空間查找。因為編譯器也不知道程序員需要用哪個a,所以程序員需要在使用的a的左邊加上“::”符號,并且在“::”符號的左邊加上命名空間的名稱,這樣就可以精確的使用某個命名空間里的內容了,也稱展開命名空間。

? ? ? ? 上述代碼運行結果:

?3、命名空間域與全局域的關系

? ? ? ? 如果上文中的代碼沒有對a使用“second::”,會出現什么樣的后果呢?

? ? ? ? 可以發現編譯器顯示找不到變量a了,因為編譯器查找的順序是先找局部、再找全局,并不會自動的去命名空間內查找,所以全局域和命名空間域是分開的兩個區域。因此在上述代碼中,當頭文件里的變量a被存放在命名空間中,可以理解為該變量從全局域被移動至命名空間域。

? ? ? ? 關系圖:

? ? ? ? 比如全局域和局部域都有一個名為a的變量,如果編譯器在局部域中就找到了a,則編譯器會直接調用該a的值,并且也不會去全局域中查找,用上述代碼進行變形當作例子:

#include"first.h"
#include"second.h"
#include<stdio.h>int a = 1021;//全局變量int main()
{int a = 22;//局部變量printf("%d ", a);return 0;
}

? ? ? ? ?運行結果:

????????可以看到編譯器直接選用了局部變量a作為打印結果。并且我們新加了全局變量int a=1021,編譯器也沒有報重命名的錯誤,說明全局域和命名空間域是分開的的兩個區域,在全局域中定義了一個a,則命名空間域也能使用a的名稱。

4、命名空間的嵌套

? ? ? ? ?命名空間的嵌套就是在該空間內在創建一個命名空間,一般是防止最外層命名空間的名稱與別的空間同名,寫法如下:

//first.h
#pragma once
namespace first
{namespace A{int a = 10;}
}//second.h
#pragma once
namespace first//假設兩個頭文件下的第一層空間重名
{namespace B//則需要第二層空間來區別a變量{int a = 101;}
}//main.cpp
#include"first.h"
#include"second.h"
#include<stdio.h>int a = 1021;int main()
{printf("%d\n", first::A::a);printf("%d\n", first::B::a);return 0;
}

? ? ? ? 運行結果:

?5、展開命名空間的方法

? ? ? ? 展開命名空間就是從命名空間內讀取內容,上文提到的作用域限定符就是其中的一個辦法,但是如果讀取大量的內容就會很麻煩,因為只要是每一次讀取都要加上作用域限定符,會很繁瑣。因此另兩種方法是部分展開和全部展開。

5.1 特定展開

? ? ? ? 特定展開就是上文的展開方式,既:空間名稱::變量名稱。值得一提的是,使用特定展開時,編譯器不會去局部和全局找,而是直接到命名空間內找,因此就算全局也有與該變量一模一樣的名稱,也不會報錯,而且編譯器還是會調用命名空間內的變量。

? ? ? ? 特定展開代碼如下:

//first.h
#pragma once
namespace first
{int a = 10;
}//second.h
#pragma once
namespace second
{int a = 101;
}#include"first.h"
#include"second.h"
#include<stdio.h>
int a = 1021;int main()
{printf("%d\n", first::a);//編譯器會調用first文件中的a,而不是調用全局a=1021的areturn 0;
}

?????????運行結果:

5.1 部分展開

? ? ? ? 在全局處使用using+空間名稱::變量名稱。部分展開與特定展開就不一樣了,部分展開是把要調用的變量移動到全局域中,然后編譯器在全局域中找到該變量,并不是讓編譯器指定到該空間去找,因此要保證全局中不能出現與該變量一樣的名稱,不然會報錯。

? ? ? ? 部分展開邏輯圖如下:

????????具體代碼如下:

//first.h
#pragma once
namespace first
{int a = 10;
}//second.h
#pragma once
namespace second
{int a = 101;
}//main.cpp
#include"first.h"
#include"second.h"
#include<stdio.h>
using first::a;//展開first空間并且只調用a
//int a = 1021;//注意這時候first.h里的變量a屬于全局變量了,不能再定義額外名稱的a的變量int main()
{printf("%d\n", a);printf("%d\n", a);return 0;
}

? ? ? ? 運行結果:

???????? 在全局處加上了using first::a,之后所有需要調用a變量的代碼前面都不需要再加作用域限定符了。但是僅僅限于變量a不用加限定符,如果要調用first空間內其他的變量還是要加作用域限定符的,因此又引出一個新的概念:全部展開,全部展開某個命名空間,則后續的代碼可以不加限定符直接調用該空間內的所有內容。

5.2 全部展開

? ? ? ? 在全局處加上using+namespace+要展開空間的名稱,既可對該空間進行全部展開。全局展開也同部分展開邏輯一樣,全局展開相當于把該空間里的所有內容都移到全局域中,因此全局域中不能出現與該空間內有標識符名稱相同的情況。

? ? ? ? 全部展開代碼如下:

//first.h
#pragma once
namespace first
{int a = 10;int b = 123;int c = 456;
}//second.h
#pragma once
namespace second
{int a = 101;
}//main.cpp
#include"first.h"
#include"second.h"
#include<stdio.h>
using namespace first;
//int a = 1021;int main()
{printf("%d\n", a);printf("%d\n", b);printf("%d\n", c);return 0;
}

? ? ? ? 運行結果:

? ? ? ? 從結果來看,當全部展開first空間后,可以隨意使用該空間的內容而且無需添加任何條件。?

結語:

????????以上就是關于C++中命名空間的介紹,對于命名空間的全部展開其實在一般的情況下是不推薦的,因為全部展開意味著空間內的所有內容都變成了全局的,很容易發生重名,也就失去了命名空間防止重名的意義。

????????最后希望本文可以給你帶來更多的收獲,如果本文對你起到了幫助,希望可以動動小指頭幫忙點贊👍+關注😎+收藏👌!如果有遺漏或者有誤的地方歡迎大家在評論區補充~!!謝謝大家!!( ̄︶ ̄)↗ 

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/206729.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/206729.shtml
英文地址,請注明出處:http://en.pswp.cn/news/206729.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

快速排序的新用法

普通快排 簡介 快速排序是一種高效的排序算法&#xff0c;利用分治的思想進行排序。它的基本原理是在待排序的n個數據中任取一個數據為分區標準&#xff0c;把所有小于該排序碼的數據移到左邊&#xff0c;把所有大于該排序碼的數據移到右邊&#xff0c;中間放所選記錄&#x…

Spring 之 @Cacheable 緩存使用教程

1、Cacheable 指定使用緩存 定義個 Controller &#xff0c;在方法上加上注解 Cacheable&#xff0c;配置要使用哪些緩存&#xff0c;比如 myMapCache 表示一級緩存是 Map&#xff0c;myRedisCache 表示二級緩存是 Redis。并配置緩存 key。 key 由 SPEL 表達式組成&#xff0c…

異常檢測 | MATLAB實現BiLSTM(雙向長短期記憶神經網絡)數據異常檢測

異常檢測 | MATLAB實現BiLSTM(雙向長短期記憶神經網絡)數據異常檢測 目錄 異常檢測 | MATLAB實現BiLSTM(雙向長短期記憶神經網絡)數據異常檢測效果一覽基本介紹模型準備模型設計參考資料效果一覽 基本介紹 訓練一個雙向 LSTM 自動編碼器來檢測機器是否正常工作。 自動編碼器接受…

CleanMyMac X2024最新版本軟件實用性測評

信大多數MAC用戶都較為了解&#xff0c;Mac雖然有著許多亮點的性能&#xff0c;但是讓用戶叫苦不迭的還其硬盤空間小的特色&#xff0c;至于很多人因為文件堆積以及軟件緩存等&#xff0c;造成系統空間內存不夠使用的情況。于是清理工具就成為了大多數MAC用戶使用頻率較高的實用…

二十一章網絡通信

計算機網絡實現了多臺計算機間的互聯&#xff0c;使得它們彼此之間能夠進行數據交流。網絡應用程序就是在已連接的不同計算機上運行的程序&#xff0c;這些程序借助于網絡協議&#xff0c;相互之間可以交換數據。編寫網絡應用程序前&#xff0c;首先必須明確所要使用的網絡協議…

數據采集工具的大全【都是免費值得收藏】

數據是推動業務成功的關鍵之一。為了獲取準確、全面的信息&#xff0c;數據采集成為了許多企業和個人的必備工作。本文將專注于數據采集工具&#xff0c;探討其在全網和指定網站采集方面的優勢&#xff0c;為大家提供對比分析&#xff0c;以幫助大家找到最適合的數據采集利器。…

算法復習——6種排序方法的簡單回顧

算法復習——6種排序方法的簡單回顧 常見排序方法&#xff1a;冒泡排序、選擇排序、插入排序、堆排序、歸并排序、快速排序的簡單回顧 冒泡排序 重復“從序列右邊開始比較相鄰兩個數字的大小,再根據結果交換兩個數字的位置” 在冒泡排序中&#xff0c;第 1 輪需要比較 n - 1…

Tair(1):Tair介紹

1 介紹 ? 在Tair出現之前的很長一段時間里&#xff0c;像redis、memcache這些知名NoSql數據庫是不支持分布式的&#xff0c;在這樣的背景下&#xff0c;由淘寶網自主開發并在2010.6開源的一個高性能、高擴展、高可靠分布式緩存&#xff0c;類似map的key/value結構&#xff0c…

使用單例模式+觀察者模式實現參數配置實時更新

使用vector存儲觀察者列表 #include <iostream> #include <vector> #include <functional> #include <algorithm>// 配置參數結構體 struct MyConfigStruct {int parameter1;std::string parameter2; };class Config { public:using Observer std::f…

hive 命令行中使用 replace 和nvl2 函數報錯

1.有時候在命令行的情況下使用 replace 函數時會報錯 這個時候可以使用 translate 代替 2.有時候使用 nvl2() 函數的時候會報錯 這個時候可以用 case when 來代替

【Spring 源碼】 深入理解 Bean 定義之 BeanDefinition

&#x1f680; 作者主頁&#xff1a; 有來技術 &#x1f525; 開源項目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 倉庫主頁&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 歡迎點贊…

兩數之和問題

更好的閱讀體驗請點擊 兩數之和。 題目&#xff1a;兩數之和 ? 給定一個整數數組 nums 和一個整數目標值 target&#xff0c;請你在該數組中找出 和為目標值 target 的那 兩個 整數&#xff0c;并返回它們的數組下標。 ? 你可以假設每種輸入只會對應一個答案。但是&#xff…

MetricBeat監控Redis

目錄 一、安裝部署 二、開啟Redis監控模塊 三、編輯Redis配置文件 四、啟動Metricbeat 五、查看監控圖表 一、安裝部署 metriceat的安裝部署參考章節&#xff1a; 監控組件>Metricbeat安裝使用&#xff0c;這里不再贅述。 二、開啟Redis監控模塊 進入metricbeat安裝目錄…

【每日一題】出租車的最大盈利

文章目錄 Tag題目來源解題思路方法一&#xff1a;遞歸方法二&#xff1a;遞歸記錄數組記憶化搜索方法三&#xff1a;動態規劃&#xff08;遞推&#xff09; 寫在最后 Tag 【遞歸】【記憶化搜索】【動態規劃】【數組】【2023-12-08】 題目來源 2008. 出租車的最大盈利 解題思路…

【EI會議征稿中】2024年第四屆人工智能、自動化與高性能計算國際會議(AIAHPC 2024)

2024年第四屆人工智能、自動化與高性能計算國際會議&#xff08;AIAHPC 2024&#xff09; 2024 4th International Conference on Artificial Intelligence, Automation and High Performance Computing 2024第四屆人工智能、自動化與高性能計算國際會議(AIAHPC 2024)將于20…

藍橋杯從零開始備戰(Python組)---基礎知識篇

第一次嘗試報名藍橋杯的Python組&#xff0c;好好備戰&#xff0c;希望省賽可以拿獎&#xff01;目前是整理了一些Python的常用函數和常用內置庫&#xff0c;后面可能會開始刷題&#xff0c;如果有比較需要記住的知識點&#xff0c;會再寫一篇刷題篇 一、輸入輸出 1.輸入字符…

游戲被攻擊怎么辦

隨著科技的進步和互聯網的普及&#xff0c;游戲行業也正在經歷前所未有的變革。玩家們不再滿足于傳統的線下游戲&#xff0c;而是轉向了線上游戲。然而&#xff0c;隨著游戲的線上化&#xff0c;游戲安全問題也日益凸顯。游戲受到攻擊是游戲開發者永遠的痛點&#xff0c;談“D“…

HomeAssistant添加HACS插件并實現公網控制米家,HomeKit等智能家居

HomeAssistant添加HACS插件并實現公網控制米家&#xff0c;HomeKit等智能家居 文章目錄 HomeAssistant添加HACS插件并實現公網控制米家&#xff0c;HomeKit等智能家居基本條件一、下載HACS源碼二、添加HACS集成三、綁定米家設備 ? 上文介紹了如何實現群暉Docker部署HomeAssist…

【嵌入式開發 Linux 常用命令系列 4.1 -- git push 遠程分支與本地分支查看】

文章目錄 概述git push 語法步驟1&#xff1a;git 遠程主機名查看步驟2&#xff1a;git 遠程分支名查看步驟3&#xff1a;git 本地分支名查看示例演示 概述 在日常工作中&#xff0c;將代碼 git clone 本地之后&#xff0c;或者使用repo init && repo sync 之后不知道…

SQLserver截取字符串

當我們存的數據是json的時候可以全部取出在模糊查詢但是有多個重復數據的時候就沒辦法準確的模糊出來這個時候我們就需要用的字符串截取 --創建函數create FUNCTION [dbo].[Fmax] (str varchar(50),start VARCHAR(50),length VARCHAR(50)) RETURNS varchar(max) AS BEGINDEC…