久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

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

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:244281 發(fā)表于 2018-3-5 19:19 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
本帖最后由 tyyhmtyyhm 于 2018-3-5 19:29 編輯


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

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

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

評分

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

查看全部評分

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

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: www.久久久.com| 精品日韩一区二区 | 欧美成年网站 | 夜夜草天天草 | 黄色国产在线播放 | 久久69精品久久久久久久电影好 | 成年人免费在线视频 | 欧美在线看片 | 国产精品久久福利 | 青青草av | 在线国产视频 | 黄色日批视频 | 成人午夜免费福利视频 | 久久综合av| 2019中文字幕视频 | 成人在线免费观看av | 日本成人在线播放 | 久久久久91 | 亚洲精品一区二区三区在线观看 | 九九精品视频在线 | 亚洲欧美激情精品一区二区 | 亚洲一区中文字幕 | 九九在线视频 | 日韩精品四区 | 日本欧美在线观看视频 | 欧美性久久久 | 国产一二三视频在线观看 | 国产午夜精品视频 | 天天成人综合网 | 日韩a视频 | 精品一区二区三区在线观看 | 日韩一区二区三区在线观看 | 久久毛片| 特黄特黄a级毛片免费专区 av网站免费在线观看 | 亚洲国产欧美一区二区三区久久 | 国产91丝袜在线熟 | 国产精品免费一区二区三区四区 | 久久久成人一区二区免费影院 | 国产精品一区二区免费 | 国产一区二区三区四区在线观看 | 国产精品久久久久久吹潮 |