欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 2383|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

[C++]筆記八:C++對(duì)C的擴(kuò)展——命名空間 namespace基礎(chǔ)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
本帖最后由 tyyhmtyyhm 于 2018-3-5 19:29 編輯


C++對(duì)C的擴(kuò)展——命名空間 namespace基礎(chǔ)第一,命名空間的意義
命名空間是ANSIC++引入的可以由用戶命名的作用域,用來處理程序中常見的同名沖突。
我認(rèn)識(shí)兩位叫“A”的朋友,一位是我同學(xué),一位是我同事,兩個(gè)人的聯(lián)系方式在手機(jī)中保存的時(shí)候需要備注一下“同學(xué)A”、“同事A”,在名字前面加上額外的信息加以區(qū)分,雖然有時(shí)候腦袋會(huì)不清醒,打電話會(huì)打錯(cuò)……
同樣的情況也出現(xiàn)在C++編程中。例如,我自己寫一個(gè)顯示函數(shù)show(),在另外一個(gè)可用的庫中也有一個(gè)顯示函數(shù)show(),二者函數(shù)名相同。這樣我在調(diào)用函數(shù)時(shí),編譯器就無法判斷我是用的是哪一個(gè)show()函數(shù)。
因此引入命名空間(namespace)這個(gè)概念,專門用于解決上面的問題,就像在“A”這個(gè)名字前面加上額外的附加信息一樣(額外的附加信息…..這句是不是病句),命名空間可以用來作為附加信息來區(qū)分不同庫中相同名稱的函數(shù)、類、變量等。本質(zhì)上,命名空間就是定義了一個(gè)范圍。
再說幾句,我們之前看到的代碼都有這條語句:using namespace std;即使用命名空間std,規(guī)定該文件中使用的標(biāo)準(zhǔn)庫函數(shù)都是在標(biāo)準(zhǔn)命名空間std中定義的。
為什么需要將這些函數(shù)、類等定義在命名空間中呢?這其實(shí)是為了避免變量或函數(shù)重名的問題。一個(gè)項(xiàng)目往往由多個(gè)工程師開發(fā)完成,有可能出現(xiàn)全局變量或函數(shù)重名的現(xiàn)象,而如果每個(gè)人都定義了自己的命名空間就可以解決這個(gè)問題,即使重名,只要分屬不同的命名空間就不會(huì)引起問題。
C語言中定義了3個(gè)層次的作用域,即文件(編譯單元)、函數(shù)和復(fù)合語句。C++又引入了類作用域,類是出現(xiàn)在文件內(nèi)的。在不同的作用域中可以定義相同名字的變量,互不于擾,系統(tǒng)能夠區(qū)別它們。
全局變量的作用域是整個(gè)程序,在同一作用域中不應(yīng)有兩個(gè)或多個(gè)同名的實(shí)體(enuty),包括變量、函數(shù)和類等。
例:如果在文件中定義了兩個(gè)類,在這兩個(gè)類中可以有同名的函數(shù)。在引用時(shí),為了區(qū)別,應(yīng)該加上類名作為限定:
class A //聲明A類
{
public:
void funl();//聲明A類中的funl函數(shù)
private:
int i;
};
void A::funl() //定義A類中的funl函數(shù)
{…………}
class B //聲明B類
{
public:
void funl(); //B類中也有funl函數(shù)
void fun2();
};
void B::funl() //定義B類中的funl函數(shù)
{ …………}
這樣不會(huì)發(fā)生混淆。
在文件中可以定義全局變量(global variable),它的作用域是整個(gè)程序。如果在文件A中定義了一個(gè)變量a   inta=3;
在文件B中可以再定義一個(gè)變量a   int a=5;
在分別對(duì)文件A和文件B進(jìn)行編譯時(shí)不會(huì)有問題。但是,如果一個(gè)程序包括文件A和文件B,那么在進(jìn)行連接時(shí),會(huì)報(bào)告出錯(cuò),因?yàn)樵谕粋(gè)程序中有兩個(gè)同名的變量,認(rèn)為是對(duì)變量的重復(fù)定義。
可以通過extern聲明同一程序中的兩個(gè)文件中的同名變量是同一個(gè)變量。如果在文件B中有以下聲明: extemint a; 表示文件B中的變量a是在其他文件中已定義的變量。由于有此聲明,在程序編譯和連接后,文件A的變量a的作用域擴(kuò)展到了文件B。如果在文件B中不再對(duì)a賦值,則在文件B中用以下語句輸出的是文件A中變量a的值:cout<<a; //得到a的值為3
第二,命名空間的定義
命名空間的定義使用關(guān)鍵字namespace,后跟命名空間的名稱,如下所示:
namespace  A
{
void  Fun1(){...};
void  Fun2(){...};
}
上面的組織形式我們將函數(shù)的具體實(shí)現(xiàn)和聲明放到了一起,有時(shí)候我們并不想看到函數(shù)的具體實(shí)現(xiàn),只希望能一眼看到的全部都是函數(shù)的接口界面。我們可以采用如下的方式將函數(shù)的界面和具體實(shí)現(xiàn)分開。
namespace A
{
    int a;
double b;
void  Fun1();
void  Fun2();
}
void A::Fun1(){/*...*/}
void A::Fun2(){/*...*/}
1、如果一個(gè)函數(shù)的定義沒有在其對(duì)應(yīng)的命名空間里,必須要使用作用域解析符::來指定函數(shù)的命名空間。
2、不可以在命名空間以外定義一個(gè)命名空間中不存在的新成員。例如:
void A::Fun3();//錯(cuò)誤,A里并沒有Fun3()
3、一個(gè)良好的程序應(yīng)該將程序中的所有實(shí)體(變量,類,函數(shù))都放到某個(gè)命名空間里。當(dāng)然除了main()函數(shù)之外。
命名空間內(nèi)部不僅可以聲明或定義變量,對(duì)于其它能在命名空間以外聲明或定義的實(shí)體,同樣也都能在命名空間內(nèi)部進(jìn)行聲明或定義,例如變量的聲明或定義、函數(shù)的聲明或定義、typedef等都可以出現(xiàn)在命名空間中。
namespace 是定義命名空間所必須寫的關(guān)鍵字,A是用戶自己指定的命名空間的名字(可以用任意的合法標(biāo)識(shí)符),在花括號(hào)內(nèi)是聲明塊,在其中聲明的實(shí)體稱為命名空間成員(namespacemember)。現(xiàn)在命名空間成員包括變量a和b,注意二者仍然是全局變量,僅僅是把它們隱藏在指定的命名空間中而已。如果在程序中要使用變量a和b,必須加上命名空間名和作用域分辨符“::”,如A:a,A::b。這種用法稱為命名空間限定(qualified),這些名字(如A::a)稱為被限定名(qualified name)。C++中命名空間的作用類似于操作系統(tǒng)中的目錄和文件的關(guān)系,由于文件很多,不便管理,而且容易重名,于是人們?cè)O(shè)立若干子目錄,把文件分別放到不同的子目錄中,不同子目錄中的文件可以同名。調(diào)用文件時(shí)應(yīng)指出文件路徑。
命名空間的作用:是建立一些互相分隔的作用域,把一些全局實(shí)體分隔開來。以免產(chǎn)生老師點(diǎn)名叫李華時(shí),3個(gè)同名的學(xué)生都站起來應(yīng)答,這就是名字沖突,因?yàn)樗麄儫o法辨別老師想叫的是哪一個(gè)李華,同名者無法互相區(qū)分。為了避免同名混淆,學(xué)校把3個(gè)同名的學(xué)生分在3個(gè)班。這樣,在小班點(diǎn)名叫李華時(shí),只會(huì)有一個(gè)人應(yīng)答。也就是說,在該班的范圍(即班作用域)內(nèi)名字是惟一的。如果在全校集合時(shí)校長(zhǎng)點(diǎn)名,需要在全校范圍內(nèi)找這個(gè)學(xué)生,就需要考慮作用域問題。如果校長(zhǎng)叫李華,全校學(xué)生中又會(huì)有3人一齊喊“到”,因?yàn)樵谕蛔饔糜蛑写嬖?個(gè)同名學(xué)生。為了在全校范圍內(nèi)區(qū)分這3名學(xué)生,校長(zhǎng)必須在名字前加上班號(hào),如高三甲班的李華,或高三乙班的李華,即加上班名限定。這樣就不致產(chǎn)生混淆。
可以根據(jù)需要設(shè)置許多個(gè)命名空間,每個(gè)命名空間名代表一個(gè)不同的命名空間域,不同的命名空間不能同名。這樣,可以把不同的庫中的實(shí)體放到不同的命名空間中,或者說,用不同的命名空間把不同的實(shí)體隱蔽起來。過去我們用的全局變量可以理解為全局命名空間,獨(dú)立于所有有名的命名空間之外,它是不需要用 namespace聲明的,實(shí)際上是由系統(tǒng)隱式聲明的,存在于每個(gè)程序之中。
在聲明一個(gè)命名空間時(shí),花括號(hào)內(nèi)不僅可以包括變量,而且還可以包括以下類型:
·變量(可以帶有初始化);
·常量;
·數(shù)(可以是定義或聲明);
·結(jié)構(gòu)體;
·類;
·模板;
·命名空間(在一個(gè)命名空間中又定義一個(gè)命名空間,即嵌套的命名空間)。
例如
namespace nsl
{
const int RATE=0.08; //常量
double pay; //變量
double tax() //函數(shù)
{
return a*RATE;
}
namespace  ns2    //嵌套的命名空間
{
int age;
}
}
如果想輸出命名空間nsl中成員的數(shù)據(jù),可以采用下面的方法:
cout<<nsl::RATE<<endl;
cout<<nsl::pay<<endl;
cout<<nsl::tax()<<endl;
cout<<nsl::ns2::age<<endl; //需要指定外層的和內(nèi)層的命名空間名
   可以看到命名空間的聲明方法和使用方法與類差不多。但它們之間有一點(diǎn)差別:在聲明類時(shí)在右花括號(hào)的后面有一分號(hào),而在定義命名空間時(shí),花括號(hào)的后面沒有分號(hào)。
