C++ 命名空間避免命名沖突的實(shí)現(xiàn)
??名字沖突問題
在實(shí)際生活中,一個(gè)大型的項(xiàng)目往往不是一個(gè)人獨(dú)立完成的,而是由若干個(gè)人合作完成的,不同的人分別完成不同的部分,最后組合成一個(gè)完整的程序。
假如不同的人分別定義了類,放在不同的頭文件中,在主文件(包含主函數(shù)的文件)需要用這些類時(shí),就用#include指令將這些頭文件包含進(jìn)來。
由于各頭文件是由不同的人設(shè)計(jì)的,有可能在不同的頭文件中用了相同的名字來命名所定義的類或函數(shù)。這樣在程序中就會出現(xiàn)名字沖突。
??例子
程序員甲在頭文件header1.h中定義了類Student和函數(shù)fun:
#pragma once //header1.h #include <iostream> #include<string> #include <cmath> using namespace std; class Student //聲明Student類 { public: Student(int n, string nam, int a) { num = n; name = nam; age = a; } void get_data(); private: int num; string name; int age; }; //成員函數(shù)的定義 void Student::get_data() { cout<< num <<"" << name << "" << age << endl; } //定義全局函數(shù)(即外部函數(shù)) double fun(double a, double b) { return sqrt(a + b); }
在main函數(shù)所在的主文件中包含文件header1.h:
#include "header1.h" int main() { Student stud1(101,"Wang",18); stud1.get_data; cout<<fun(5,3)<<endl; return 0; }
運(yùn)行結(jié)果如下:
如果程序員乙寫了頭文件head2.h,在其中定義了其他類以外,還定義了類Student和函數(shù)fun,但其內(nèi)容與頭文件header1.h中的Student和函數(shù)fun有所不同。
//header2.h #pragma once #include <string.h> #include<cmath> #include<iostream> using namespace std; class Student { public: Student(int n, string nam, char s)//參數(shù)與header1.h中不同 { num = n; name = nam; sex = s; } void get_data(); private: int num; string name; char sex; }; //成員函數(shù)定義 void Student::get_data() { cout << num << "" << name << "" << sex << endl; } //定義全局函數(shù) double fun(double a, double b) { return sqrt(a - b);//返回值與header1中的fun函數(shù)不同 } ...... //頭文件2可能還有其他的內(nèi)容
假如主程序員在其程序中要用到header1.h中的Student和函數(shù)fun,因而在程序中包含了頭文件header1.h,同時(shí)又要用到頭文件header2.h中的一些內(nèi)容,但是不知道此時(shí)header2.h中包含了與header1.h同名單內(nèi)容不同的Student類和fun函數(shù),因而又在頭文件中包含了頭文件header2.h。
主文件如下:
//main file #include <iostream> #include "header1.h" #include "header2.h" int main() { Student stud1(101,"Wang",18); stud1.get_data; cout<<fun(5,3)<<endl; return 0; }
這時(shí),程序編譯就會出現(xiàn)錯(cuò)誤。
??名字沖突
因?yàn)樵陬A(yù)編譯后,頭文件中的內(nèi)容取代了對應(yīng)的#include指令,這樣就在同一個(gè)程序文件中出現(xiàn)了兩個(gè)Student類和兩個(gè)fun函數(shù),顯然是重復(fù)定義,這就是名字沖突。
名字沖突,即在同一個(gè)作用域中含有兩個(gè)或多個(gè)同名的實(shí)體。
不僅如此,在程序中往往還需要引用一些庫,包括C++編譯系統(tǒng)提供的庫、由軟件開發(fā)商提供的庫或者用戶自己開發(fā)的庫,為此需要包含有關(guān)的頭文件。如果在這些庫中包含有與程序的全局實(shí)體同名的實(shí)體,或者不同的庫中有相同的實(shí)體名,則在編譯時(shí)就會出現(xiàn)名字沖突。有人稱之為全局命名空間污染。
為了避免這類問題的出現(xiàn),人們提出了許多方法,例如:將實(shí)體的名字寫得長一點(diǎn)(包含十幾個(gè)或幾十個(gè)字母和字符);把名字搞得特殊一些,包括一些特殊的字符;由編譯系統(tǒng)提供的內(nèi)部全局標(biāo)識符都用下劃線作為前綴,如_complex(),以避免與用戶的實(shí)體同名;由軟件開發(fā)商提供的尸體的名字用特定的字符作為前綴等。但是這樣的效果并不理想,而且增加了閱讀程序的難度,即可讀性降低了。
C語言和早期的C++語言沒有提供有效的機(jī)制來解決這個(gè)問題,沒有庫的提供者能夠建立自己的命名空間。人們希望ANSI C++ 標(biāo)準(zhǔn)庫能夠解決這個(gè)問題,提供一種機(jī)制、一種工具,使由庫的設(shè)計(jì)者命名的全局標(biāo)識符能夠和程序的全局實(shí)體名以及其他類的全局標(biāo)識符區(qū)別開來。
??命名空間
為了解決這個(gè)問題,ANSI C++增加了命名空間。
所謂命命名空間,就是一個(gè)由程序設(shè)計(jì)者命名的內(nèi)存區(qū)域。程序設(shè)計(jì)者可以根據(jù)需要指定一些有名字的空間域,把一些全局實(shí)體分別放在各個(gè)命名空間中,從而與其他全局實(shí)體分離開來。
我的理解就是原來我們的全局實(shí)體變量都是“暴露出來”的,然后命名空間的作用就是分別個(gè)你需要的全局實(shí)體“圍起來”,像柵欄一樣,每一塊區(qū)域都有一個(gè)專屬于自己的名字。然后在編譯階段,就像是好多個(gè)“圍起來的柵欄”,且各不相同。
命名空間的作用是建立一些互相分隔的作用域,把一些全局實(shí)體分隔開來,以免產(chǎn)生名字沖突。
這里有一段很形象的描述,可以幫助大家更好地理解:例如,某中學(xué)高三年級有3個(gè)叫李相國的學(xué)生,如果都在同一班,那么老師點(diǎn)名叫李相國時(shí),3個(gè)人都站起來應(yīng)答,這就是名字沖突。因?yàn)樗麄儫o法辨別老師想叫的是哪一個(gè)李相國?同名者無法互相區(qū)分。為了避免同名混淆,學(xué)校把3個(gè)同名的學(xué)生分在3個(gè)班。這樣,在小班點(diǎn)名叫李相國時(shí),只會有一個(gè)人應(yīng)答。也就是說,在該班的范圍內(nèi),即班作用域內(nèi)名字是唯一的。如果在全校集合時(shí)校長點(diǎn)名,需要在全校范圍內(nèi)找這個(gè)學(xué)生,要考慮的作用域是全校范圍。如果校長叫李相國,全校學(xué)生中又會有3個(gè)人一齊喊“到”,因?yàn)樵谕蛔饔糜蛑写嬖?個(gè)同名學(xué)生。為了在全校范圍內(nèi)區(qū)分這3名學(xué)生,即加上班名限定。這樣就不會產(chǎn)生混淆。
可以根據(jù)需要設(shè)置許多個(gè)命名空間,每個(gè)命名空間代表一個(gè)不同的命名空間域,不同的命名空間不能同名。這樣,可以把不同的庫中的實(shí)體放到不同的命名空間中,或者說,用不同的命名空間把不同的實(shí)體隱藏起來。過去用的全局變量可以理解為存在于全局命名空間,獨(dú)立域所有有名的命名空間之外,不是不需要namespace聲明的,實(shí)際上是由系統(tǒng)隱式聲明的,在該空間中有效。
??命名空間的類型
在聲明一個(gè)命名空間時(shí),花括號內(nèi)不僅可以包括變量,而且還可以包括一下類型:
- 變量(可以帶有初始化);
- 常量;
- 函數(shù)(可以是定義或聲明);
- 結(jié)構(gòu)體;
- 類;
- 模板;
- 命名空間(在一個(gè)命名空間中又定義了一個(gè)命名空間,即嵌套的命名空間)。
??命名空間的成員
例如:
namespace ns1 //指定命名空間ns1 { int a; double b; }
- ns1是命名空間的名字。
- 在花括號內(nèi),聲明的實(shí)體即為命名空間的成員,包括全局變量a和b。
- 使用a和b,需要加上命名空間和作用域分辨符"::",如ns1::a,ns1::b。
- 需要注意的是,a和b仍然是全局變量,僅僅是把他們放在了命名空間中而已。
??命名空間的使用
舉例如下:
namespace ns1 { const int RATE=0.08;//常量 double pay;//變量 double tax()//函數(shù) { return a*RATE; } namespace ns2 //嵌套命名空間 { int age; } }
輸出命名空間中ns1中成員的數(shù)據(jù):
cout<<ns1::RATE<<endl;
cout<<ns1::pay<<endl;
cout<<ns1::tax()<<end;
cout<<ns1::ns2::age<<endl;
??使用命名空間解決名字沖突
聲明命名空間ns1,并在命名空間ns1中聲明Student類和定義成員函數(shù)、定義fun函數(shù)。
#pragma once //header1.h #include <iostream> #include<string> #include <cmath> using namespace std; namespace ns1 { class Student //聲明Student類 { public: Student(int n, string nam, int a) { num = n; name = nam; age = a; } void get_data(); private: int num; string name; int age; }; //成員函數(shù)的定義 void Student::get_data() { cout << num << "" << name << "" << age << endl; } //定義全局函數(shù)(即外部函數(shù)) double fun(double a, double b) { return sqrt(a + b); } }
在header2.h中,聲明命名空間ns2,并在命名空間ns2中定義Student類和 成員函數(shù)以及fun函數(shù)。
using namespace std; namespace ns2 { class Student { public: Student(int n, string nam, char s)//參數(shù)與header1.h中不同 { num = n; name = nam; sex = s; } void get_data(); private: int num; string name; char sex; }; //成員函數(shù)定義 void Student::get_data() { cout << num << "" << name << "" << sex << endl; } //定義全局函數(shù) double fun(double a, double b) { return sqrt(a - b);//返回值與header1中的fun函數(shù)不同 } }
主函數(shù)如下:
#include "header1.h"; #include "header2.h"; int main() { ns1::Student stud1(101, "Wang", 18);//用命名空間ns1中的Student類定義stud1 stud1.get_data(); cout <<ns1:: fun(5, 3) << endl;//調(diào)用命名空間ns1中的fun函數(shù) ns2::Student stud2(102, "Li", 'f');//用命名空間ns2中的Student類定義stud2 stud2.get_data(); cout << ns2::fun(5, 3) << endl;//調(diào)用命名空間ns2中的fun函數(shù) return 0; }
運(yùn)行結(jié)果如下:
到此這篇關(guān)于C++ 命名空間避免命名沖突的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)C++ 命名空間避免命名沖突內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++?Boost?StringAlgorithms超詳細(xì)講解
Boost是為C++語言標(biāo)準(zhǔn)庫提供擴(kuò)展的一些C++程序庫的總稱。Boost庫是一個(gè)可移植、提供源代碼的C++庫,作為標(biāo)準(zhǔn)庫的后備,是C++標(biāo)準(zhǔn)化進(jìn)程的開發(fā)引擎之一,是為C++語言標(biāo)準(zhǔn)庫提供擴(kuò)展的一些C++程序庫的總稱2022-11-11C++實(shí)現(xiàn)主機(jī)字節(jié)序和網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換示例
這篇文章主要為大家介紹了C++實(shí)現(xiàn)主機(jī)字節(jié)序和網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11C++面試題之進(jìn)制轉(zhuǎn)換的實(shí)例
這篇文章主要介紹了C++面試題之進(jìn)制轉(zhuǎn)換的實(shí)例的相關(guān)資料,希望通過本文能幫助到大家,讓大家理解掌握這樣的知識,需要的朋友可以參考下2017-10-10Qt6實(shí)現(xiàn)調(diào)用攝像頭并顯示畫面
這篇文章主要為大家詳細(xì)介紹了Qt6如何實(shí)現(xiàn)調(diào)用攝像頭并顯示畫面的效果,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以參考一下2023-02-02C++中實(shí)現(xiàn)多態(tài)有幾種方式小結(jié)
在C++中,多態(tài)是一種面向?qū)ο缶幊痰奶匦?允許以統(tǒng)一的方式處理不同類型的對象,并根據(jù)實(shí)際對象的類型來執(zhí)行相應(yīng)的操作,本文給大家介紹了C++中實(shí)現(xiàn)多態(tài)有幾種方式小結(jié),需要的朋友可以參考下2024-12-12