無論是身處學(xué)校還是步入社會(huì),大家都嘗試過寫作吧,借助寫作也可以提高我們的語言組織能力。大家想知道怎么樣才能寫一篇比較優(yōu)質(zhì)的范文嗎?這里我整理了一些優(yōu)秀的范文,希望對(duì)大家有所幫助,下面我們就來了解一下吧。
標(biāo)準(zhǔn)命名空間 命名空間的概念及作用篇一
對(duì)于命名空間,官方文檔已經(jīng)說得很詳細(xì)[查看],我在這里做了一下實(shí)踐和總結(jié)。
命名空間一個(gè)最明確的目的就是解決重名問題,php中不允許兩個(gè)函數(shù)或者類出現(xiàn)相同的名字,否則會(huì)產(chǎn)生一個(gè)致命的錯(cuò)誤。這種情況下只要避免命名重復(fù)就可以解決,最常見的一種做法是約定一個(gè)前綴。例:項(xiàng)目中有兩個(gè)模塊:article和message board,它們各自有一個(gè)處理用戶留言的類comment。之后我可能想要增加對(duì)所有用戶留言的一些信息統(tǒng)計(jì)功能,比如說我想得到所有留言的數(shù)量。這時(shí)候調(diào)用它們comment提供的方法是很好的做法,但是同時(shí)引入各自的comment類顯然是不行的,代碼會(huì)出錯(cuò),在另一個(gè)地方重寫任何一個(gè)comment也會(huì)降低維護(hù)性。那這時(shí)只能重構(gòu)類名,我約定了一個(gè)命名規(guī)則,在類名前面加上模塊名,像這樣:article_comment、messageboard_comment 可以看到,名字變得很長,那意味著以后使用comment的時(shí)候會(huì)寫上更多的代碼(至少字符多了)。并且,以后如果要對(duì)各個(gè)模塊增加更多的一些整合功能,或者是互相調(diào)用,發(fā)生重名的時(shí)候就需要重構(gòu)名字。當(dāng)然在項(xiàng)目開始的時(shí)候就注意到這個(gè)問題,并規(guī)定命名規(guī)則就能很好的避免這個(gè)問題。另一個(gè)解決方法可以考慮使用命名空間。
注明:
本文提到的常量:php5.3開始const關(guān)鍵字可以用在類的外部。const和define都是用來聲明常量的(它們的區(qū)別不詳述),但是在命名空間里,define的作用是全局的,而const則作用于當(dāng)前空間。我在文中提到的常量是指使用const聲明的常量。
基礎(chǔ)
命名空間將代碼劃分出不同的空間(區(qū)域),每個(gè)空間的常量、函數(shù)、類(為了偷懶,我下邊都將它們稱為元素)的名字互不影響,這個(gè)有點(diǎn)類似我們常常提到的‘封裝'的概念。創(chuàng)建一個(gè)命名空間需要使用namespace關(guān)鍵字,這樣: 復(fù)制代碼代碼如下:
//創(chuàng)建一個(gè)名為'article'的命名空間 namespace article;?>
要注意的是,當(dāng)前腳本文件的第一個(gè)命名空間前面不能有任何代碼,下面的寫法都是錯(cuò)誤的: 復(fù)制代碼代碼如下: //例一
//在腳本前面寫了一些邏輯代碼
//例二
//在腳本前面輸出了一些字符
為什么要說第一個(gè)命名空間呢?因?yàn)橥荒_本文件中可以創(chuàng)建多個(gè)命名空間。
下面我創(chuàng)建了兩個(gè)命名空間,順便為這兩個(gè)空間各自添加了一個(gè)comment類元素: 復(fù)制代碼代碼如下:
//創(chuàng)建一個(gè)名為'article'的命名空間 namespace article;//此comment屬于article空間的元素 class comment { }
//創(chuàng)建一個(gè)名為'messageboard'的命名空間 namespace messageboard;//此comment屬于messageboard空間的元素 class comment { } ?>
在不同空間之間不可以直接調(diào)用其它元素,需要使用命名空間的語法: 復(fù)制代碼代碼如下:
namespace article;class comment { }
namespace messageboard;class comment { } //調(diào)用當(dāng)前空間(messageboard)的comment類 $comment = new comment();//調(diào)用article空間的comment類
$article_comment = new articlecomment();?>
可以看到,在messageboard空間中調(diào)用article空間里的comment類時(shí),使用了一種像文件路徑的語法: 空間名元素名
除了類之外,對(duì)函數(shù)和常量的用法是一樣的,下面我為兩個(gè)空間創(chuàng)建了新的元素,并在messageboard空間中輸出了它們的值。復(fù)制代碼代碼如下:
namespace messageboard;const path = '/message_board';function getcommenttotal(){ return 300;} class comment { } //調(diào)用當(dāng)前空間的常量、函數(shù)和類 echo path;///message_board echo getcommenttotal();//300 $comment = new comment();//調(diào)用article空間的常量、函數(shù)和類 echo articlepath;///article echo articlegetcommenttotal();//100 $article_comment = new articlecomment();?>
然后我的確得到了article空間的元素?cái)?shù)據(jù)。子空間
命名空間的調(diào)用語法像文件路徑一樣是有道理的,它允許我們自定義子空間來描述各個(gè)空間之間的關(guān)系。抱歉我忘了說,article和message board這兩個(gè)模塊其實(shí)都是處于同一個(gè)blog項(xiàng)目內(nèi)。如果用命名空間來表達(dá)它們的關(guān)系,是這樣: 復(fù)制代碼代碼如下:
//我用這樣的命名空間表示處于blog下的article模塊 namespace blogarticle;class comment { }
//我用這樣的命名空間表示處于blog下的message board模塊 namespace blogmessageboard;class comment { } //調(diào)用當(dāng)前空間的類
$comment = new comment();//調(diào)用blogarticle空間的類
$article_comment = new blogarticlecomment();?>
而且,子空間還可以定義很多層次,比如說 blogarticlearchivesdate
公共空間
我有一個(gè)腳本文件,里面有一些好用的函數(shù)和類: 復(fù)制代碼代碼如下:
function getip(){ } class filterxss { } ?>
在一個(gè)命名空間里引入這個(gè)腳本,腳本里的元素不會(huì)歸屬到這個(gè)命名空間。如果這個(gè)腳本里沒有定義其它命名空間,它的元素就始終處于公共空間中: 復(fù)制代碼代碼如下:
namespace blogarticle;//引入腳本文件
include './';$filter_xss = new filterxss();//出現(xiàn)致命錯(cuò)誤:找不到blogarticlefilterxss類 $filter_xss = new filterxss();//正確 ?>
調(diào)用公共空間的方式是直接在元素名稱前加 就可以了,否則php解析器會(huì)認(rèn)為我想調(diào)用當(dāng)前空間下的元素。除了自定義的元素,還包括php自帶的元素,都屬于公共空間。
要提一下,其實(shí)公共空間的函數(shù)和常量不用加 也可以正常調(diào)用(不明白php為什么要這樣做),但是為了正確區(qū)分元素,還是建議調(diào)用函數(shù)的時(shí)候加上
名稱術(shù)語
在說別名和導(dǎo)入之前,需要知道關(guān)于空間三種名稱的術(shù)語,以及php是怎樣解析它們的。官方文檔說得非常好,我就直接拿來套了。
1.非限定名稱,或不包含前綴的類名稱,例如 $comment = new comment()。如果當(dāng)前命名空間是blogarticle,comment將被解析為blogarticlecomment。如果使用comment的代碼不包含在任何命名空間中的代碼(全局空間中),則comment會(huì)被解析為comment。
2.限定名稱,或包含前綴的名稱,例如 $comment = new articlecomment()。如果當(dāng)前的命名空間是blog,則comment會(huì)被解析為blogarticlecomment。如果使用comment的代碼不包含在任何命名空間中的代碼(全局空間中),則comment會(huì)被解析為comment。
3.完全限定名稱,或包含了全局前綴操作符的名稱,例如 $comment = new articlecomment()。在這種情況下,comment總是被解析為代碼中的文字名(literal name)articlecomment。
其實(shí)可以把這三種名稱類比為文件名(例如 )、相對(duì)路徑名(例如./article/)、絕對(duì)路徑名(例如 /blog/article/),這樣可能會(huì)更容易理解。我用了幾個(gè)示例來表示它們: 復(fù)制代碼代碼如下:
//創(chuàng)建空間blog namespace blog;class comment { } //非限定名稱,表示當(dāng)前blog空間 //這個(gè)調(diào)用將被解析成 blogcomment();$blog_comment = new comment();//限定名稱,表示相對(duì)于blog空間
//這個(gè)調(diào)用將被解析成 blogarticlecomment();$article_comment = new articlecomment();//類前面沒有反斜桿 //完全限定名稱,表示絕對(duì)于blog空間 //這個(gè)調(diào)用將被解析成 blogcomment();$article_comment = new blogcomment();//類前面有反斜桿 //完全限定名稱,表示絕對(duì)于blog空間
//這個(gè)調(diào)用將被解析成 blogarticlecomment();$article_comment = new blogarticlecomment();//類前面有反斜桿
//創(chuàng)建blog的子空間article namespace blogarticle;class comment { } ?>
其實(shí)之前我就一直在使用非限定名稱和完全限定名稱,現(xiàn)在它們終于可以叫出它們的名稱了。
別名和導(dǎo)入
別名和導(dǎo)入可以看作是調(diào)用命名空間元素的一種快捷方式。php并不支持導(dǎo)入函數(shù)或常量。它們都是通過使用use操作符來實(shí)現(xiàn): 復(fù)制代碼代碼如下:
namespace blogarticle;class comment { }
//創(chuàng)建一個(gè)bbs空間(我有打算開個(gè)論壇)namespace bbs;//導(dǎo)入一個(gè)命名空間 use blogarticle;//導(dǎo)入命名空間后可使用限定名稱調(diào)用元素 $article_comment = new articlecomment();//為命名空間使用別名 use blogarticle as arte;//使用別名代替空間名
$article_comment = new artecomment();//導(dǎo)入一個(gè)類
use blogarticlecomment;//導(dǎo)入類后可使用非限定名稱調(diào)用元素 $article_comment = new comment();//為類使用別名
use blogarticlecomment as comt;//使用別名代替空間名
$article_comment = new comt();?>
我注意到,如果導(dǎo)入元素的時(shí)候,當(dāng)前空間有相同的名字元素將會(huì)怎樣?顯然結(jié)果會(huì)發(fā)生致命錯(cuò)誤。
例:
復(fù)制代碼代碼如下:
namespace blogarticle;class comment { }
namespace bbs;class comment { } class comt { }
//導(dǎo)入一個(gè)類
use blogarticlecomment;$article_comment = new comment();//與當(dāng)前空間的comment發(fā)生沖突,程序產(chǎn)生致命錯(cuò)誤 //為類使用別名
use blogarticlecomment as comt;$article_comment = new comt();//與當(dāng)前空間的comt發(fā)生沖突,程序產(chǎn)生致命錯(cuò)誤 ?> 動(dòng)態(tài)調(diào)用
php提供了namespace關(guān)鍵字和__namespace__魔法常量動(dòng)態(tài)的訪問元素,__namespace__可以通過組合字符串的形式來動(dòng)態(tài)訪問: 復(fù)制代碼代碼如下:
namespace blogarticle;const path = '/blog/article';class comment { }
//namespace關(guān)鍵字表示當(dāng)前空間 echo namespacepath;///blog/article $comment = new namespacecomment();//魔法常量__namespace__的值是當(dāng)前空間名稱 echo __namespace__;//blogarticle //可以組合成字符串并調(diào)用
$comment_class_name = __namespace__.'comment';$comment = new $comment_class_name();?>
字符串形式調(diào)用問題
上面的動(dòng)態(tài)調(diào)用的例子中,我們看到了字符串形式的動(dòng)態(tài)調(diào)用方式,如果要使用這種方式要注意兩個(gè)問題。
1.使用雙引號(hào)的時(shí)候特殊字符可能被轉(zhuǎn)義 復(fù)制代碼代碼如下:
namespace blogarticle;class name { } //我是想調(diào)用blogarticlename $class_name = __namespace__.“name”;//但是n將被轉(zhuǎn)義為換行符 $name = new $class_name();//發(fā)生致命錯(cuò)誤 ?>
2.不會(huì)認(rèn)為是限定名稱
php在編譯腳本的時(shí)候就確定了元素所在的空間,以及導(dǎo)入的情況。而在解析腳本時(shí)字符串形式調(diào)用只能認(rèn)為是非限定名稱和完全限定名稱,而永遠(yuǎn)不可能是限定名稱。復(fù)制代碼代碼如下:
namespace blog;//導(dǎo)入common類
use blogarticlecommon;//我想使用非限定名稱調(diào)用blogarticlecommon $common_class_name = 'common';//實(shí)際會(huì)被當(dāng)作非限定名稱,也就表示當(dāng)前空間的common類,但我當(dāng)前類沒有創(chuàng)建common類 $common = new $common_class_name();//發(fā)生致命錯(cuò)誤:common類不存在 //我想使用限定名稱調(diào)用blogarticlecommon $common_class_name = 'articlecommon';//實(shí)際會(huì)被當(dāng)作完全限定名稱,也就表示article空間下的common類,但我下面只定義了blogarticle空間而不是article空間
$common = new $common_class_name();//發(fā)生致命錯(cuò)誤:articlecommon類不存在
namespace blogarticle;class common { } ?> 總結(jié)
我對(duì)php的命名空間剛剛接觸,也不能隨便給一些沒有實(shí)踐的建議。我個(gè)人認(rèn)為命名空間的作用和功能都很強(qiáng)大,如果要寫插件或者通用庫的時(shí)候再也不用擔(dān)心重名問題。不過如果項(xiàng)目進(jìn)行到一定程度,要通過增加命名空間去解決重名問題,我覺得工作量不會(huì)比重構(gòu)名字少。也不得不承認(rèn)它的語法會(huì)對(duì)項(xiàng)目增加一定的復(fù)雜度,因此從項(xiàng)目一開始的時(shí)候就應(yīng)該很好的規(guī)劃它,并制定一個(gè)命名規(guī)范。
標(biāo)準(zhǔn)命名空間 命名空間的概念及作用篇二
進(jìn)行對(duì)象的序列化,的引用,ization命名空間。這樣就可以在文件中使用序列化所需要的各種特性了。
imports ization
如果對(duì)xml serialization缺少了解,請(qǐng)首先參考拙文:中實(shí)現(xiàn)對(duì)象序列化
2005-04-05
對(duì)象序列化
上面的例子包含了典型的xml中常見的各種元素:xml聲明、xml根節(jié)點(diǎn)、xml節(jié)點(diǎn)、xml屬性、xml集合。除xml聲明外,中都有對(duì)應(yīng)的特性用于定義這些元素。這些特性包括:xmlrootattribute、xmltypeattribute、xmlelementattribute、xmlattributeattribute、xmlarrayattribute和xmlarrayitemattribute。另外,還有兩個(gè)常用的特性,xmlignoreattribute用于標(biāo)記在對(duì)象序列化時(shí)需要被忽略的部分,xmlincludeattribute用于標(biāo)記在生成xml schema時(shí)需要包括的類型。如果沒有顯式地標(biāo)記任何特性,那么默認(rèn)類的特性為xmltypeattribute、類成員的特性為xmlelementattribute,且名稱為類或類成員的名稱。例如:
public class order
public id as string
public orderdate as string
end class
如果不做任何特性標(biāo)記,使用下面的代碼序列化時(shí): dim o as new order
with o
.id = 123456
.orderdate = tdatestring
end with
dim writer as new xmltextwriter(“”, 8)
dim serializer as new xmlserializer(gettype(order))
ting = ed ize(writer, o)
序列化后的xml為:
123456
2005-4-11
可以看到,對(duì)應(yīng)order類,而
和
分別對(duì)應(yīng)order類中的字段id和orderdate。另外,多了一個(gè)xml聲明和兩個(gè)xml命名空間。
自動(dòng)添加的,但是encoding是在xmltextwriter中指定的,如果不指定encoding,那么xml聲明只有。 1.1,這個(gè)版本中只支持xml 1.0版本。另外,如果不指定encoding,那么默認(rèn)的編碼可能也是utf8(沒找到相關(guān)的資料)。
.net默認(rèn)為order類添加了xmlschema和xmlschema-instance兩個(gè)w3c的命名空間。該命名空間也可以自己指定,方法是使用xmlserializer的另一個(gè)serialize方法。
dim ns as new xmlserializernamespaces (“", ”“)ting = ed ize(writer, o, ns)
要將類序列化為xml節(jié)點(diǎn):
_
public class order‘ any code class
要將類序列化為xml根節(jié)點(diǎn):
_
public class order‘ any code class
當(dāng)在類中同時(shí)使用xmlrootattribute、xmltypeattribute時(shí),序列化文檔中的類型以xmlrootattribute為準(zhǔn):
_
public class order‘ any code class
要將類成員序列化為xml節(jié)點(diǎn):
_
public id as string要將類成員序列化為xml屬性:
_
public id as string要將類成員序列化為xml集合:
_
public class order_
public id as stringpublic orderdate as string
_
public items as new arraylistend class
_
public class orderitempublic name as string
end class
使用特性的一個(gè)好處是:可以在代碼和序列化的文檔中使用不同的編碼規(guī)范。
標(biāo)準(zhǔn)命名空間 命名空間的概念及作用篇三
基本技能 12.5:命名空間
我們曾經(jīng)在第一章中對(duì)命名空間進(jìn)行簡單的介紹。這里我們將對(duì)命名空間進(jìn)行深入的討論。使用命名空間的目的是對(duì)標(biāo)識(shí)符的名稱進(jìn)行本地化,以避免命名沖突。在c++中,變量、函數(shù)和類都是大量存在的。如果沒有命名空間,這些變量、函數(shù)、類的名稱將都存在于全局命名空間中,會(huì)導(dǎo)致很多沖突。比如,如果我們在自己的程序中定義了一個(gè)函數(shù)toupper(),這將重寫標(biāo)準(zhǔn)庫中的toupper()函數(shù),這是因?yàn)檫@兩個(gè)函數(shù)都是位于全局命名空間中的。命名沖突還會(huì)發(fā)生在一個(gè)程序中使用兩個(gè)或者更多的第三方庫的情況中。此時(shí),很有可能,其中一個(gè)庫中的名稱和另外一個(gè)庫中的名稱是相同的,這樣就沖突了。這種情況會(huì)經(jīng)常發(fā)生在類的名稱上。比如,我們在自己的程序中定義了一個(gè)stack類,而我們程序中使用的某個(gè)庫中也可能定義了一個(gè)同名的類,此時(shí)名稱就沖突了。
namespace關(guān)鍵字的出現(xiàn)就是針對(duì)這種問題的。由于這種機(jī)制對(duì)于聲明于其中的名稱都進(jìn)行了本地化,就使得相同的名稱可以在不同的上下文中使用,而不會(huì)引起名稱的沖突。或許命名空間最大的受益者就是c++中的標(biāo)準(zhǔn)庫了。在命名空間出現(xiàn)之前,整個(gè)c++庫都是定義在全局命名空間中的(這當(dāng)然也是唯一的命名空間)。引入命名空間后,c++庫就被定義到自己的名稱空間中了,稱之為std。這樣就減少了名稱沖突的可能性。我們也可以在自己的程序中創(chuàng)建自己的命名空間,這樣可以對(duì)我們認(rèn)為可能導(dǎo)致沖突的名稱進(jìn)行本地化。這點(diǎn)在我們創(chuàng)建類或者是函數(shù)庫的時(shí)候是特別重要的。命名空間基礎(chǔ)
namespace關(guān)鍵字使得我們可以通過創(chuàng)建作用范圍來對(duì)全局命名空間進(jìn)行分隔。本質(zhì)上來講,一個(gè)命名空間就定義了一個(gè)范圍。定義命名空間的基本形式如下:
namespace 名稱{//聲明}
在命名空間中定義的任何東西都局限于該命名空間內(nèi)。
下面就是一個(gè)命名空間的例子,其中對(duì)一個(gè)實(shí)現(xiàn)簡單遞減計(jì)數(shù)器的類進(jìn)行了本地化。在該命名空間中定義了計(jì)數(shù)器類用來實(shí)現(xiàn)計(jì)數(shù);其中的upperbound和lowerbound用來表示計(jì)數(shù)器的上界和下界。//演示命名空間
namespace counternamespace {
int upperbound;
int lowerbound;
class counter {
int count;
public:
counter(int n){
if(n <= upperbound){
count = n;}
else {
count = upperbound;} }
void reset(int n){
if(n < upperbound){
count = n;} }
int run(){
if(count > lowerbound){
return count--;}
else
{
return lowerbound;
}
} };}
其中的upperbound,lowerbound和類counter都是有命名空間counternamespace定義范圍的組成部分。
在命名空間中聲明的標(biāo)識(shí)符是可以被直接引用的,不需要任何的命名空間的修飾符。例如,在counternamesapce命名空間中,run()函數(shù)中就可以直接在語句中引用lowerbound:
if(count > lowerbound){
return count--;}
然而,既然命名空間定義了一個(gè)范圍,那么我們在命名空間之外就需要使用范圍解析運(yùn)算符來引用命名空間中的對(duì)象。例如,在命名空間counternamespace定義的范圍之外給upperbound賦值為10,就必須這樣寫:
counternamespace::upperbound = 10;或者在counternamespace定義的范圍之外想要聲明一個(gè)counter類的對(duì)象就必須這樣寫:
counternamespace::counter obj;
一般來講,在命名空間之外想要訪問命名空間內(nèi)部的成員需要在成員前面加上命名空間和范圍解析運(yùn)算符。
下面的程序演示了如何使用counternamespace這個(gè)命名空間: //演示命名空間
#include
using namespace std;
namespace counternamespace {int upperbound;
int lowerbound;
class counter {
int count;
public:
counter(int n){
if(n <= upperbound){
count = n;}
else {
count = upperbound;} }
void reset(int n){
if(n < upperbound){
count = n;} }
int run(){
if(count > lowerbound){
return count--;} else
return lowerbound;} };}
int main(){
counternamespace::upperbound = 100;
counternamespace::lowerbound = 0;
counternamespace::counter ob1(10);
int i;
do {
i = ();
cout << i << “ ”;
} while(i > counternamespace::lowerbound);
cout << endl;
counternamespace::counter ob2(20);
do {
i = ();
cout << i << “ ”;
} while(i > counternamespace::lowerbound);
cout << endl;
(100);
do {
i = ();
cout << i << “ ”;
} while(i > counternamespace::lowerbound);
cout << endl;
return 0;}
請(qǐng)注意:counter類以及upperbound和lowerbound的引用都是在前面加上了counternamespace修飾符。但是,一旦聲明了counter類型的對(duì)象,就沒有必須在對(duì)該對(duì)象的任何成員使用這種修飾符了。()是可以被直接調(diào)用的。其中的命名空間是可以被解析的。
相同的空間名稱是可以被多次聲明的,這種聲明向相互補(bǔ)充的。這就使得命名空間可以被分割到幾個(gè)文件中甚至是同一個(gè)文件的不同地方中。例如:
namespace ns {
int i;}
//...namespace ns {
int j;}
其中命名空間ns被分割成兩部分,但是兩部分的內(nèi)容卻是位于同一命名空間中的。也就是ns。最后一點(diǎn):命名空間是可以嵌套的。也就是說可以在一個(gè)命名空間內(nèi)部聲明另外的命名空間。using關(guān)鍵字
如果在程序中需要多次引用某個(gè)命名空間的成員,那么按照之前的說法,我們每次都要使用范圍解析符來指定該命名空間,這是一件很麻煩的事情。為了解決這個(gè)問題,人們引入了using關(guān)鍵字。using語句通常有兩種使用方式:
using namespace 命名空間名稱;using 命名空間名稱::成員;
第一種形式中的命名空間名稱就是我們要訪問的命名空間。該命名空間中的所有成員都會(huì)被引入到當(dāng)前范圍中。也就是說,他們都變成當(dāng)前命名空間的一部分了,使用的時(shí)候不再需要使用范圍限定符了。第二種形式只是讓指定的命名空間中的指定成員在當(dāng)前范圍中變?yōu)榭梢姟N覀冇们懊娴腸ounternamespace來舉例,下面的using語句和賦值語句都是有效的:
using counternamespace::lowerbound;//只有l(wèi)owerbound當(dāng)前是可見的 lowerbound = 10;//這樣寫是合法的,因?yàn)閘owerbound成員當(dāng)前是可見的 using counternamespace;//所有counternamespace空間的成員當(dāng)前都是可見的
upperbound = 100;//這樣寫是合法的,因?yàn)樗械腸ounternamespace成員目前都是可見的
下面是我們對(duì)之前的程序進(jìn)行修改的結(jié)果: //使用using
#include
using namespace std;namespace counternamespace { int upperbound;
int lowerbound;
class counter {
int count;
public:
counter(int n){
if(n < upperbound){
count = n;}
else {
count = upperbound;} }
void reset(int n){
if(n <= upperbound){
count = n;} }
int run(){
if(count > lowerbound){
return count--;}
else {
return lowerbound;} } };}
int main(){
//這里只是用counternamespace中的upperbound using counternamespace::upperbound;
//此時(shí)對(duì)upperbound的訪問就不需要使用范圍限定符了 upperbound = 100;
//但是使用lowerbound的時(shí)候,還是需要使用范圍限定符的 counternamespace::lowerbound = 0;counternamespace::counter ob1(10);
int i;
do {
i = ();cout << i << “ ”;
}while(i > counternamespace::lowerbound);cout << endl;
//下面我們將使用整個(gè)counternamespace的命名空間
using namespace counternamespace;counter ob2(20);
do {
i = ();cout << i << “ ”;
}while(i > counternamespace::lowerbound);cout << endl;
(100);lowerbound = 90;
do {
i = ();cout << i << “ ”;}while(i > lowerbound);
return 0;}
上面的程序還為我們演示了重要的一點(diǎn):當(dāng)我們用using引入一個(gè)命名空間的時(shí)候,如果之前有引用過別的命名空間(或者同一個(gè)命名空間),則不會(huì)覆蓋掉對(duì)之前的引入,而是對(duì)之前引入內(nèi)容的補(bǔ)充。也就是說,到最后,上述程序中的std和counternamespace這兩個(gè)命名空間都變成全局空間了。沒有名稱的命名空間
有一種特殊的命名空間,叫做未命名的命名空間。這種沒有名稱的命名空間使得我們可以創(chuàng)建在一個(gè)文件范圍里可用的命名空間。其一般形式如下: namespace {
//聲明 }
我們可以使用這種沒有名稱的命名空間創(chuàng)建只有在聲明他的文件中才可見的標(biāo)識(shí)符。也即是說,只有在聲明這個(gè)命名空間的文件中,它的成員才是可見的,它的成員才是可以被直接使用的,不需要命名空間名稱來修飾。對(duì)于其他文件,該命名空間是不可見的。我們在前面曾經(jīng)提到過,把全局名稱的作用域限制在聲明他的文件的一種方式就是把它聲明為靜態(tài)的。盡管c++是支持靜態(tài)全局聲明的,但是更好的方式就是使用這里的未命名的命名空間。std命名空間
標(biāo)準(zhǔn)c++把自己的整個(gè)庫定義在std命名空間中。這就是本書的大部分程序都有下面代碼的原因:
using namespace std;
這樣寫是為了把std命名空間的成員都引入到當(dāng)前的命名空間中,以便我們可以直接使用其中的函數(shù)和類,而不用每次都寫上std::。
當(dāng)然,我們是可以顯示地在每次使用其中成員的時(shí)候都指定std::,只要我們喜歡。例如,我們可以顯示地采用如下語句指定cout:
std::cout << “顯示使用std::來指定cout”;
如果我們的程序中只是少量地使用了std命名空間中的成員,或者是引入std命名空間可能導(dǎo)致命名空間的沖突的話,我們就沒有必要使用using namespace std;了。然而,如果在程序中我們要多次使用std命名空間的成員,則采用using namespace std;的方式把std命名空間的成員都引入到當(dāng)前命名空間中會(huì)顯得方便很多,而不用每次都單獨(dú)在使用的時(shí)候顯示指定。
標(biāo)準(zhǔn)命名空間 命名空間的概念及作用篇四
c++命名空間namespace 雖然使用命名空間的方法,有多種可供選擇。但是不能貪圖方便,一味使用using 指令,這樣就完全背離了設(shè)計(jì)命名空間的初衷,也失去了命名空間應(yīng)該具有的防止名稱沖突的功能。
一般情況下,對(duì)偶爾使用的命名空間成員,應(yīng)該使用命名空間的作用域解析運(yùn)算符來直接給名稱定位。而對(duì)一個(gè)大命名空間中的經(jīng)常要使用的少數(shù)幾個(gè)成員,提倡使用using聲明,而不應(yīng)該使用using編譯指令。只有需要反復(fù)使用同一個(gè)命名空間的許多數(shù)成員時(shí),使用using編譯指令,才被認(rèn)為是可取的。
例如,如果一個(gè)程序()只使用一兩次cout,而且也不使用std命名空間中的其他成員,則可以使用命名空間的作用域解析運(yùn)算符來直接定位。如: #include
……
std::cout << “hello, world!” << std::endl;std::cout << “outer::i = ” << outer::i << “, inner::i = ” << outer::inner::i << std::endl;又例如,如果一個(gè)程序要反復(fù)使用std命名空間中的cin、cout和cerr(),而不怎么使用其他std命名空間中的其他成員,則應(yīng)該使用using 聲明而不是using指令。如:
#include
……
using std::cout;cout << “hello, world!” << endl;cout << “outer::i = ” << outer::i << “, inner::i = ” << outer::inner::i << endl;4)命名空間的名稱l
命名空間別名 標(biāo)準(zhǔn)c++引入命名空間,主要是為了避免成員的名稱沖突。若果用戶都給自己的命名空間取簡短的名稱,那么這些(往往同是全局級(jí)的)命名空間本身,也可能發(fā)生名稱沖突。如果為了避免沖突,而為命名空間取很長的名稱,則使用起來就會(huì)不方便。這是一個(gè)典型的兩難問題。
標(biāo)準(zhǔn)c++為此提供了一種解決方案——命名空間別名,格式為: namespace 別名 = 命名空間名;例如:(at&t美國電話電報(bào)公司)
namespace american_telephone_and_telegraph { // 命名空間名太長
class string {
string(const char*);
// ……
} }
american_telephone_and_telegraph::string s1 // 使用不方便
= new american_telephone_and_telegraph::string(“grieg”);
namespace att = american_telephone_and_telegraph;// 定義別名
att::string s2 = new att::string(“bush”);// 使用方便 att::string s3 = new att::string(“nielsen”);
l
無名命名空間 標(biāo)準(zhǔn)c++引入命名空間,除了可以避免成員的名稱發(fā)生沖突之外,還可以使代碼保持局部性,從而保護(hù)代碼不被他人非法使用。如果你的目的主要是后者,而且又為替命名空間取一個(gè)好聽、有意義、且與別人的命名空間不重名的名稱而煩惱的話,標(biāo)準(zhǔn)c++還允許你定義一個(gè)無名命名空間。你可以在當(dāng)前編譯單元中(無名命名空間之外),直接使用無名命名空間中的成員名稱,但是在當(dāng)前編譯單元之外,它又是不可見的。無名命名空間的定義格式為: namespace {
聲明序列可選 } 實(shí)際上,上面的定義等價(jià)于:(標(biāo)準(zhǔn)c++中有一個(gè)隱含的使用指令)
namespace $$$ {
聲明序列可選 } using namespace $$$;例如: namespace {
int i;
void f(){/*……*/} } int main(){
i = 0;// 可直接使用無名命名空間中的成員i
f();// 可直接使用無名命名空間中的成員f()}
標(biāo)準(zhǔn)命名空間 命名空間的概念及作用篇五
本講基本要求
* 掌握:命名空間的作用及定義;如何使用命名空間。
* 了解:使用早期的函數(shù)庫
重點(diǎn)、難點(diǎn)
◆命名空間的作用及定義;如何使用命名空間。
在學(xué)習(xí)本書前面各章時(shí),讀者已經(jīng)多次看到在程序中用了以下語句: using namespace std;
這就是使用了命名空間std。在本講中將對(duì)它作較詳細(xì)的介紹。
一、為什么需要命名空間(問題提出)
命名空間是ansic++引入的可以由用戶命名的作用域,用來處理程序中常見的同名沖突。
在c語言中定義了3個(gè)層次的作用域,即文件(編譯單元)、函數(shù)和復(fù)合語句。c++又引入了類作用域,類是出現(xiàn)在文件內(nèi)的。在不同的作用域中可以定義相同名字的變量,互不于擾,系統(tǒng)能夠區(qū)別它們。
1、全局變量的作用域是整個(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 int a=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中有以下聲明: extem int a;
表示文件b中的變量a是在其他文件中已定義的變量。由于有此聲明,在程序編譯和連接后,文件a的變量a的作用域擴(kuò)展到了文件b。如果在文件b中不再對(duì)a賦值,則在文件b中用以下語句輸出的是文件a中變量a的值: cout<
2、程序中就會(huì)出現(xiàn)名字沖突。
在簡單的程序設(shè)計(jì)中,只要人們小心注意,可以爭取不發(fā)生錯(cuò)誤。但是,一個(gè)大型的應(yīng)用軟件,往往不是由一個(gè)人獨(dú)立完成的,而是由若干人合作完成的,不同的人分別完成不同的部分,最后組合成一個(gè)完整的程序。假如不同的人分別定義了類,放在不同的頭文件中,在主文件(包含主函數(shù)的文件)需要用這些類時(shí),就用#include命令行將這些頭文件包含進(jìn)來。由于各頭文件是由不同的人設(shè)計(jì)的,有可能在不同的頭文件中用了相同的名字來命名所定義的類或函數(shù)。例4 名字沖突
程序員甲在頭文件headerl.h中定義了類student和函數(shù)fun。//例4中的頭文件header1(頭文件1,沒其文件名為cc8-4-h1.h)#include
#include
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;};void student::get_data()//成員函數(shù)定義 { cout<wang 18 2.82843 如果程序員乙寫了頭文件header2.h,在其中除了定義其他類以外,還定義了類student和函數(shù)fun,但其內(nèi)容與頭文件headerl.h中的student和函數(shù)fun有所不同。//例4中的頭文件header2 #include
#include
using namespace std;class student //聲明student類 { public: student(int n,string nam,char s)//參數(shù)與headerl中的student不同
{ num=n;name=nam;sex=s;} void get_data();private: int num;string name;char sex;};//此項(xiàng)與headerl不同void student::get_data()//成員函數(shù)定義 { cout<
double fun(double a,double b)//定義全局函數(shù)
{ return sqrt(a-b);} //返回值與headerl中的fun函數(shù)不同 //頭文件2中可能還有其他內(nèi)容
假如主程序員在其程序中要用到headerl.h中的student和函數(shù)fun,因而在程序中包含了頭文件headerl.h,同時(shí)要用到頭文件header2.h中的一些內(nèi)容(但對(duì)header2.h中包含與headerl.h中的student類和fun函數(shù)同名而內(nèi)容不同的類和函數(shù)并不知情,因?yàn)樵谝粋€(gè)頭文件中往往包含許多不同的信息,而使用者往往只關(guān)心自己所需要的部分,而不注意其他內(nèi)容),因而在程序中又包含了頭文件header2.h。如果主文件(包含主函數(shù)的文件)如下: #include
using namespace std;#include ”header1.h“//包含頭文件l #include ”header2.h“//包含頭文件2 int main(){ student stud1(101,”wang“,18);_data();cout<
3、全局命名空間污染(global namespace pollution)。
在程序中還往往需要引用一些庫(包括c++編譯系統(tǒng)提供的庫、由軟件開發(fā)商提供的庫或者用戶自己開發(fā)的庫),為此需要包含有關(guān)的頭文件。如果在這些庫中包含有與程序的全局實(shí)體同名的實(shí)體,或者不同的庫中有相同的實(shí)體名,則在編譯時(shí)就會(huì)出現(xiàn)名字沖突。
為了避免這類問題的出現(xiàn),人們提出了許多方法,例如:將實(shí)體的名字寫得長—些(包含十幾個(gè)或幾十個(gè)字母和字符);把名字起得特殊一些,包括一些特殊的字符;由編譯系統(tǒng)提供的內(nèi)部全局標(biāo)識(shí)符都用下劃線作為前綴,如_complex(),以避免與用戶命名的實(shí)體同名;由軟件開發(fā)商提供的實(shí)體的名字用特定的字符作為前綴。但是這樣的效果并不理想,而且增加了閱讀程序的難度,可讀性降低了。c語言和早期的c++語言沒有提供有效的機(jī)制來解決這個(gè)問題,沒有使庫的提供者能夠建立自己的命名空間的工具。人們希望ansi c++標(biāo)準(zhǔn)能夠解決這個(gè)問題,提供—種機(jī)制、一種工具,使由庫的設(shè)計(jì)者命名的全局標(biāo)識(shí)符能夠和程序的全局實(shí)體名以及其他庫的全局標(biāo)識(shí)符區(qū)別開來。
二、什么是命名空間(解決方案)
命名空間:實(shí)際上就是一個(gè)由程序設(shè)計(jì)者命名的內(nèi)存區(qū)域,程序設(shè)計(jì)者可以根據(jù)需要指定一些有名字的空間域,把一些全局實(shí)體分別放在各個(gè)命名空間中,從而與其他全局實(shí)體分隔開來。
如: namespace ns1 //指定命名中間nsl
{ int a;
double b;} namespace是定義命名空間所必須寫的關(guān)鍵字,nsl是用戶自己指定的命名空間的名字(可以用任意的合法標(biāo)識(shí)符,這里用ns1是因?yàn)閚s是namespace的縮寫,含義請(qǐng)楚),在花括號(hào)內(nèi)是聲明塊,在其中聲明的實(shí)體稱為命名空間成員(namespace member)?,F(xiàn)在命名空間成員包括變量a和b,注意a和b仍然是全局變量,僅僅是把它們隱藏在指定的命名空間中而已。如果在程序中要使用變量a和b,必須加上命名空間名和作用域分辨符“::”,如nsl::a,nsl::b。這種用法稱為命名空間限定(qualified),這些名字(如nsl::a)稱為被限定名(qualified name)。c++中命名空間的作用類似于操作系統(tǒng)中的目錄和文件的關(guān)系,由于文件很多,不便管理,而且容易重名,于是人們設(shè)立若干子目錄,把文件分別放到不同的子目錄中,不同子目錄中的文件可以同名。調(diào)用文件時(shí)應(yīng)指出文件路徑。
命名空間的作用:是建立一些互相分隔的作用域,把一些全局實(shí)體分隔開來。以免產(chǎn)生老點(diǎn)名叫李相國時(shí),3個(gè)人都站起來應(yīng)答,這就是名字沖突,因?yàn)樗麄儫o法辨別老師想叫的是哪一個(gè)李相國,同名者無法互相區(qū)分。為了避免同名混淆,學(xué)校把3個(gè)同名的學(xué)生分在3個(gè)班。這樣,在小班點(diǎn)名叫李相國時(shí),只會(huì)有一個(gè)人應(yīng)答。也就是說,在該班的范圍(即班作用域)內(nèi)名字是惟一的。如果在全校集合時(shí)校長點(diǎn)名,需要在全校范圍內(nèi)找這個(gè)學(xué)生,就需要考慮作用域問題。如果校長叫李相國,全校學(xué)生中又會(huì)有3人一齊喊“到”,因?yàn)樵谕蛔饔糜蛑写嬖?個(gè)同名學(xué)生。為了在全校范圍內(nèi)區(qū)分這3名學(xué)生,校長必須在名字前加上班號(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; //常量 doublepay;
//變量
doubletax()
//函數(shù)
{return a*rate;} namespacens2
//嵌套的命名空間
{int age;} }
如果想輸出命名空間nsl中成員的數(shù)據(jù),可以采用下面的方法: cout<
cout<
可以看到命名空間的聲明方法和使用方法與類差不多。但它們之間有一點(diǎn)差別:在聲明類時(shí)在右花括號(hào)的后面有一分號(hào),而在定義命名空間時(shí),花括號(hào)的后面沒有分號(hào)。
三、使用命名空間解決名字沖突(使用指南)有了以上的基礎(chǔ)后,就可以利用命名空間來解決名字沖突問題?,F(xiàn)在,對(duì)例4程序進(jìn)行修改,使之能正確運(yùn)行。
例5 利用命名空間來解決例4程序名字沖突問題。
修改兩個(gè)頭文件,把在頭文件中聲明的類分別放在兩個(gè)不同的命名空間中。//例8.5中的頭文件1,文件名為header1.h using namespace std;#include
#include
namespace ns1 //聲明命名空間ns1 { class student //在命名空間nsl內(nèi)聲明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;};void student::get_data()//定義成員函數(shù){ cout<
double fun(double a,double b)//在命名空間n引內(nèi)定義fun函數(shù) { return sqrt(a+b);} } //例8.5中的頭文件2,文件名為header2.h #include
#include
namespace ns2 //聲明命名空間ns2 { class student { public: student(int n,string nam,char s){ num=n;name=nam;sex=s;} void get_data();private: int num;string name;char sex;};
void student::get_data(){ cout<double fun(double a,double b){ return sqrt(a-b);} } //main file #include
#include ”header1.h“ //包含頭文件l #include ”header2.h“ //包含頭文件2 int main(){ ns1::student stud1(101,”wang“,18);//用命名空間nsl中聲明的student類定義studt _data();//不要寫成ns1::_data();
cout<ns2::student stud2(102,”li“,'f');//用命名空間ns2中聲明的student類定義stud2 _data();cout<
分析例4程序出錯(cuò)的原因是:在兩個(gè)頭文件中有相同的類名student和相同的函數(shù)名fun,在把它們包含在主文件中時(shí),就產(chǎn)生名字沖突,存在重復(fù)定義。編譯系統(tǒng)無法辨別用哪一個(gè)頭文件中的student來定義對(duì)象studl?,F(xiàn)在兩個(gè)student和fun分別放在不同的命名空間中,各自有其作用域,互不相干。由于作用域不相同,不會(huì)產(chǎn):生名字沖突。正如同在兩個(gè)不同的類中可以有同名的變量和函數(shù)而不會(huì)產(chǎn)生沖突一樣。
在定義對(duì)象時(shí)用ns1::student(命名空間nsl中的student)來定義studl,用ns2::student(命名空間ns2中的student)來定義stud2。顯然,nsl::student和ns2::student是兩個(gè)不同的類,不會(huì)產(chǎn)生混淆。同樣,在調(diào)用fun函數(shù)時(shí)也需要用命名空間名ns]或ns2加以限定。ns1::fun()和ns2::fun()是兩個(gè)不同的函數(shù)。注意:對(duì)象studl是用nsl::student定義的,但對(duì)象studl并不在命名空間nsl中。studl的作用域?yàn)閙ain函數(shù)范圍內(nèi)。在調(diào)用對(duì)象studl的成員函數(shù)get_data時(shí),應(yīng)寫成studl.get_data(),而不應(yīng)寫成nsl::_data()。程序能順利通過編譯,并得到以下運(yùn)行結(jié)果: 101 wang l9(對(duì)象studl中的數(shù)據(jù))2.82843(/5+3的值)102 li f(對(duì)象studg中的數(shù)據(jù))1.41421(/5-2的值)
四、使用命名空間成員的方法 從上面的介紹可以知道,在引用命名空間成員時(shí),要用命名空間名和作用域分辨符對(duì)命名空間成員進(jìn)行限定,以區(qū)別不同的命名空間中的同名標(biāo)識(shí)符。即: 命名空間名::命名空間成員名
這種方法是有效的,能保證所引用的實(shí)體有惟一的名字。但是如果命名空間名字比較長,尤其在有命名空間嵌套的情況下,為引用一個(gè)實(shí)體,需要寫很長的名字。在一個(gè)程序中可能要多次引用命名空間成員,就會(huì)感到很不方便。1、使用命名空間別名
可以為命名空間起一個(gè)別名(namespace alias),用來代替較長的命名空間名。如 namespace television //聲明命名空間,名為television {...} 可以用一個(gè)較短而易記的別名代替它。如:
namespace tv=television; //別名tv與原名television等價(jià)
也可以說,別名tv指向原名television,在原來出現(xiàn)television的位置都可以無條件地用tv來代替。
2、使用using命名空間成員名
using后面的命名空間成員名必須是由命名空間限定的名字。例如: using nsl::student; 以上語句聲明:在本作用域(using語句所在的作用域)中會(huì)用到命名空間ns1中的成員student,在本作用域中如果使用該命名空間成員時(shí),不必再用命名空間限定。例如在用上面的using聲明后,在其后程序中出現(xiàn)的student就是隱含地指nsl::student。
using聲明的有效范圍是從using語句開始到using所在的作用域結(jié)束。如果在以上的using語句之后有以下語句:
student studl(101,”wang“,18); //此處的student相當(dāng)于ns1::student 上面的語句相當(dāng)于
nsl::student studl(101,”wang“,18); 又如
using nsl::fun; //聲明其后出現(xiàn)的fun是屬于命名空間nsl中的fun cout<
但是要注意:在同一作用域中用using聲明的不同命名空間的成員中不能有同名的成員。例如:
usmgnsl::student; //聲明其后出現(xiàn)的student是命名空間nsl中的student usmgns2::student; //聲明其后出現(xiàn)的student是命名空間ns2小的student student stud1; //請(qǐng)問此處的student是哪個(gè)命名中間中的student? 產(chǎn)生了二義性,編譯出錯(cuò)。
3、使用using namespace命名空間名
用上面介紹的using命名空間成員名,一次只能聲明一個(gè)命名空間成員,如果在一個(gè)命名空間中定義了10個(gè)實(shí)體,就需要使用10次using命名空間成員名。能否在程序中用一個(gè)語句就能一次聲明一個(gè)命名空間中的全部成員呢? c++提供了using namespace語句來實(shí)現(xiàn)這一目的。using namespace語句的一般格式為 using namespace 命名空間名; 例如
using nanlespace nsl;
聲明了在本作用域中要用到命名空間nsl中的成員,在使用該命名空間的任何成員時(shí)都不必用命名空間限定。如果在作了上面的聲明后有以下語句: student studl(101,”wang”,18); //student隱含指命名中間nsl中的student cout<
cout<
student stud2(102,“l(fā)i”,'r'); _data();
coutt<
五、無名的命名空間
以上介紹的是有名字的命名空間,c++還允許使用沒有名字的命名空間,如在文件a中聲明了以下的無名命名空間:
namespace //命名空間沒有名字 { void fun()//定義命名空間成員 { cout<<“ok.”<
則執(zhí)行無名命名空間中的成員fun函數(shù),輸出”ok.”。
在本程序中的其他文件中也無法使用該fun函數(shù),也就是把fun函數(shù)的作用域限制在本文件范圍中??梢月?lián)想到:在c浯言中可以用static聲明一個(gè)函數(shù),其作用也是使該函數(shù)的作用域限于本文件。c++保留了用static聲明函數(shù)的用法,同時(shí)提供了用無名命名空間來實(shí)現(xiàn)這一功能。隨著越來越多的c++編譯系統(tǒng)實(shí)現(xiàn)了ansi c++建議的命名空間的機(jī)制,相信使用無名命名空間成員的方法將會(huì)取代以前習(xí)慣用的對(duì)全局變量的靜態(tài)聲明。
六、標(biāo)準(zhǔn)命名空間std 為了解決c++標(biāo)準(zhǔn)庫中的標(biāo)識(shí)符與程序中的全局標(biāo)識(shí)符之間以及不同庫中的標(biāo)識(shí)符之間的同名沖突,應(yīng)該將不同庫的標(biāo)識(shí)符在不同的命名空間中定義(或聲明)。標(biāo)準(zhǔn)c++庫的所有的標(biāo)識(shí)符都是在一個(gè)名為std的命名空間中定義的,或者說標(biāo)準(zhǔn)頭文件(如iostream)中函數(shù)、類、對(duì)象和類模板是在命名空間std中定義的。std是standard(標(biāo)準(zhǔn))的縮寫,表示這是存放標(biāo)準(zhǔn)庫的有關(guān)內(nèi)容的命名空間,含義請(qǐng)楚,不必死記。
這樣,在程序中用到c++標(biāo)準(zhǔn)庫時(shí),需要使用std作為限定。如
std::cout<<“ok.”<
這樣,在std中定義和聲明的所有標(biāo)識(shí)符在本文件中都可以作為全局量來使用。但是應(yīng)當(dāng)絕對(duì)保證在程序中不出現(xiàn)與命名空間std的成員同名的標(biāo)識(shí)符,例如在程序中不能再定義一個(gè)名為cout的對(duì)象。由于在命名空間std中定義的實(shí)體實(shí)在太多,有時(shí)程序設(shè)計(jì)人員也弄不請(qǐng)哪些標(biāo)識(shí)符已在命名空間std中定義過,為減少出錯(cuò)機(jī)會(huì),有的專業(yè)人員喜歡用若干個(gè)"using命名空間成員”聲明來代替“using namespace命名空間”聲明,如 using std::string; using std::cout; using std::cin;
等。為了減少在每一個(gè)程序中都要重復(fù)書寫以亡的using聲明,程序開發(fā)者往往把編寫應(yīng)用程序時(shí)經(jīng)常會(huì)用到的命名空間std成員的usmg聲明組成一個(gè)頭文件,然后在程序中包含此頭文件即可。
如果閱讀了多種介紹c++的書,可能會(huì)發(fā)現(xiàn)有的書的程序中有using namespace語句,有的則沒有。有的讀者會(huì)提出:究竟應(yīng)該有還是應(yīng)該沒有?應(yīng)當(dāng)說:用標(biāo)準(zhǔn)的c++編程,是應(yīng)該對(duì)命名空間std的成員進(jìn)行聲明或限定的(可以采取前面介紹過的任一種方法)。但是目前所用的c++庫大多是幾年前開發(fā)的,當(dāng)時(shí)并沒有命名空間,庫中的有關(guān)內(nèi)容也沒有放在std命名空間中,因而在程序中不必對(duì)std進(jìn)行聲明。
七、使用早期的函數(shù)庫
c語言程序中各種功能基本上都是由函數(shù)來實(shí)現(xiàn)的,在c語言的發(fā)展過程中建立了功能豐富的函數(shù)庫,c++從c語言繼承了這份寶貴的財(cái)富。在c++程序中可以使用c語言的函數(shù)庫。如果要用函數(shù)庫中的函數(shù),就必須在程序文件中包含有關(guān)的頭文件,在不同的頭文件中,包含了不同的函數(shù)的聲明。
在c++中使用這些頭文件有兩種方法。
1、用c語言的傳統(tǒng)方法
頭文件名包括后綴.h,如stdio.h,math.h等。由于c語言沒有命名空間,頭文件并不存放在命名空間中,因此在c++程序文件中如果用到帶后綴.h的頭文件時(shí),不必用命名空間。只需在文件中包含所用的頭文件即可。如 #include
2、用c++的新方法c++標(biāo)準(zhǔn)要求系統(tǒng)提供的頭文件不包括后綴.h,例如iostream、string。為了表示與c語言的頭文件有聯(lián)系又有區(qū)別,c++所用的頭文件名是在c語言的相應(yīng)的頭文件名(但不包括后綴.h)之前加一字母c。例如,c語言中有關(guān)輸入與輸出的頭文件名為stdio.h在c++中相應(yīng)的頭文件名為cstdio。c語言中的頭文件math.h,在c++中相應(yīng)的頭文什名為cmath。c語言中的頭文件string.h在c++中相應(yīng)的頭文件名為cstring。注意在c++中,頭文件cstnng和頭文件strmg不是同一個(gè)文件。前者提供c語言中對(duì)字符串處理的有關(guān)函數(shù)(如strcmp,ctrcpy)的聲明,后者提供c++中對(duì)字符串處理的新功能。此外,由于這些函數(shù)都是在命名空間std中聲明的,因此在程序中要對(duì)命名空間std作聲明。如:
#include
#include
using namespace std;
目前所用的大多數(shù)c++編譯系統(tǒng)既保留了c的用法,又提供丁c++的新方法。下面兩種用法等價(jià),可以任選。c傳統(tǒng)方法 c++新方法#include
#include
#include
#include
#include
#include
using namespace std;