第三,命名空間的使用
第一種:命名空間::標(biāo)識(shí)符名稱
為了調(diào)用帶有命名空間的函數(shù)或變量,需要在前面加上命名空間的名稱,我們看到,使用“命名空間::標(biāo)識(shí)符名稱”的方式就可以訪問命名空間中的變量或函數(shù)了,而且即使是重復(fù)命名也可以正確訪問。
讓我們來看看命名空間如何為變量或函數(shù)等實(shí)體定義范圍:
定義兩個(gè)命名空間,在使用函數(shù)func()時(shí),用first_space::func()和second_space::func()來指明使用的是哪個(gè)func函數(shù),cout和endl屬于std命名空間。
#include<iostream>
//usingnamespace std;
//第一個(gè)命名空間
namespace first_space
{
         voidfunc()
         {
                   std::cout<<"Inside first_space"<<std::endl;
         }      
}
//第二個(gè)命名空間
namespace second_space
{
         voidfunc()
         {
                   std::cout<<"Inside second_space"<<std::endl;
         }
}
int main()
{
//調(diào)用第一個(gè)命名空間中的函數(shù)
first_space::func();
//調(diào)用第二個(gè)命名空間中的函數(shù)
second_space::func();
      
    system("pause");
    return 0;
}
執(zhí)行結(jié)果如圖
                              
