




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、實驗05 數據的共享與保護(2學時)(第5章 數據的共享與保護)一、實驗目的(1) 觀察程序運行中變量的作用域、生存期和可見性。(2) 學習類的靜態成員的使用。(3) 學習多文件結構在C+程序中的使用。二、實驗任務5_1 運行下面的程序,觀察變量x、y的值。/lab5_1.cpp#include <iostream>using namespace std;void fn1();int x=1,y=2;int main()cout<<"開始."<<endl;cout<<"x="<<x<<
2、;endl;cout<<"y="<<y<<endl;cout<<"在main()中求x和y的值."<<endl;int x=10,y=20;cout<<"x="<<x<<endl;cout<<"y="<<y<<endl; cout<<"進入函數fn1()."<<endl;fn1();cout<<"返回main()&quo
3、t;<<endl;cout<<"x="<<x<<endl;cout<<"y="<<y<<endl; return 0;void fn1()int y=200;cout<<"x="<<x<<endl;cout<<"y="<<y<<endl;5_2 實現客戶機(CLIENT)類。聲明字符型靜態數據成員ServerName,保存其服務器名稱;聲明整型靜態數據成員Cli
4、entNum,記錄已定義的客戶數量;定義靜態函數ChangeServerName()改變服務器名稱。在頭文件client.h中聲明類,在文件client.cpp中實現,在文件lab5_2.cpp中測試這個類,觀察相應的成員變量取值的變化情況。三、實驗步驟1.(驗證)運行lab5_1.cpp程序,觀察程序輸出。全局變量的作用域為文件作用域,在整個程序運行期間有效,但如果在局部模塊中聲明了同名的變量,則在局部模塊中,可見的是局部變量,此時,全局變量不可見;而局部變量的生存期只限于相應的程序模塊中,離開相應的程序模塊,局部變量x、y就不再存在,此時同名的全局變量重新可見。程序名:lab5_1.cpp
5、。 程序的運行結果:2.(編程)實現客戶機(CLIENT)類。新建一個空的項目lab5_2,添加頭文件client.h,在其中聲明類CLIENT,注意使用編譯預處理命令;再添加源程序文件client.cpp,在其中實現CLIENT類,注意靜態成員變量的使用方法;再添加文件lab5_2.cpp,在其中定義main()函數,測試CLIENT類,觀察 相應的成員變量取值的變化情況。提示:訪問一臺服務器的客戶總數。靜態成員為類的屬性,為所有的類的對象共同擁有。再定義兩個靜態成員函數,分別顯示服務器名和客戶總數。構造函數用于增加一個客戶,析構函數用于減少一個客戶。定義一個對象,再定義第二個對象,然后減少
6、一個對象。參考程序輸出結果: 程序及運行結果:(1) 類聲明頭文件client.h/client.h#ifndef CLIENT_H#define CLIENT_H/其中的靜態成員為類的屬性,為所有的類的對象共同擁有class clientpublic:client();client();static void ChangeServerName(char ss);/改變服務器名稱static void showServerName();static void showClientNum();private:static char ServerName;/保存服務器名,引用性說明static i
7、nt ClientNum;/記錄已定義的客戶(即對象)數量,引用性說明;#endif(2) 類實現程序文件client.cpp/client.cpp#include <iostream>#include "client.h"using namespace std;client:client() ClientNum+;/增加一個對象(客戶)client:client() ClientNum-; /減少一個對象(客戶)void client:ChangeServerName(char sn) ServerName=sn; /無staticvoid client:sh
8、owServerName() cout<<"服務器名:"<<ServerName<<endl; void client:showClientNum() cout<<"客戶總數:"<< ClientNum <<endl; /必須在文件作用域的某處用類名限定進行定義性說明,這時也可以進行初始化。char client:ServerName='A' /無staticint client:ClientNum=0;(3) 主函數文件lab5_2.cpp/lab5_2.cpp#i
9、nclude <iostream>#include "client.h"using namespace std;void main()client:showServerName();/初始狀態client:showClientNum();/類名引用靜態成員函數client:ChangeServerName('B');client a;/增加一個客戶a. showServerName();/對象名引用靜態成員函數a. showClientNum();client b; /增加一個客戶b. showServerName();b. showClient
10、Num();/減少一個客戶client:showServerName();client:showClientNum();(4) 運行結果附:第5章 數據的共享與保護5.1 標識符的作用域與可見性P1465.1.1 作用域作用域是一個標識符在程序正文中有效的區域。C+的作用域有:函數原型作用域、塊作用域(局部作用域)、類作用域、文件作用域。1. 函數原型作用域在函數原型聲明時形式參數的作用范圍。例, double Area(double radius);其中標識符radius的作用(或稱有效)范圍在形參列表的左、右括號之間,稱標識符radius的作用域是函數原型作用域。由于在函數原型的形參表中起
11、作用的只是形參類型,標識符并不起作用,可省略。2. 局部作用域(塊作用域)例:void fun(int a)int b=a;cin>>b;if(b>0)int c;.a的作用域c的作用域b的作用域形參作用域:從形參列表中的聲明處開始,到整個函數體結束處止。b和c都具有塊作用域,是不同的塊作用域。塊是一對大括號括起來的一段程序。此例,函數體是一個塊,if語句后的分支體又是一個較小的塊,二者是包含關系。在塊中聲明的標識符,其作用域從聲明處開始,一直到塊結束的大括號為止。具有塊作用域的變量也稱為局部變量。3. 類作用域類是一組有名成員的集合,類X的成員m具有類作用域,對m的訪問方式
12、如下:(1) 若在X的成員函數中無同名的局部作用域標識符,則在該函數內可訪問成員m。(2) 通過表達式x.m或X:m。這正是程序中訪問對象成員的最基本方法。(3) 通過prt->m這樣的表達式,其中prt為指向X類的一個對象的指針。4. 命名空間作用域命名空間大型程序通常由不同模塊構成,不同模塊中的類和函數之間可能發生重名,將引發錯誤。命名空間可以解決類名、函數等的命名沖突。命名空間語法形式:namespace 命名空間名命名空間內的各種聲明(函數聲明、類聲明、)例namespace SomeNs class SomeClass . ;特殊的命名空間_ 全局命名空間:默認的命名空間_ 匿
13、名命名空間:對每個源文件是唯一的命名空間作用域一個命名空間確定了一個命名空間作用域引用其它命名空間作用域中的標識符_ 命名空間名:標識符名_ 例:聲明一個SomeClass型的對象SomeNs:SomeClass obj1;將其它命名空間作用域的標識符暴露于當前作用域_ 對指定標識符using 命名空間名:標識符名;_ 對所有標識符using namespace命名空間名;例5-1中所聲明的全局變量就具有文件作用域,它們在整個文件中都有效。例5-1 作用域實例。#include <iostream>using namespace std; /使得在當前文件中可直接引用std命名空間
14、的標識符coutint i;/全局變量,文件作用域namespace Nsint j;/在Ns命名空間中的全局變量void main()i=5;/文件作用域的i賦初值Ns:j=6;/為全局變量j賦值/子塊1using namespace Ns;/使得在當前塊中可直接引用Ns命名空間的標識符int i;/局部變量,塊作用域i=7;cout<<"i="<<i<<endl;/輸出7cout<<"j="<<j<<endl;cout<<"i="<<i
15、<<endl;/輸出5參考(cout, endl是命名空間std中的全局變量):#include <iostream>/using namespace std; /使得在當前文件中可直接引用std命名空間的標識符cout,endlint i;/全局變量,文件作用域namespace Nsint j;/在Ns命名空間中的全局變量void main()i=5;/文件作用域的i賦初值Ns:j=6;/為全局變量j賦值/子塊1using namespace Ns;/使得在當前塊中可直接引用Ns命名空間的標識符int i;/局部變量,塊作用域i=7;std:cout<<
16、"i="<<i<< std:endl;/輸出7std:cout<<"j="<<j<< std:endl;std:cout<<"i="<<i<< std:endl;/輸出5具有文件作用域的變量也稱為全局變量。5.1.2 可見性P150可見的標識符 程序運行到某一點,能夠引用到的標識符。文件作用域最大,接下來依次是類作用域和塊作用域。圖5-1 作用域關系圖可見性表示從內層作用域向外層作用域“看”時能看到什么。作用域可見性的一般規則:_ 標識符聲
17、明在前,引用在后。_ 同一作用域,不能聲明同名標識符。_ 在沒有包含關系的不同作用域中聲明的同名標識符互不影響。_ 在具有包含關系的作用域中聲明了同名標識符,則外層標識符在內層不可見。例5-l中,文件作用域與塊作用域相互包含。#include <iostream>using namespace std;int i;/全局變量,文件作用域namespace Nsint j;/在Ns命名空間中的全局變量void main()i=5;/文件作用域的i賦初值Ns:j=6;/為全局變量j賦值/子塊1using namespace Ns;int i;/局部變量,塊作用域i=7;cout<
18、<"i="<<i<<endl;/輸出7cout<<"j="<<j<<endl;cout<<"i="<<i<<endl;/輸出5在主函數內子塊1前,可引用到具有文件作用域的變量,它是可見的。當進入子塊1,只能引用到具有局部作用域的同名變量,文件作用域的同名變量不可見,稱內層屏蔽,或同名覆蓋,即內層的變量覆蓋了外層的同名變量。5.2 對象的生存期P150對象(包括簡單變量)從誕生到結束的這段時間就是它的生存期。5.2.1 靜態生存期若對象
19、的生存期與程序的運行期相同,稱它具有靜態生存期。在文件作用域中聲明的對象具有靜態生存期的。若要在函數內部的塊作用域中聲明具有靜態生存期的對象,則要使用關鍵字static。 static int i;i稱為靜態變量。其余的對象都具有動態生存期。定義時未指定初值的基本類型靜態生存期變量,初值為0;動態生存期變量,不指定初值時值不確定。5.2.2 動態生存期在塊作用域中聲明的具有動態生存期的對象,稱局部生存期對象。動態生存期對象誕生于聲明點,結束于該標識符作用域結束處。例5-2 變量的生存期與可見性。局部變量就是具有塊作用域的變量。全局變量就是具有文件作用域的變量。#include <iost
20、ream>using namespace std;int i=1;/i為全局變量,具有靜態生存期void other(void)static int a=2;static int b;/a, b為靜態局部變量,具有全局壽命,局部可見,只第一次進入函數時被初始化int c=10;/c為局部變量,具有動態生存期,每次進入函數時都初始化a=a+2; i=i+32; c=c+5;cout<<"-OTHER-n"cout<<"i:"<<i<<" a:"<<a<<&qu
21、ot; b:"<<b<<" c:"<<c<<endl;b=a;void main()static int a;/a為靜態局部變量,具有全局壽命,局部可見int b=-10;/b, c為局部變量,具有動態生存期int c=0;cout<<"-MAIN-n"cout<<"i:"<<i<<" a:"<<a<<" b:"<<b<<" c:&q
22、uot;<<c<<endl;c=c+8; other();cout<<"-MAIN-n"cout<<"i:"<<i<<" a:"<<a<<" b:"<<b<<" c:"<<c<<endl;c=c+10; other();例5-3 具有靜態、動態生存期對象的時鐘程序。聲明具有函數原型作用域、塊作用域、類作用域和文件作用域的多個變量及對象,并分析各自的可見性
23、和生存期。#include <iostream>using namespace std;class Clock/時鐘類定義public:Clock();void setTime(int newH,int newM,int newS);/三個形參具有函數原型作用域void showTime();private:int hour,minute,second;/時鐘類成員函數實現Clock:Clock():hour(0),minute(0),second(0) /構造函數void Clock:setTime(int newH,int newM,int newS)/3個形參均具有局部作用域
24、 hour=newH; minute=newM; second=newS; void Clock:showTime() cout<<hour<<":"<<minute<<":"<<second<<endl;Clock globClock;/聲明對象,具有靜態生存期,文件作用域void main()cout<<"第一次輸出:"<<endl;/引用文件作用域的對象globClock :globClock.showTime();/對象的
25、成員函數具有類作用域globClock.setTime(8,30,30);Clock myClock(globClock);/聲明具有塊作用域的對象cout<<"第二次輸出:"<<endl;myClock.showTime();/引用具有塊作用域的對象5.3 類的靜態成員P153靜態成員是解決同一個類的不同對象之間的數據和函數共享問題的。例,抽象出某公司全體雇員的共性,設計如下的雇員類:class Employee/雇員類private :int empNo int id string name /字符串對象.
26、若需要統計雇員總數,這個數據存放在什么地方呢?若以類外的變量來存儲總數,不能實現數據的隱藏。若在類中增加一個數據成員用以存放總數,必然在每一個對象中都存儲一個副本,不僅冗余,且每個對象分別維護一個“總數”,勢必造成數據的不一致性。比較理想的方案是類的所有對象共同擁有一個用于存放總數的數據成員。5.3.1 靜態數據成員P154實例屬性“一個類的所有對象具有相同的屬性”,是指屬性的個數、名稱、數據類型相同,各個對象的屬性值則可各不相同。以類的非靜態數據成員表示。類屬性是描述類的所有對象的共同特征的一個數據項,對于任何對象實例,它的屬性值是相同的。通過靜態數據成員來實現“類屬性”。靜態數據成員的訪問
27、靜態數據成員不屬于任何一個對象,只能通過類名對它訪問,用法是“類名:標識符”。靜態數據成員的說明和定義在類的聲明中僅僅對靜態數據成員進行引用性說明,必須在文件作用域的某處用類名限定進行定義性說明,這時也可進行初始化。在UML中,靜態數據成員下方添加下劃線。例5-4 具有靜態數據成員的Point類。引入靜態數據成員的Point類。圖5-2 包含靜態數據成員的Point類的UML圖Point x : int y : int count : int=0+Point(xx : int=0, yy : int=0)+getX() : int+getY() : int+Point(p : Point&am
28、p;)+showCount() : void#include <iostream>using namespace std;class Point/Point類定義public:Point(int xx=0,int yy=0):x(xx),y(yy) count+; /所有對象共同維護countPoint(Point &p) x=p.x; y=p.y; count+; Point() count-; int getX() return x; int getY() return y; void showCount() cout<<" 對象count=&qu
29、ot;<<count<<endl; /輸出靜態數據成員private:int x,y;static int count;/靜態數據成員聲明,用于記錄點的個數;int Point:count=0;/靜態數據成員定義和初始化,使用類名限定void main()Point a(4,5);/定義對象a,其構造函數會使count增1cout<<"Point a: "<<a.getX()<<","<<a.getY();a.showCount();/輸出對象個數Point b(a); /定義對象b
30、,其拷貝構造函數會使count增1cout<<"Point b: "<<b.getX()<<","<<b.getY();b.showCount();在對類的靜態私有數據成員初始化的同時,還可引用類的其他私有成員。例,若一個類T存在類型T的靜態私有對象,則可引用該類的私有構造函數將其初始化。5.3.2 靜態函數成員P156靜態成員函數是使用static關鍵字聲明的函數成員。靜態成員函數屬于整個類,由同一個類的所有對象共同維護,并共享。對于公有的靜態成員函數,可通過類名或對象名來調用。靜態成員函數可直接訪問該類
31、的靜態數據和函數成員,而訪問非靜態數據成員,必須通過參數傳遞方式得到對象名,然后通過對象名來訪問。class Apublic:static void f(A a);private:int x;void A:f(A a)cout<<x;/對x的引用是錯誤的。可用A:f(c)調用,此時,無當前對象。cout<<a.x;/正確在UML中,靜態函數成員前添加<<static>>。例5-5 具有靜態數據和函數成員的Point類。圖5-3 包含靜態函數成員的Point類的UML圖Point x : int y : int count : int=0+Poin
32、t(xx : int=0, yy : int=0)+getX() : int+getY() : int+Point(p : Point&)<<static>>+showCount() : void#include <iostream>using namespace std;class Pointpublic:Point(int xx=0,int yy=0):x(xx),y(yy) count+; ;Point(Point &p) x=p.x; y=p.y; count+; Point() count-; int getX() return x
33、; int getY() return y; static void showCount() cout<<" 對象count="<<count<<endl; /靜態函數成員private:int x,y;static int count;/靜態數據成員聲明;int Point:count=0;/靜態數據成員定義及初始化,使用類名限定void main()Point a(4,5);cout<<"Point a: "<<a.getX()<<","<<a.g
34、etY();Point:showCount();/輸出對象號,類名引用Point b(a);cout<<"Point b: "<<b.getX()<<","<<b.getY();b.showCount();/輸出對象號,對象名引用采用靜態函數成員的好處可不依賴于任何對象,直接訪問靜態數據。5.4 類的友元P158友元提供了不同類或對象的成員函數之間、類的成員函數與一般函數之間進行數據共享的機制。在一個類中,可用關鍵字friend將其他函數或類聲明為友元。若友元是一般函數或類的成員函數,稱友元函數;若友元是一
35、個類,稱友元類,友元類的所有成員函數都自動成為友元函數。5.4.1 友元函數P160友元函數是在類中用關鍵字friend修飾的非成員函數。友元函數不是本類的成員函數,但是在它的函數體中可通過對象名訪問類的私有和保護成員。在UML中,友元函數前添加<<friend>>。例5-6 使用友元函數計算兩點間的距離。圖5-4 包含友元函數成員的Point類的UML圖Point x : int y : int+Point(xx : int=0, yy : int=0)+getX() : int+getY() : int<<friend>>+dist(a :
36、Point&, b : Point&) : foat#include <iostream>#include <cmath>using namespace std;class Point/Point類定義public:Point(int xx=0,int yy=0):x(xx),y(yy)int getX() return x; int getY() return y; friend float dist(Point &p1,Point &p2);/友元函數聲明private:int x,y;float dist(Point &p1
37、,Point &p2)/友元函數實現double x=double(p1.x-p2.x);/通過對象訪問私有數據成員double y=double(p1.y-p2.y);return static_cast<float>(sqrt(x*x+y*y);void main()Point myp1(1,1),myp2(4,5);cout<<"距離是:"cout<<dist(myp1,myp2)<<endl;5.4.2 友元類P161若A類為B類的友元類,則A類的所有成員函數都是B類的友元函數,都可以訪問B類的私有和保護成員。
38、class B. /B類的成員聲明friend class A;/聲明A為B的友元類.;聲明友元類,是建立類與類之間的聯系,實現類之間數據共享的一種途徑。在UML中,兩個類之間的友元關系是通過<<friend>>構造型依賴來表征。圖5-5 類A和類B友元關系的UML圖B+set(i : int) : void+display() : voidA x : int+display() : void+getx() : int<<friend>>-a#include <iostream>using namespace std;class Ap
39、ublic:void display() cout<<x<<endl; int getx() return x; friend class B;private:int x;class Bpublic:void set(int i);void display() cout<<a.x<<endl; private:A a;void B:set(int i)a.x=i;/由于B是A的友元,所以在B的成員函數中可以訪問A類對象的私有成員void main()B b;b.set(5);b.display();注意:第一,友元關系是不能傳遞的。第二,友元關系
40、是單向。第三,友元關系是不被繼承的。5.5 共享數據的保護P1635.5.1 常對象聲明格式:const 類型說明符 對象名;或類型說明符 const 對象名;常對象必須進行初始化,且不能被更新。語法如何保障常對象的值不被改變呢?改變對象的數據成員值有兩個途徑:一是在類外通過對象名訪問其公有數據成員,這時語法會限制不能再賦值。二是在類的成員函數中改變數據成員的值,規定不能通過常對象調用普通的成員函數。5.5.2 用const修飾的類成員P1641. 常成員函數聲明格式:類型說明符 函數(參數表)const;注意: const是函數類型的一個組成部分。 常成員函數不能更新對象的數據成員,也不能調
41、用該類中沒有用const修飾的成員函數。 常對象只能調用它的常成員函數。 const可用于對重載函數的區分。例如, void print(); void print() const;這是對print的有效重載。在UML中,常成員函數前添加<<const>>。例5-7 常成員函數舉例。圖5-6 包含常成員函數的R類的UML圖R r1 : int r2 : int+R(rr1 : int, rr2 : int)+print() : void<<const>>+print() : void#include <iostream>using n
42、amespace std;class Rpublic:R(int rr1,int rr2):r1(rr1),r2(rr2)void print();void print() const;/常成員函數private:int r1,r2;void R:print() cout<<r1<<":"<<r2<<endl; void R:print() const cout<<r1<<""<<r2<<endl; void main()R a(5,4);a.print();
43、const R b(20,52);b.print();2. 常數據成員類的成員數據也可以是常量。使用const說明的數據成員為常數據成員。任何函數中都不能對常數據成員賦值。構造函數對常數據成員進行初始化,就只能通過初始化列表。在UML中,常數據成員前添加const。例5-8 常數據成員舉例。圖5-7 包含常數據成員的A類的UML圖A a : const int b : const int=10+A(i : int)+print() : void#include <iostream>using namespace std;class Apublic:A(int i);void pri
44、nt();private:const int a;/常數據成員static const int b;/靜態常數據成員;const int A:b=10;/靜態常數據成員在類外說明和初始化A:A(int i):a(i) /常數據成員只能通過初始化列表來獲得初值 void A:print() cout<<a<<":"<<b<<endl; void main()/*建立對象a1和a2,并以100和0作為初值,分別調用構造函數,通過構造函數的初始化列表給對象的常數據成員賦初值*/A a1(100),a2(0);a1.print();a
45、2.print();5.5.3 常引用P166常引用的說明形式:const 類型說明符 &引用名;常引用所引用的對象不能被更新。若用常引用做形參,便不會發生對實參意外的更改。例5-9 常引用做形參#include <iostream>#include <cmath>using namespace std;class Point/Point類定義public:Point(int xx=0,int yy=0):x(xx),y(yy)int getX() return x; int getY() return y; friend float dist(const Po
46、int &p1,const Point &p2);/友元函數聲明private:int x,y;float dist(const Point &p1, const Point &p2)/友元函數實現double x=double(p1.x-p2.x);/通過對象訪問私有數據成員double y=double(p1.y-p2.y);return static_cast<float>(sqrt(x*x+y*y);void main()const Point myp1(1,1),myp2(4,5);cout<<"距離是:"c
47、out<<dist(myp1,myp2)<<endl;*5.6 多文件結構和編譯預處理命令P1685.6.1 C+程序的一般組織結構通常一個項目至少劃分為三個文件:類聲明文件(*.h文件)類實現文件(*.cpp文件)類的使用文件(*.cpp,主函數文件)每個源程序文件稱為一個編譯單元。C+語法要求一個類的聲明必須出現在所有使用該類的編譯單元中。慣用的做法將類的聲明寫在頭文件中,使用該類的編譯單元則包含這個頭文件。例5-10 具有靜態數據、函數成員的Point類,多文件組織。/文件1,類的聲明,point.h#include <iostream>using n
48、amespace std;class Pointpublic:Point(int xx=0,int yy=0)X=xx; Y=yy; countP+; ;Point(Point &p);Point()countP-;int GetX()return X;int GetY()return Y;static void GetC() cout<<"對象id="<<countP<<endl; /靜態函數成員private:int X,Y;static int countP;/靜態數據成員聲明;/文件2,類的實現,point.cpp#inc
49、lude “point.h”int Point:countP=0;/靜態數據成員定義及初始化,使用類名限定Point:Point(Point &p) X=p.X; Y=p.Y; countP+; /文件3,主函數,pmain.cpp#include “point.h”void main()Point A(4,5);cout<<"Point A,"<<A.GetX()<<","<<A.GetY();A.GetC();/輸出對象號,對象名引用Point B(A);cout<<"Po
50、int B,"<<B.GetX()<<","<<B.GetY();Point:GetC();/輸出對象號,類名引用圖5-8 C+多文件組織結構圖#include指令的作用將指定的源文件嵌入到當前源文件中#include指令所在位置,被嵌入的文件可以是.h文件,也可以是.cpp文件。#include兩上書寫方式#include<文件名>,按照標準方式搜索要嵌入的文件,該文件位于C+系統目錄的include子目錄下,一般包含系統提供的標準文件時采用這樣的方式。#include"文件名",首先在當前目錄
51、下搜索要嵌入的文件,若沒有,再按照標準方式搜索,對用戶自己編寫的文件一般采用這種方式。在使用多文件結構時,注意內聯函數的特殊性一個內聯函數,需要在每個調用它的編譯單元中給出一個完全一致的實現。慣用的做法是將內聯函數的實現寫在頭文件中,由調用的編譯單元包含這個頭文件。5.6.2 外部變量與外部函數P170用extern聲明外部變量。外部變量是具有文件作用域的變量,定義在所有文件之外。聲明一個外部變量時,可以同時定義它,也可以只是引用一個在別處聲明的外部變量。/源文件1int i=3 /定義變量ivoid next(void) /函數原型聲明void main() i+; ne
52、xt() void next(void) i+ other() /源文件2extern int i /聲明一個在其他文件中定義的外部變量ivoid other(void) i+; 外部變量是可以為多個源文件所共享的全局變量。定義性聲明 引用性聲明對外部變量的聲明可以是定義性聲明,即在聲明的同時定義(分配內存,初始化),也可以是引用性聲明(引用在別處定義的變量)。外部變量可用extern在多處聲明,但對變量的定義和初始化是惟一的。定義一個文件作用域的變量時,其默認狀態可以為不同的編譯單元所共享,只要在其他編譯單元中冠以extern聲明該變量即可,若在
53、文件作用域中定義變量時以static修飾,則該變量的作用范圍僅限于定義它的編譯單元。2. 外部函數非成員函數具有文件作用域,可以在不同的編譯單元被調用,只要在調用之前聲明函數原型即可。可以在聲明函數原型或定義函數時用extern修飾,其效果與不加修飾的默認狀態是一樣的。若在聲明一個函數原型時或定義函數時冠以static修飾,就將函數的作用域限制在當前的編譯單元內。5.6.3 標準C+庫P172標準C+類與組件在邏輯上分為6種類型:輸入/輸出類容器類與ADT(抽象數據類型)存儲管理類算法錯誤處理運行環境支持對庫中預定義內容的說明分別存在于不同的頭文件中,要使用這些預定義的成分,就要將相應的頭文件
54、包含到源程序中。標準C+庫不再有“.h”擴展名,但仍保留18個帶有“.h”擴展名的C頭文件。兩種形式的頭文件不能混用。比如,若已經包含頭文件iostream,就不能再包含math.h,而要代之以新的頭文件cmath。使用標準C+庫時,在緊接著所有的include指令之后,加入using namespace std;將指定命名空間中的名稱引入到當前命名空間中。否則,需要在使用std命名空間中的標識符時冠以命名空間名“:”。(第10章)5.6.4 編譯預處理P173編譯器在對源程序進行編譯之前,首先要由預處理程序對程序文本進行預處理。預處理程序提供了一組編譯預處理指令和預處理操作符。所有的預處理指
55、令在程序中都是以“#”來引導,每一條預處理指令單獨占用行,不要用分號結束。預處理指令可以根據需要出現在程序中的任何位置。1. #include指令(文件包含指令)其作用是將另一個源文件嵌入到當前源文件中該點處。 include<文件名>按標準方式搜索,文件位于C+系統目錄的include子目錄下。 include"文件名"首先在當前目錄中搜索,若沒有,再按標準方式控索。2. #define和#undef指令#define用來定義符號常量,例如,#define PI 3.14。#undef用來刪除由#define定義的宏,使之不再起作用。3. 條件編譯指令用來限定
56、程序中的某些內容要在滿足一定條件的情況下才參與編譯。常用的條件編譯語句有下列5種形式: 形式1#if 常量表達式程序段 /當“常量表達式”非0時編譯本程序段#endif 形式2#if 常量表達式程序段1 /當“常量表達式”非0時編譯本程序段#else程序段2 /當“常量表達式”為0時編譯本程序段#endif 形式3#if 常量表達式1程序段1 /當“常量表達式1”非0時編譯本程序段#elif常量表達式2程序段2 /否則,當“常量表達式2”非0時編譯本程序段 .#elif常量表達式n程序段n /否則,當“常量表達式n”非0時編譯本程序段#else程序段n+1 /其他情況下編譯本程序段#endif
57、 形式4#ifdef 標識符程序段1 /若“標識符”經#define定義過,且未經#undef刪除,則編譯本程序段#else程序段2 /否則編譯本程序段#endif#ifdef 標識符程序段 /若“標識符”經#define定義過,且未經#undef刪除,則編譯本程序段#endif 形式5#ifndef 標識符程序段1 /若“標識符”未定義過,則編譯本程序段#else程序段2 /否則編譯本程序段#endif#ifdef 標識符程序段 /若“標識符”未定義過,則編譯本程序段#endif4. defined操作符defined是一個預處理操作符,而不是指令,因此不要以#開頭。defined(標識符)若“標識符”在此前經#define定義過,且未經#undef刪除,則上述表達式為非0,否則為0。下面兩種寫法是完全等效的:#ifndef MYHEAD_H#define MYHEAD_H.#end
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 跨界合作的業務發展策略計劃
- 區塊鏈如何助力智慧城市建設
- 倉庫績效激勵機制的設計計劃
- 行政法與公共利益的關系試題及答案
- 行政管理專業經濟法知識試題及答案
- 舞蹈社團表演活動安排計劃
- 執業護士考試臨床護理質量試題及答案
- 員工職業生涯規劃與支持機制計劃
- 堅持可持續發展的工作理念計劃
- 幼兒園心理健康課程計劃
- 項目部臨時動火作業審批表
- 飲料生產公司應急預案匯編參考范本
- 高效水泥助磨劑PPT課件(PPT 66頁)
- 生物防治第三講
- 旁站監理實施細則(完整版)
- 學業水平考試復習高中語文文言文課本翻譯
- 蘇教版二年級(下冊)科學全冊單元測試卷含期中期末(有答案)
- 常用原料凈料率參照表
- 高低溫試驗報告
- 第一章 混凝土拌合站組織機構框圖及崗位職責
- 指南預應力簡支t形梁橋
評論
0/150
提交評論