第二種:using指令之聲明整個(gè)命名空間
可以使用usingnamespace *;指令,這里的*可以表示任何命名空間,其作用是釋放命名空間*中的變量或函數(shù)等,使之在被訪問時(shí)可以不必加“命名空間::”,訪問方法與一般的變量或函數(shù)無異。這樣在使用命名空間中的變量、函數(shù)、類等時(shí)就不需要在前面加上命名空間的名稱,這個(gè)指令會(huì)告訴編譯器,后續(xù)的代碼將使用指定的命名空間中的名稱。
#include<iostream>
//using namespace std;
//第一個(gè)命名空間
namespace first_space
{
         void func()
         {
                   std::cout<<"Inside first_space"<<std::endl;
         }      
}
//第二個(gè)命名空間
namespace second_space
{
         void func()
         {
                   std::cout<<"Inside second_space"<<std::endl;
         }
}
using namespacefirst_space;
int main()
{
//調(diào)用第一個(gè)命名空間中的函數(shù)
         func();
         
         system("pause");
         return 0;
}
在main函數(shù)上面已經(jīng)用using namespace *;指令釋放了first_space命名空間中的函數(shù),因此main函數(shù)中func()函數(shù)就知道使用哪個(gè)命名空間中的func()函數(shù)了。

using namespace *;會(huì)給我們書寫程序帶來方便,但也要慎用,如果釋放了多個(gè)命名空間中的東西后,它們又可能會(huì)引起命名沖突。下面演示同時(shí)釋放first_space和second_space命名空間的情況。
#include <iostream>
using namespacestd;  
  
// 命名空間 first_space
namespace first_space  
{  
    char *Url = "Autocodes";  
}  
  
// 命名空間 second_space  
namespace second_space  
{  
    char *Url = "AutocodesAutocodes";  
}  
  
// 釋放命名空間 first_space second_space  
using namespacefirst_space;  
using namespacesecond_space;  
  
int main()
{  
    cout <<Url << endl;
         system("pause");
    return 0;  
}
上例中,編譯器會(huì)提示編譯錯(cuò)誤,因?yàn)樗恢涝撛L問哪個(gè)命名空間中的字符串變量Url。這時(shí)要想正確訪問,還需在Url前面加上命名空間修飾。
  而如果main函數(shù)中又定義了一個(gè)局部變量Url呢?
#include <iostream>
using namespacestd;  
  
// 命名空間 first_space
namespace first_space  
{  
    char *Url = "Autocodes";  
}  
  
// 命名空間 second_space  
namespace second_space  
{  
    char *Url = "AutocodesAutocodes";  
}  
  
// 釋放命名空間 first_space second_space  
using namespacefirst_space;  
using namespacesecond_space;  
  
int main()
{  
char *Url = "Autocodes Autocodes Autocodes";  
    cout <<Url << endl;
         system("pause");
    return 0;  
}
運(yùn)行后我們發(fā)現(xiàn),Url訪問正確,可見,這種情況下,編譯器優(yōu)先訪問局部變量。
第三種:using指令之聲明命名空間中特定的項(xiàng)目
using不僅僅可以用于聲明整個(gè)命名空間,也可以針對(duì)命名空間中的一個(gè)名稱。
using指令也可以用來指定命名空間中的特定項(xiàng)目。例如,如果只打算使用命名空間中的cout,可以使用如下語句:
using std::cout;
隨后的代碼中,在使用cout時(shí)就可以不用加上命名空間名稱作為前綴,但是命名空間std中的其他項(xiàng)目仍然需要加上命名空間名稱作為前綴,如下所示:
#include <iostream>
using std::cout;
int main ()
{
cout<< "std::endl is used with std!" << std::endl;
return 0;
}

using 指令引入的名稱遵循正常的范圍規(guī)則。名稱從使用 using 指令開始是可見的,直到該范圍結(jié)束。此時(shí),在范圍以外定義的同名實(shí)體是隱藏的。
第四,不連續(xù)的命名空間
命名空間可以定義在幾個(gè)不同的部分中,因此命名空間是由幾個(gè)單獨(dú)定義的部分組成的。一個(gè)命名空間的各個(gè)組成部分可以分散在多個(gè)文件中。
所以,如果命名空間中的某個(gè)組成部分需要請(qǐng)求定義在另一個(gè)文件中的名稱,則仍然需要聲明該名稱。下面的命名空間定義可以是定義一個(gè)新的命名空間,也可以是為已有的命名空間增加新的元素:
namespace namespace_name  
{
       //代碼聲明
}
第五,嵌套的命名空間
命名空間可以嵌套,可以在一個(gè)命名空間中定義另一個(gè)命名空間,如下所示:
namespace namespace_name1
{
       //代碼聲明
       namespace  namespace_name2
{
//代碼聲明
}
}
可以使用::運(yùn)算符來訪問嵌套的命名空間中的成員:
//訪問namespace_name2中的成員
using namespace namespace_name1::namespace_name2;
//訪問namespace_name1中的成員
using namespace  namespace_name1;
在上面的語句中,如果使用的是namespace_name1,那么在該范圍內(nèi)namespace_name2中的元素也是可用的,如下所示:
第六,多重界面
有時(shí)候我們同一個(gè)命名空間在面向不同的用戶時(shí),可能需要提供不同的界面。比如我們有一個(gè)命名空間里面定義了關(guān)于串口的一些實(shí)體。我們給一個(gè)開發(fā)中的程序提供的接口可能包括:打開串口,設(shè)置波特率,設(shè)置校驗(yàn)位等。但是面向一個(gè)最終用戶時(shí),我們可能只需要給他提供一個(gè)打開串口接口就夠了。這便是使用多重界面的意義。
1、實(shí)現(xiàn)多重界面的方法有很多,首先可能想到的是使用不同的命名空間。
namespace A
{
void Fun1();
void Fun2();
void Fun3();
}
namespaceA_Interface1
{
usingA::Fun1;
}
2、上面界面實(shí)現(xiàn)的過程中,A_Interface1和A有著非常強(qiáng)的關(guān)聯(lián),修改A中的Fun1會(huì)使A_Interface1中的Fun1也修改。有時(shí)候我們可能不需要這么強(qiáng)的關(guān)聯(lián)性,讓A_Interface1中的函數(shù)有著一定的可控性,可以使用下面界面實(shí)現(xiàn)的方式。
namespaceA
{
void Fun1();
void Fun2();
void Fun3();
}
namespaceA_Interface1
{
void Fun1()
{
A::Fun1();
}
}
第七,無名命名空間
我們知道不同命名空間的變量名可以重復(fù),這有助于第三方將兩個(gè)不同人寫的代碼進(jìn)行整合。有時(shí)候我們并不想我們的某些代碼被其他人進(jìn)行整合,但是也想利用命名空間的優(yōu)勢(shì)——可以讓變量名重復(fù)。這時(shí)候使用無名命名空間就很有價(jià)值了:第一沒有名字,其他地方無法引用進(jìn)去;第二因?yàn)槭敲臻g它里面的變量可以和其他命名空間中變量的名字重復(fù)。
無名命名空間可以在本編譯單元(所在文件)處調(diào)用,沒有這一規(guī)則就永遠(yuǎn)都用不到了。需要注意的是,不同編譯單元中的無名命名空間不同。
第八,命名空間的別名
我們?cè)诮o命名空間取名字的時(shí)候,如果太短(比如上面的A)很可能出現(xiàn)沖突。名太長(zhǎng)又太麻煩。這時(shí)候我們將長(zhǎng)名字的命名空間在合適的地方取個(gè)別名可能會(huì)更好些。格式如下:
namespace A = LongNameNamespaceA;
這種替換的方式和C語言中的宏定義非常相似,因此別名另外一個(gè)特別用于的地方就是使代碼對(duì)命名空間的依賴降低。比如我們有一個(gè)大型程序依賴于一個(gè)命名空間LibA,現(xiàn)在需要版本升級(jí)將所有引用LibA中的代碼替換為L(zhǎng)ibA_Plus.如果使用起別名的方式,我們不用再代碼中逐個(gè)查找將LibA::替換為L(zhǎng)ibA_Plus.而是簡(jiǎn)單的在命名空間的別名定義處稍作修改即可。
namespace A = LibA;
//替換為
namespaceA = LibA_Plus;
但也需要注意過多的使用命名空間別名也容易造成混亂。
再如 :
namespaceTelevision     //聲明命名空間,名為Television
{ … }
可以用一個(gè)較短而易記的別名代替它。如:
namespace TV=Television; //別名TV與原名Television等價(jià)
也可以說,別名TV指向原名Television,在原來出現(xiàn)Television的位置都可以無條件地用TV來代替。
【C++】筆記系列均為原創(chuàng),轉(zhuǎn)載請(qǐng)注明轉(zhuǎn)自微號(hào):Lightspeed-Tech  或  AutoCode
更多精彩資料,請(qǐng)關(guān)注!

評(píng)分

參與人數(shù) 1黑幣 +10 收起 理由
白鶴859 + 10 很給力!

查看全部評(píng)分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂2 踩
回復(fù)

使用道具 舉報(bào)

無效樓層,該帖已經(jīng)被刪除

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表