




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
C++基礎(chǔ)
2.1類和對象
2.1.1從結(jié)構(gòu)到類
2.1.2類的定義
一般地分為聲明部分和實(shí)現(xiàn)部分。聲明部分是用來聲明該類中的成員,含數(shù)據(jù)成員和成員函數(shù)的聲明。成員函數(shù)是用來對數(shù)據(jù)成員進(jìn)行操作的。實(shí)現(xiàn)部分是用來對成員函數(shù)的定義。聲明部分將告訴使用者“幹什麼”,而實(shí)現(xiàn)部分是告訴使用者“怎麼幹”。
定義類的一般格式如下:
class<類名> {private: [<私有數(shù)據(jù)和函數(shù)>] public: [<公有數(shù)據(jù)和函數(shù)>]};
<各個(gè)成員函數(shù)的實(shí)現(xiàn)>class的後面是用戶定義的類名,類中的數(shù)據(jù)和函數(shù)是類的成員,分別稱為數(shù)據(jù)成員和成員函數(shù)。由於數(shù)據(jù)成員是用變數(shù)來描述的,因此數(shù)據(jù)成員又可稱為“成員變數(shù)”。
public和private聲明了類中的成員和程式其他部分的關(guān)係。對於public類成員來說,它們是公有的,能被外面的程式訪問;對於private類成員來說,它們是私有的,只能由類中的函數(shù)所使用,而不能被外面的程式所訪問。
<各個(gè)成員函數(shù)的實(shí)現(xiàn)>是類定義中的實(shí)現(xiàn)部分,包含所有在類體中聲明的函數(shù)的定義。如果一個(gè)成員函數(shù)在類體中定義,實(shí)現(xiàn)部分將不出現(xiàn)。如果所有的成員函數(shù)都在類體中定義,則實(shí)現(xiàn)部分可以省略。當(dāng)類的成員函數(shù)的函數(shù)體在類的外部定義時(shí),必須由作用域運(yùn)算符“::”來通知編譯系統(tǒng)該函數(shù)所屬的類。
2.1類和對象
定義類時(shí)還應(yīng)注意:(1)
在“public:”或“private:”後面定義的所有成員都是公有或私有的,直到下一個(gè)“public:”或“private:”出現(xiàn)為止。若成員前面沒有類似“public:”或“private:”,則所定義的成員是private(私有),這是類的默認(rèn)設(shè)置。(2)
關(guān)鍵字public和private可以在類中出現(xiàn)多次,且前後的順序沒有關(guān)係。但最好先聲明公有成員,後聲明私有成員,因?yàn)閜ublic成員是用戶最關(guān)心的。(3)
除了public和private外,關(guān)鍵字protected(保護(hù))也可修飾成員的類型,它與private兩者基本相似,但在類的繼承時(shí)有所不同。(4)
數(shù)據(jù)成員的類型可以是任意的,包含整型、浮點(diǎn)型、字元型、數(shù)組、指針等,也可以是另一個(gè)類的對象,但不允許對所定義的成員變數(shù)進(jìn)行初始化。
(5)儘量將類單獨(dú)存放在一個(gè)檔中或?qū)㈩惖穆暶鞣旁?h檔中而將成員函數(shù)的實(shí)現(xiàn)放在與.h檔同名的.cpp檔中。以後將會看到,VisualC++6.0為用戶創(chuàng)建的應(yīng)用程式框架中都是將各個(gè)類以.h和同名的.cpp檔來組織的。
2.1類和對象2.1.3對象的定義
一個(gè)類定義後,就可以定義該類的對象,格式: <類名><對象名列表>
類名是用戶已定義過的類的識別字,對象名可以有一個(gè)或多個(gè),多個(gè)時(shí)要用逗號分隔。被定義的對象既可以是一個(gè)普通對象,也可以是一個(gè)數(shù)組對象或指針對象。一個(gè)對象的成員就是該對象的類所定義的成員,引用(訪問)時(shí)可用下列方式:
<對象名>.<成員名> <對象名>.<成員名>(<參數(shù)表>)。前者用來表示引用數(shù)據(jù)成員,後者用來表示引用成員函數(shù)?!?”是一個(gè)成員運(yùn)算符,用來引用對象的成員對於指針對象的成員引用可用下列方式:
<對象指針名>-><成員名> <對象指針名>-><成員名>(<參數(shù)表>)“->”與“.”運(yùn)算符的區(qū)別是:“->”用來訪問指針對象的成員,“.”用來訪問一般對象的成員。需要說明的是,下麵的兩種表示是等價(jià)的:
<對象指針名>-><成員名> (*<對象指針名>).<成員名>
這對於成員函數(shù)也適用,例如two->GetAverage()和(*two).GetAverage()是等價(jià)的,由於成員運(yùn)算符“.”的優(yōu)先順序比取內(nèi)容運(yùn)算符“*”高。若結(jié)構(gòu)成員前面沒有“public:”或“private:”,則所定義的成員是public(公有)。
2.2類的成員及特性
2.2.1構(gòu)造函數(shù)
使用構(gòu)造函數(shù)能給數(shù)據(jù)成員自動設(shè)置某些初始值。它的最大特點(diǎn)是在對象建立時(shí)它會被自動執(zhí)行,因此用於變數(shù)、對象的初始化代碼一般放在構(gòu)造函數(shù)中。構(gòu)造函數(shù)必須與相應(yīng)的類同名,可以帶參數(shù),可以不帶參數(shù),而且可以重載。但不能指定函數(shù)返回值的類型,也不能指定為void類型。例如:classCStuScore { public: CStuScore(charstr[12]) //第一個(gè)構(gòu)造函數(shù)
{ strcpy(strName,str); } CStuScore(charstr[12],charstrNO[9]) //第二個(gè)構(gòu)造函數(shù)
{ strcpy(strName,str); strcpy(strStuNO,strNO);} char strName[12]; //姓名
char strStuNO[9]; //學(xué)號
...}
(1)
程式中的strcpy是一個(gè)庫函數(shù),用來複製字串,使用時(shí)要頭檔string.h。
(2)
類定義時(shí),如沒有定義任何構(gòu)造函數(shù),編譯器自動為類生成一個(gè)不帶任何參數(shù)的默認(rèn)構(gòu)造函數(shù)。
(3)
由於構(gòu)造函數(shù)的參數(shù)只能在定義對象時(shí)指定。
2.2類的成員及特性2.2.2析構(gòu)函數(shù)
與構(gòu)造函數(shù)相對應(yīng)的另一種特殊的C++成員函數(shù)是析構(gòu)函數(shù),它的功能是用來釋放一個(gè)對象,在對象刪除前,用它來做一些清理工作,它與構(gòu)造函數(shù)的功能正好相反。 析構(gòu)函數(shù)也要與相應(yīng)的類同名,並在名稱前面加上一個(gè)“~”符號。每一個(gè)類只有唯一的一個(gè)析構(gòu)函數(shù),沒有任何參數(shù),也不返回任何值,也不能被重載。例如:
classCStuScore { public: ... ~CStuScore() { } //析構(gòu)函數(shù)
...}
同樣,如果一個(gè)類中沒有定義析構(gòu)函數(shù)時(shí),則編譯系統(tǒng)也會為類自動生成一個(gè)默認(rèn)析構(gòu)函數(shù),其格式如下(以類CStuScore為例):
~CStuScore() //默認(rèn)析構(gòu)函數(shù)的形式
{}需要說明的是,析構(gòu)函數(shù)只有在下列兩種情況下才會被自動調(diào)用:
(1)
當(dāng)對象定義在一個(gè)函數(shù)體中,該函數(shù)調(diào)用結(jié)束後,析構(gòu)函數(shù)被自動調(diào)用。
(2)
用new為對象分配動態(tài)記憶體後,當(dāng)使用delete釋放對象時(shí),析構(gòu)函數(shù)被自動調(diào)用。
2.2類的成員及特性2.2.3對象成員初始化 構(gòu)造函數(shù)定義格式:
<類名>::<構(gòu)造函數(shù)名>(形參表):對象1(參數(shù)表),對象2(參數(shù)表),…,對象n(參數(shù)表) {…… }
對象1、對象2、…、對象n就是該類使用的其他類的對象,冒號“:”後面的列表稱為成員初始化列表。說明:(1)
類的對象成員必須初始化,但不能將對象成員直接在構(gòu)造函數(shù)體內(nèi)進(jìn)行初始化,例如下麵的初始化是不可以的:
CRect(intleft,inttop,intright,intbottom) { ptCenter=CPoint((left+right)/2,(top+bottom)/2); size=CSize(right-left,bottom-top);}(2)
對象成員初始化時(shí),必須有相應(yīng)的構(gòu)造函數(shù),且多個(gè)對象成員的構(gòu)造次序不是按初始化成員列表的順序,而是按各類聲明的先後次序進(jìn)行的,從上例的運(yùn)行結(jié)果可以得到證明。(3)
對象成員初始化也可在類構(gòu)造函數(shù)定義時(shí)進(jìn)行。(4)事實(shí)上,成員初始化列表也可用於類中的普通數(shù)據(jù)成員的初始化。
2.2類的成員及特性2.2.4常類型
常對象 常對象是指對象常量,定義格式:<類名>const<對象名>
定義常對象時(shí)要進(jìn)行初始化,並且該對象不能再被更新,修飾符const可以放在類名後面,也可以放在類名前面。
常成員函數(shù)
使用const關(guān)鍵字進(jìn)行聲明的成員函數(shù)。只有常成員函數(shù)才有資格操作常量或常對象。說明格式: <類型說明符><函數(shù)名>(<參數(shù)表>)const;
const是加在函數(shù)聲明後面的類型修飾符,它是函數(shù)類型的一個(gè)組成部分,因此在函數(shù)實(shí)現(xiàn)部分也要帶const關(guān)鍵字。常成員函數(shù)還可以理解為一個(gè)“只讀”函數(shù),它不能更改數(shù)據(jù)成員的值,也不能調(diào)用那些引起數(shù)據(jù)成員值變化的成員函數(shù),只能調(diào)用const成員函數(shù)。
常數(shù)據(jù)成員 類型修飾符const不僅可以說明成員函數(shù),也可以說明數(shù)據(jù)成員。由於const類型對象必須被初始化,並且不能更新,因此,在類中聲明const數(shù)據(jù)成員後,只能通過構(gòu)造函數(shù)成員初始化方式來對常數(shù)據(jù)成員初始化。
2.2類的成員及特性2.2.5this指針
類中總有一個(gè)特殊的指針this,它指向類自己。該指針可以在類中訪問類的成員變數(shù)和成員函數(shù)。但在實(shí)際運(yùn)用中,一般不需要顯式地使用this指針來引用成員。
[例Ex_This]this指針的使用。
#include<iostream.h> classCOne { public: COne() {x=y=0;} COne(inta,intb) {x=a; y=b;} //對象引用作函數(shù)參數(shù)
voidcopy(COne&a); voidprint() {cout<<x<<","<<y<<endl;} private: intx,y;}; voidCOne::copy(COne&a) { if(this==&a)return; *this=a;}
voidmain() { COneone,two(3,4); one.print(); one.copy(two); one.print();}
運(yùn)行結(jié)果:
0,0 3,4
函數(shù)copy代碼中,*this=a;是將形參a獲得的某對象的值賦給操作該成員函數(shù)的對象。在本例中,就是將對象two賦給對象one。2.2類的成員及特性2.2.6類的作用域和對象的生存期類的作用域是指在類的定義中由一對花括弧所括起來的部分。類作用域中定義的變數(shù)不能使用auto,register和extern等修飾符,只能使用static修飾符,而定義的函數(shù)也不能用extern修飾符。檔作用域中可以包含類作用域,類作用域小於檔作用域。某個(gè)類A中某個(gè)成員M在下列情況下具有類A的作用域:(1)
成員M出現(xiàn)在類A的某個(gè)成員函數(shù)中,並且該成員函數(shù)沒有定義同名識別字。(2)
成員M出現(xiàn)在a.M或A::M運(yùn)算式中,其中a是A的對象。(3)
成員M出現(xiàn)在pa->M這樣的運(yùn)算式中,其中pa是一個(gè)指向A類對象的指針。對象的生存期是指對象從被創(chuàng)建開始到被釋放為止的時(shí)間。生存期的不同對象分:(1)
局部對象:當(dāng)對象被定義時(shí)調(diào)用構(gòu)造函數(shù),該對象被創(chuàng)建,當(dāng)程式退出定義該對象所在的函數(shù)體或程式塊時(shí),調(diào)用析構(gòu)函數(shù),釋放該對象。(2)
靜態(tài)對象:當(dāng)程式第一次執(zhí)行所定義的靜態(tài)對象時(shí),該對象被創(chuàng)建,當(dāng)程式結(jié)束時(shí),該對象被釋放。(3)
全局對象:當(dāng)程式開始時(shí),調(diào)用構(gòu)造函數(shù)創(chuàng)建該對象,當(dāng)程式結(jié)束時(shí)調(diào)用析構(gòu)函數(shù)釋放該對象。局部對象是被定義在一個(gè)函數(shù)體或程式塊內(nèi)的,它的作用域小,生存期也短。靜態(tài)對象是被定義在一個(gè)檔中,它的作用域從定義時(shí)起到檔結(jié)束時(shí)止。它的作用域比較大,它的生存期也比較長。全局對象是被定義在某個(gè)檔中,而它的作用域卻在包含該檔的整個(gè)程式中,它的作用域是最大的,它的生存期也是最長的。
2.2類的成員及特性2.2.7靜態(tài)成員
靜態(tài)數(shù)據(jù)成員
靜態(tài)數(shù)據(jù)成員是同一個(gè)類中所有對象共用的成員。使用靜態(tài)數(shù)據(jù)成員可以節(jié)省記憶體。靜態(tài)數(shù)據(jù)成員的值對每個(gè)對象都是一樣,但它的值是可以更新的。靜態(tài)數(shù)據(jù)成員是靜態(tài)存儲的,具有靜態(tài)生存期。它是這樣的定義的:
(1)
使用關(guān)鍵字static聲明靜態(tài)數(shù)據(jù)成員。
(2)
對靜態(tài)數(shù)據(jù)成員進(jìn)行初始化。由於靜態(tài)數(shù)據(jù)成員需要系統(tǒng)為其分配記憶體空間,因此不能在類聲明中進(jìn)行初始化。靜態(tài)數(shù)據(jù)成員初始化須在類的外部進(jìn)行,且與一般數(shù)據(jù)成員初始化不同,它的格式如下:
<數(shù)據(jù)類型><類名>::<靜態(tài)數(shù)據(jù)成員名>=<值>靜態(tài)成員函數(shù)
靜態(tài)成員函數(shù)屬於類的靜態(tài)成員,但它不是對象成員。因此,對靜態(tài)成員的引用不要用對象名。在靜態(tài)成員函數(shù)的實(shí)現(xiàn)中不能直接引用類中的非靜態(tài)成員,但可以引用類中的靜態(tài)成員。如果靜態(tài)成員函數(shù)中一定要引用非靜態(tài)成員時(shí),則可通過對象來引用。公有的靜態(tài)成員函數(shù)既可以通過相應(yīng)的對象訪問,也可以通過其所屬的類名來引用。
2.2類的成員及特性2.2.8友元
類的重要特性是使數(shù)據(jù)封裝與隱藏,但同時(shí)也給外部函數(shù)訪問類中的私有和保護(hù)類型數(shù)據(jù)成員帶來了不便,為此,C++使用一個(gè)特殊的函數(shù)——“友元函數(shù)”來解決這個(gè)問題。
“友元函數(shù)”必須在類中進(jìn)行聲明而在類外定義,聲明時(shí)須在函數(shù)類型前面加上關(guān)鍵字friend。友元函數(shù)雖不是類的成員函數(shù),但它可以訪問類中的私有和保護(hù)類型數(shù)據(jù)成員。
friend除了可以定義友元函數(shù)外,還可以定義友元類,即一個(gè)類可以作另一個(gè)類的友元。當(dāng)一個(gè)類作為另一個(gè)類的友元時(shí),這就意味著這個(gè)類的所有成員函數(shù)都是另一個(gè)類的友元函數(shù)。
2.3繼承和派生類
通過繼承可以在一個(gè)一般類的基礎(chǔ)上建立新類。被繼承的類稱為基類(baseclass),在基類上建立的新類稱為派生類(derivedclass)。如果一個(gè)類只有一個(gè)基類則稱為單繼承,否則稱為多繼承。通過進(jìn)行類繼承,可以提高程式的可重用性和可維護(hù)性。
2.3.1單繼承 從一個(gè)基類定義一個(gè)派生類可按下列格式:
class<派生類名>:[<繼承方式>]<基類名> { [<派生類的成員>] };
繼承方式有三種:public(公有)、private(私有)及protected(保護(hù)),若繼承方式?jīng)]有指定,則被指定為默認(rèn)的public方式。繼承方式?jīng)Q定了派生類繼承基類的屬性及其使用權(quán)限。公有繼承(public)公有繼承的特點(diǎn)是基類的公有成員和保護(hù)成員作為派生類的成員時(shí),它們都保持原有的狀態(tài),而基類的私有成員仍然是私有的。注意的是:派生類中或派生類的對象可以使用基類的公有成員(包括保護(hù)成員),例如CStudent類的成員函數(shù)Print中調(diào)用了基類CPerson的Output函數(shù),stu對象調(diào)用了基類的SetData成員函數(shù),但基類或基類的對象卻不可以使用派生類的成員。
2.3繼承和派生類私有繼承(private)
特點(diǎn)是基類的公有成員和保護(hù)成員都作為派生類的私有成員,並且不能被這個(gè)派生類的子類所訪問。保護(hù)繼承(protected)
特點(diǎn)是基類的所有公有成員和保護(hù)成員都成為派生類的保護(hù)成員,並且只能被它的派生類成員函數(shù)或友元訪問,基類的私有成員仍然是私有的。注意:一定要區(qū)分清楚派生類的對象和派生類中的成員函數(shù)對基類的訪問是不同的。例如,在公有繼承時(shí),派生類的對象可以訪問基類中的公有成員,派生類的成員函數(shù)可以訪問基類中的公有成員和保護(hù)成員。在私有繼承和保護(hù)繼承時(shí),基類的所有成員不能被派生類的對象訪問,而派生類的成員函數(shù)可以訪問基類中的公有成員和保護(hù)成員。2.3繼承和派生類2.3.2派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù)
派生類對象在建立時(shí),先執(zhí)行基類的構(gòu)造函數(shù),然後執(zhí)行派生類的構(gòu)造函數(shù)。但對於析構(gòu)函數(shù)來說,其順序剛好相反,先執(zhí)行派生類的析構(gòu)函數(shù),而後執(zhí)行基類的析構(gòu)函數(shù)。注意:基類的構(gòu)造函數(shù)和析構(gòu)函數(shù)不能被派生類繼承。 派生類進(jìn)行初始化對基類設(shè)置初值格式:
<派生類名>(總參表):<基類1>(參數(shù)表1),<基類2>(參數(shù)表2),…,<基類n>(參數(shù)表n),對象成員1(對象成員參數(shù)表1),對象成員2(對象成員參數(shù)表2),…,對象成員n(對象成員參數(shù)表n) {...}
構(gòu)造函數(shù)總參表後面給出的是需要用參數(shù)初始化的基類名、對象成員名及各自對應(yīng)的參數(shù)表,基類名和對象成員名之間的順序可以是任意的,且對於使用默認(rèn)構(gòu)造函數(shù)的基類和對象成員,可以不列出基類名和對象成員名。這裏所說的對象成員是指在派生類中新聲明的數(shù)據(jù)成員,它屬於另外一個(gè)類的對象。對象成員必須在初始化列表中進(jìn)行初始化。2.3繼承和派生類2.3.3多繼承在類的繼承中允許一個(gè)派生類繼承多個(gè)基類,這種多繼承的方式可使派生類具有多個(gè)基類的特性,因而不僅使程式結(jié)構(gòu)清晰,且大大提高了程式代碼的可重用性。 多繼承下派生類的定義是按下麵的格式:
class<派生類名>:[<繼承方式1>]<基類名1>,[<繼承方式2>]<基類名2>,... { [<派生類的成員>] };
其中的繼承方式還是前面的三種:public、private和protected。 例如:
classA {...} classB {...} classC:publicA,privateB {...}
派生類C的成員包含了基類A中成員和B中成員以及該類本身的成員。
C++允許一個(gè)基類有多個(gè)派生類(稱為多重派生)以及從一個(gè)基類的派生類中再進(jìn)行多個(gè)層次的派生。
C++進(jìn)階
3.1多態(tài)和虛函數(shù)
多態(tài)(Polymorphism)編譯時(shí)多態(tài):重載運(yùn)行時(shí)多態(tài):虛函數(shù)3.1多態(tài)和虛函數(shù)
3.1.1虛函數(shù)
[例Ex_VirtualFunc]虛函數(shù)的使用。#include<iostream.h>classCShape{public: virtualfloatarea() {return0.0;} };classCTriangle:publicCShape{public:CTriangle(floath,floatw){H=h; W=w; }floatarea(){return(float)(H*W*0.5);}private: floatH,W;};classCCircle:publicCShape{public: CCircle(floatr) { R=r; } floatarea() {return(float)(3.14159265*R*R);} private: floatR;};voidmain(){ CShape*s[2]; s[0]=newCTriangle(3,4); cout<<s[0]->area()<<endl; s[1]=newCCircle(5); cout<<s[1]->area()<<endl;}
運(yùn)行結(jié)果為:
6 78.5398
3.1多態(tài)和虛函數(shù)
說明:
(1)
虛函數(shù)在重新定義時(shí)參數(shù)的個(gè)數(shù)和類型必須和基類中的虛函數(shù)完全匹配,這一點(diǎn)和函數(shù)重載完全不同。
(2)
虛函數(shù)所具備的上述功能,只有通過基類指針才可實(shí)現(xiàn)。虛函數(shù)在用對象名和成員運(yùn)算符以正常方式調(diào)用時(shí),不能達(dá)到其效果。
(3)
如果不使用new來創(chuàng)建相應(yīng)的派生類對象,也可用下列方法來實(shí)現(xiàn):
voidmain() { CShape*p1,*p2;
CTriangletri(3,4); CCirclecir(5); p1=&tri;
p2=○ cout<<p1->area()<<endl; cout<<p2->area()<<endl;}
(4)
虛函數(shù)必須是類的一個(gè)成員函數(shù),不能是友元函數(shù),不能是靜態(tài)的成員函數(shù)。
(5)可把析構(gòu)函數(shù)定義為虛函數(shù),但不能將構(gòu)造函數(shù)定義為虛函數(shù)。通常在釋放基類及其派生類中的動態(tài)申請的存儲空間時(shí),也要把析構(gòu)函數(shù)定義為虛函數(shù),以便實(shí)現(xiàn)撤銷對象時(shí)的多態(tài)性。
3.1多態(tài)和虛函數(shù)3.1.2純虛函數(shù)和抽象類
定義一個(gè)基類時(shí),會遇到這樣的情況:無法定義基類中虛函數(shù)的具體實(shí)現(xiàn),其實(shí)現(xiàn)完全依賴於其不同的派生類。例如,一個(gè)“形狀類”由於沒有確定的具體形狀,因此其計(jì)算面積的函數(shù)也就無法實(shí)現(xiàn)。這時(shí)可將基類中的虛函數(shù)聲明為純虛函數(shù)。
聲明純虛函數(shù)的一般格式為:
virtual<函數(shù)類型><函數(shù)名>(<形數(shù)表>)=0;它與一般虛函數(shù)不同的是:在純虛函數(shù)的形參表後面多了個(gè)“=0”。把函數(shù)名賦於0,本質(zhì)上是將指向函數(shù)的指針的初值賦為0。需要說明的是,純虛函數(shù)不能有具體的實(shí)現(xiàn)代碼。
抽象類是指至少包含一個(gè)純虛函數(shù)的特殊的類。它本身不能被實(shí)例化,也就是說不能聲明一個(gè)抽象類的對象。必須通過繼承得到派生類後,在派生類中定義了純虛函數(shù)的具有實(shí)現(xiàn)代碼,才能獲得一個(gè)派生類的對象。與虛函數(shù)使用方法相同,也可以聲明指向抽象類的指針,雖然該指針不能指向任何抽象類的對象,但可以通過該指針獲得對派生類成員函數(shù)的調(diào)用。事實(shí)上,純虛函數(shù)是一個(gè)特殊的虛函數(shù)。
3.2運(yùn)算符重載
3.2.1運(yùn)算符重載的語法
<函數(shù)類型><類名>::operator<重載的運(yùn)算符>(<形參表>) {…} //函數(shù)體 運(yùn)算符重載函數(shù)的函數(shù)是以特殊的關(guān)鍵字operator開始的,因而編譯器很容易與其他的函數(shù)名區(qū)分開來。
重載的運(yùn)算符必須是合法的運(yùn)算符。說明:(1)
當(dāng)用成員函數(shù)實(shí)現(xiàn)雙目運(yùn)算符的重載時(shí),運(yùn)算符的左運(yùn)算元一定是對象,右運(yùn)算元作為調(diào)用運(yùn)算符重載函數(shù)的參數(shù),參數(shù)可以是對象、對象的引用或是其他類型的參數(shù)。(2)
不是所有的運(yùn)算符都可以重載。不允許重載的運(yùn)算符除三目運(yùn)算符“?:”外,還有成員操作符“.”、成員指針取值操作符“*”、作用域操作符“::”以及sizeof運(yùn)算符。(3)
只能對已定義了的運(yùn)算符進(jìn)行重載,而且當(dāng)重載一個(gè)運(yùn)算符時(shí),該運(yùn)算符的運(yùn)算元個(gè)數(shù)、優(yōu)先順序和結(jié)合性是不能改變的。[例Ex_Complex]運(yùn)算符的簡單重載。#include<iostream.h>classCComplex{ public: CComplex(doubler=0,doublei=0) { realPart=r; imagePart=i;}
voidprint() { cout<<"該複數(shù)實(shí)部=“<<realPart<<",虛部=“<<imagePart<<endl; } CComplexoperator+(CComplex&c);
CComplexoperator+(doubler);
private:
doublerealPart; doubleimagePart; };
CComplexCComplex::operator+(CComplex&c){ CComplextemp; temp.realPart=realPart+c.realPart; temp.imagePart=imagePart+c.imagePart; returntemp;}CComplexCComplex::operator+(doubler) { CComplextemp; temp.realPart=realPart+r; temp.imagePart=imagePart; returntemp;}voidmain(){ CComplexc1(12,20),c2(50,70),c; c=c1+c2; c.print(); c=c1+20; c.print();}
對運(yùn)算符“+”作了兩次重載,一個(gè)用於實(shí)現(xiàn)兩個(gè)複數(shù)的加法,另一個(gè)用於實(shí)現(xiàn)一個(gè)複數(shù)與一個(gè)實(shí)數(shù)的加法。當(dāng)重載一個(gè)運(yùn)算符時(shí),必須定義該運(yùn)算符要完成的具體操作,而且當(dāng)運(yùn)算符重載函數(shù)是類的成員函數(shù)時(shí),該函數(shù)的形參個(gè)數(shù)要比運(yùn)算符運(yùn)算元個(gè)數(shù)少一個(gè),雙目運(yùn)算符重載的成員函數(shù)只有一個(gè)參數(shù),單目運(yùn)算符重載的成員函數(shù)沒有參數(shù)。
3.2運(yùn)算符重載3.2.2賦值運(yùn)算符的重載
對象的成員中有數(shù)組或動態(tài)的數(shù)據(jù)類型時(shí),就不能直接相互賦值,否則在程式的編譯或執(zhí)行過程中出現(xiàn)編譯或運(yùn)行錯(cuò)誤。例如:
classCdemo { public:
CDemo(char*s) { ps=newchar[strlen(s)+1]; strcpy(ps,s); }
~CDemo() { if(ps)delete[]ps; } voidprint() {
cout<<ps<<endl; } private: char*ps; };
voidmain(){ CDemod1("Key"),d2("Mouse"); d1=d2; }
程式運(yùn)行到“d1=d2”時(shí)發(fā)生運(yùn)行錯(cuò)誤。因此,必須重載“=”運(yùn)算符,它與其他運(yùn)算符的重載相同。
3.2運(yùn)算符重載[例Ex_Evaluate]賦值運(yùn)算符的重載。#include<iostream.h>#include<string.h>classCDemo{ public: //同上面的相同部分代省略
CDemo&operator=(CDemo&a) { if(ps)delete[]ps; if(a.ps){ ps=newchar[strlen(a.ps)+1]; strcpy(ps,a.ps);} elseps=0; return*this; } private: char*ps; };voidmain(){ CDemod1("Key"),d2("Mouse"); d1=d2; d1.print(); }
運(yùn)行結(jié)果為: Mouse賦值運(yùn)算符不能重載為友元函數(shù),只能是一個(gè)非靜態(tài)成員函數(shù)。
3.2運(yùn)算符重載3.2.3提取和插入運(yùn)算符重載
C++允許用戶重載“>>”和“<<”運(yùn)算符,以便用戶利用標(biāo)準(zhǔn)的輸入輸出流來輸入輸出自己定義的數(shù)據(jù)類型(包括類),實(shí)現(xiàn)對象的輸入輸出。 重載這兩個(gè)運(yùn)算符時(shí)最好將重載聲明為類的友元函數(shù),以便訪問類中的私有成員。
友元重載的一般格式如下:
friend<函數(shù)類型>operator<重載的運(yùn)算符>(<形參>) //單目
{…} friend<函數(shù)類型>operator<重載的運(yùn)算符>(<形參1,形數(shù)2)//雙目
{…} 對於單目運(yùn)算符的友元重載函數(shù),只有一個(gè)形參,形參類型可以是類的對象,可以是引用,這取決於不同的運(yùn)算符。對於雙目運(yùn)算符的友元重載函數(shù)來說,它有兩個(gè)形參,這兩個(gè)形參中必須有一個(gè)是類的對象。需要說明的是,=、()、[]和->運(yùn)算符不能用友元來重載。
3.2運(yùn)算符重載[例Ex_ExtractAndInsert]提取和插入運(yùn)算符的重載。
#include<iostream.h> classCStudent { public: friendostream&operator<<(ostream&os,CStudent&stu); friendistream&operator>>(istream&is,CStudent&stu);
private: charstrName[10]; //姓名
charstrID[10]; //學(xué)號
floatfScore[3]; //三門成績
};ostream&operator<<(ostream&os,CStudent&stu){ os<<endl<<"學(xué)生資訊如下:"<<endl; os<<"姓名:"<<stu.strName<<endl; os<<"學(xué)號:"<<stu.strID<<endl; os<<"成績:"<<stu.fScore[0]<<",\t" <<stu.fScore[1]<<",\t" <<stu.fScore[2]<<endl; returnos;}istream&operator>>(istream&is,CStudent&stu){ cout<<"請輸入學(xué)生資訊"<<endl; cout<<"姓名:"; is>>stu.strName; cout<<"學(xué)號:"; is>>stu.strID; cout<<"三門成績:"; is>>stu.fScore[0]>>stu.fScore[1]>>stu.fScore[2]; returnis; }voidmain(){ CStudentone; cin>>one; cout<<one; }3.3輸入輸出流庫
3.3.1概述
輸入輸出操作是由“流”來處理的。數(shù)據(jù)從一個(gè)位置到另一個(gè)位置的流動抽象為“流”。當(dāng)流被建立後就可以使用一些特定的操作從流中獲取數(shù)據(jù)或向流中添加數(shù)據(jù)。從流中獲取數(shù)據(jù)的操作稱為“提取”操作,向流中添加數(shù)據(jù)的操作稱為“插入”操作。
ios類提供對流狀態(tài)進(jìn)行設(shè)置的功能,是虛基類,其他類都是從這個(gè)派生而來的。
streambuf不是ios類的派生類,在類ios中只是有一個(gè)指針成員,指向streambuf類的一個(gè)對象。streambuf類是用來為ios類及其派生類提供對數(shù)據(jù)的緩衝支持。itream和ostream類是ios的公有派生類,前者向流中插入數(shù)據(jù)的有關(guān)操作,後者從流中提取數(shù)據(jù)的有關(guān)操作。iostream類是itream和ostream類公有派生的。
四個(gè)預(yù)定義的標(biāo)準(zhǔn)流對象:cin、cout、cerr和clog。當(dāng)用戶在程式中包含了頭檔“iostream.h”,編譯器調(diào)用相應(yīng)的構(gòu)造函數(shù),產(chǎn)生這四個(gè)標(biāo)準(zhǔn)流對象,用戶在程式中就可以直接使用它們了。其中,cin是istream類的對象,用處理標(biāo)準(zhǔn)輸入cout是ostream類的對象,用處理標(biāo)準(zhǔn)輸出。cerr和clog都是ostream類的對象,用來處理標(biāo)準(zhǔn)出錯(cuò)資訊,並將資訊顯示在螢?zāi)簧?。在這四個(gè)標(biāo)準(zhǔn)流對象中,除了cerr不支持緩衝外,其餘三個(gè)都帶有緩衝區(qū)。標(biāo)準(zhǔn)流通常使用提取運(yùn)算符“>>”和插入運(yùn)算符“<<”來進(jìn)行輸入輸出操作的,而且系統(tǒng)還會自動地完成數(shù)據(jù)類型的轉(zhuǎn)換。
3.3輸入輸出流庫3.3.2cout和cin輸出流(cout)
cout可以輸出一個(gè)整數(shù)、實(shí)數(shù)、字元及字串,cout中的插入符“<<”可以連續(xù)寫多個(gè),每個(gè)後面可以跟一個(gè)要輸出的常量、變數(shù)、轉(zhuǎn)義序列符、對象以及運(yùn)算式等。
(1)
width函數(shù) 格式:intwidth(); intwidth(int);
第一種格式用來獲取當(dāng)前輸出數(shù)據(jù)時(shí)的寬度。另一種格式是用來設(shè)置當(dāng)前輸出數(shù)據(jù)時(shí)的寬度。 (2)
precision函數(shù) 格式:intprecision(); intprecision(int);
這兩種格式分別用來獲取和設(shè)置當(dāng)前浮點(diǎn)數(shù)的有效數(shù)字的個(gè)數(shù),第二種格式函數(shù)還將返回設(shè)置前的有效數(shù)字的個(gè)數(shù)。需要說明的是,C++默認(rèn)的有效數(shù)字的個(gè)數(shù)為6。
(3)
fill函數(shù) 格式:charfill(); charfill(char);
這兩種格式分別用來獲取和設(shè)置當(dāng)前寬度內(nèi)的填充字元,第二種格式函數(shù)還將返回設(shè)置前的填充字元。
3.3輸入輸出流庫輸入流(cin)
格式: cin>><運(yùn)算式1>[>><運(yùn)算式2>...]
提取符“>>”可以連續(xù)寫多個(gè),每個(gè)後面跟一個(gè)運(yùn)算式,該運(yùn)算式通常是獲得輸入值的變數(shù)或?qū)ο蟆?/p>
intx1,x2,x3;cin>>x1>>x2>>x3;
要求用戶從鍵盤上輸入三個(gè)整數(shù)。輸入時(shí),必須在三個(gè)數(shù)值之間加上一些空格來分隔,空格的個(gè)數(shù)不限,最後用回車鍵結(jié)束輸入;或者在每個(gè)數(shù)值之後按回車鍵。格式算子oct、dec和hex
格式算子oct、dec和hex能分別將輸入或輸出的數(shù)值轉(zhuǎn)換成八進(jìn)制、十進(jìn)位及十六進(jìn)制。3.3輸入輸出流庫
輸入輸出過程中發(fā)現(xiàn)操作錯(cuò)誤,流就會將發(fā)生的錯(cuò)誤記錄下來。用戶可以使用錯(cuò)誤檢測功能,檢測和查明錯(cuò)誤發(fā)生的原因和性質(zhì),然後調(diào)用clear函數(shù)清除錯(cuò)誤狀態(tài),使流能夠恢復(fù)處理。
在ios類中,定義了一個(gè)公有枚舉成員io_state來記錄各種錯(cuò)誤的性質(zhì):
enumio_state{ goodbit =0x00, //正常
eofbit =0x01, //已達(dá)到檔尾
failbit =0x02, //操作失敗
badbit =0x04 //非法操作}; 在ios類中又定義了檢測上述流狀態(tài)的下列成員函數(shù):
int ios::rdstate(); //返回當(dāng)前的流狀態(tài)
intios::bad(); //如果badbit位被置位,返回非0 void ios::clear(int); //清除錯(cuò)誤狀態(tài)
intios::eof(); //返回非0表示提取操作已到檔尾
intios::fail(); //如果failbit位被置位,返回非0 int
ios::good
();//操作正常時(shí),返回非0
floatres;charbuf[80];cin>>res; ints=cin.rdstate(); while(s) { cin.clear(); cin.getline(buf,80); cout<<"錯(cuò)誤輸出"<<endl; cin>>res; s=cin.rdstate();
//cout<<"流的狀態(tài):"<<hex<<s<<endl;
}3.3輸入輸出流庫3.3.4使用輸入輸出成員函數(shù)
輸入操作的成員函數(shù)
數(shù)據(jù)的輸入/輸出可以分為三大類:字元類、字串和數(shù)據(jù)。
(1)使用get和getline函數(shù)
intget(); istream&get(char&rch); istream&get(char*pch,intnCount,chardelim='\n');
getline函數(shù)原型如下:
istream&getline(char*pch,intnCount,chardelim='\n'); (2)使用read函數(shù)
istream&read(char*pch,intnCount); istream&read(unsignedchar*puch,intnCount); istream&read(signedchar*psch,intnCount); read函數(shù)的這幾種形式都是從輸入流中讀取由nCount指定數(shù)目的位元組並將它們放在由pch或puch或psch指定的數(shù)組中。輸出操作的成員函數(shù)
ostream&put(charch); ostream&write(constchar*pch,intnCount); ostream&write(constunsignedchar*puch,intnCount); ostream&write(constsignedchar*psch,intnCount);3.3輸入輸出流庫3.3.5檔流概述
檔看作是由連續(xù)的字元的數(shù)據(jù)順序組成。根據(jù)檔中數(shù)據(jù)的組織方式,可分為文本檔和二進(jìn)位檔。文本檔中每一個(gè)位元組用以存放一個(gè)字元的ASCII碼值,二進(jìn)位檔是將數(shù)據(jù)用二進(jìn)位形式存放在檔中。
一個(gè)檔指針總是和一個(gè)檔所關(guān)聯(lián)的,在檔每一次打開時(shí),檔指針指向檔的開始,隨著對檔的處理,檔指針不斷地在檔中移動,並一直指向最新處理的字元(位元組)位置。檔處理方式,一種稱為檔的順序處理。另一種稱為檔的隨機(jī)處理,並指向所要處理的字元(位元組)位置。按照這兩種處理方式,可將檔相應(yīng)地稱為順序檔和隨機(jī)檔。3.3輸入輸出流庫3.3.6順序檔操作
檔的打開和關(guān)閉
聲明一個(gè)ifstream、ofstream或fstream類對象。
使用檔流類的成員函數(shù)打開或創(chuàng)建一個(gè)指定的檔,使得該檔與聲明的檔流對象聯(lián)繫起來,這樣對流對象的操作也就是對檔的操作。
ifstream、ofstream或fstream類構(gòu)造函數(shù)中總有一種原型和它的成員函數(shù)open功能相同。它們的函數(shù)原型如下:
ifstream(constchar*szName,intnMode=ios::in,intnProt=filebuf::openprot); voidifstream::open(constchar*szName,intnMode=ios::in,intnProt=filebuf::openprot);
ofstream(constchar*szName,intnMode=ios::out,intnProt=filebuf::openprot); voidofstream::open(constchar*szName,intnMode=ios::out,intnProt=filebuf::openprot);
fstream(constchar*szName,intnMode,intnProt=filebuf::openprot); voidfstream::open(constchar*szName,intnMode,intnProt=filebuf::openprot);3.3輸入輸出流庫檔的讀寫
[例Ex_File]將檔內(nèi)容保存在另一檔中,並將內(nèi)容顯示在螢?zāi)簧稀?/p>
#include<iostream.h> #include<fstream.h>
voidmain() { fstreamfile1; file1.open("Ex_DataFile.txt",ios::in); if(!file1) { cout<<"Ex_DataFile.txt不能打開!\n"; return;}
fstreamfile2; file2.open("Ex_DataFileBak.txt",ios::out|ios::trunc); if(!file2) { cout<<"Ex_DataFileBak.txt不能創(chuàng)建!\n"; file1.close(); return; }
charch; while(!file1.eof()) { file1.read(&ch,1); cout<<ch; file2.write(&ch,1); } file2.close(); file1.close();}3.3輸入輸出流庫3.3.7隨機(jī)檔操作 隨機(jī)檔可以在檔中來回移動檔指針,從而可以實(shí)現(xiàn)非順序讀寫檔數(shù)據(jù)的功能,達(dá)到快速檢索、修改和刪除檔數(shù)據(jù)的效果。
seekg和seekp函數(shù)將檔指針移動到指定的位置。它們的原型如下:
istream&seekg(longpos); istream&seekg(longoff,ios::seek_dirdir); ostream&seekp(longpos); ostream&seekp(longoff,ios::seek_dirdir);
其中,pos用來指定檔指針的絕對位置。若用off指定檔指針的相對偏移量時(shí),檔指針的最終位置還需根據(jù)dir值才能確定。dir值可以是:
ios::beg 從檔流的頭部開始
ios::cur 從當(dāng)前的檔指針位置開始
ios::end
從檔流的尾部開始
3.4範(fàn)本
3.4.1函數(shù)重載機(jī)制的不足
函數(shù)重載方便用戶對函數(shù)名的記憶,完善了同一個(gè)函數(shù)的代碼功能。允許多個(gè)同名的函數(shù)存在,同名的各個(gè)函數(shù)的形參必須有區(qū)別:形參的個(gè)數(shù)不同,或者形參的個(gè)數(shù)相同,但形參類型有所不同。 如果需要處理所有標(biāo)準(zhǔn)數(shù)據(jù)類型的參數(shù),則還需要更多的代碼進(jìn)行函數(shù)重載??梢钥闯龊瘮?shù)重載有時(shí)也顯得比較煩瑣,解決這個(gè)問題就是使用函數(shù)範(fàn)本。3.4.2函數(shù)範(fàn)本
格式:
template<數(shù)據(jù)類型聲明>
函數(shù)體
template是一個(gè)聲明範(fàn)本的關(guān)鍵字,數(shù)據(jù)類型聲明是使用class關(guān)鍵字來定義類型名稱,而函數(shù)體與傳統(tǒng)的函數(shù)定義相似。3.4範(fàn)本[例Ex_FunTemplate]使用函數(shù)範(fàn)本。
#include<iostream.h> template<classT> Tsum(Tx,Ty,Tz) { returnx+y+z; }
template<classT,classT1> //定義第二個(gè)函數(shù)範(fàn)本
Tsum(Tx,T1y) { returnx+y; }
voidmain() { cout<<sum(2,'a')<<endl; cout<<sum('a',2)<<endl; cout<<sum(2,5,7)<<endl; cout<<sum(1.2,5.0,7.5)<<endl; }
3.4範(fàn)本3.4.3類範(fàn)本
template<數(shù)據(jù)類型聲明>class類名
{ ... //成員的定義
}; 注意:大括弧後的分號不能省略。3.4.4標(biāo)準(zhǔn)範(fàn)本庫簡介
標(biāo)準(zhǔn)範(fàn)本庫STL(StandardTemplateLibrary)是通過STL中的相應(yīng)運(yùn)算法則在應(yīng)用程式的迭代子(iterator)、容器以及其他定義的序列中建立一種統(tǒng)一的標(biāo)準(zhǔn)。從根本上來說,STL是一個(gè)基於範(fàn)本的群體類庫,它包含群體類(鏈表或列表、向量、棧、佇列、集合、映象)、演算法(排序、查找)以及迭代子。
STL中的群體類是基於範(fàn)本的,包含線性群體類,也包含非線性群體類。其主要群體類有:
deque(雙端佇列) list(鏈表、列表) map(映象) multimap(多重映象)
multiset(多重集合) set(集合) vector(向量)3.4範(fàn)本
STL的迭代子有順序和直接訪問,順序迭代子使用++、--等進(jìn)行指針移動,只能順序訪問群體類中的對象,而直接訪問迭代子是通過iterator_traits來直接訪問群體類中的某個(gè)特定對象。iterator_traits用來指定要訪問的屬性類型,它可以有:
iterator_category(目錄類型) value_type(數(shù)值類型) difference_type(距離類型,表示兩個(gè)指針的地址之間的距離) pointer(指針類型) reference(引用類型)
STL的演算法是用函數(shù)範(fàn)本實(shí)現(xiàn)的,可以實(shí)現(xiàn)對不同類型對象的通用操作。演算法與STL群體類之間是通過迭代子iterator來進(jìn)行溝通的。STL的主要演算法有: 排序(sort、merge)
查找(find、search)
比較(equal)
集合(includes、set_union、set_difference)
計(jì)算(accumulate、partial_sum)
統(tǒng)計(jì)(max、min)
管理(swap、fill、replace、copy、unique、rotate、reverse)
堆操作(make_heap、push_heap、pop_heap、sort_heap)
對話框
4.1從C++到Windows編程
4.1.1簡單的Windows應(yīng)用程式
[例Ex_HelloMsg]一個(gè)最簡單的Windows應(yīng)用程式。
(1)選擇“檔”
“新建”菜單命令,顯示出“新建”對話框。單擊“工程”標(biāo)籤,從列表框中選中Win32Application(Win32應(yīng)用程式)項(xiàng)。
(2)在工程名稱框中鍵入Win32應(yīng)用程式專案名稱Ex_HelloMsg。在“位置”下的編輯框中直接鍵入檔夾名稱,或單擊流覽按鈕(...)選擇一個(gè)已有的檔夾。
(3)單擊[確定]按鈕繼續(xù)。一個(gè)詢問專案類型的Win32應(yīng)用程式嚮導(dǎo)將被顯示,選中Anemptyproject項(xiàng)。單擊[完成]按鈕,系統(tǒng)將顯示AppWizard的創(chuàng)建資訊,單擊[確定]按鈕系統(tǒng)將自動創(chuàng)建此應(yīng)用程式。
4.1從C++到Windows編程(4)再次選擇“檔”
“新建”菜單命令,顯示出“新建”對話框。單擊“檔”標(biāo)籤,在左邊的列表框中選擇C++SourceFile項(xiàng),在右邊的“檔”下的編輯框中鍵入Ex_HelloMsg.cpp,單擊[確定]按鈕。
(5)
輸入下麵的代碼:
#include<windows.h> intWINAPIWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,LPSTRlpCmdLine,intnCmdShow) { MessageBox(NULL,"你好,我的VisualC++世界!","問候",0);return0; }4.1從C++到Windows編程
WinMain函數(shù)的原型如下:
intWINAPIWinMain( HINSTANCEhInstance, //當(dāng)前實(shí)例句柄
HINSTANCEhPrevInstance, //前一實(shí)例句柄
LPSTRlpCmdLine, //指向命令行參數(shù)的指針
intnCmdShow) //窗口的顯示狀態(tài) 這裏出現(xiàn)了一個(gè)新的概念——“句柄”(handle),所謂句柄是一個(gè)標(biāo)識Windows資源和設(shè)備等對象的變數(shù),或者是一個(gè)對操作系統(tǒng)資源的間接引用。每一個(gè)用C/C++編寫的Windows應(yīng)用程式都需要Windows.h頭檔,它還包含了其他的一些Windows頭檔。這些頭檔定義了Windows的所有數(shù)據(jù)類型、函數(shù)調(diào)用、數(shù)據(jù)結(jié)構(gòu)和符號常量。程式中,MessageBox是一個(gè)Win32API(ApplicationProgrammingInterface,應(yīng)用程式介面)函數(shù),用來彈出一個(gè)對話框窗口,顯示短資訊。該函數(shù)第一個(gè)參數(shù)用來指定父窗口句柄,即對話框所在的窗口句柄。第二、三個(gè)參數(shù)分別用來指定顯示的消息內(nèi)容和對話框窗口的標(biāo)題,最後一個(gè)參數(shù)用來指定在對話框中顯示的按鈕。
4.1從C++到Windows編程4.1.2Windows編程特點(diǎn)
Windows應(yīng)用程式具有這樣的一些特性:消息驅(qū)動機(jī)制、圖形設(shè)備介面(GDI)、基於資源的程式設(shè)計(jì)、動態(tài)鏈接庫。消息驅(qū)動機(jī)制
DOS程式是通過調(diào)用系統(tǒng)的函數(shù)來獲得用戶輸入的,Windows程式是通過操作系統(tǒng)發(fā)送的消息來處理用戶輸入的。消息驅(qū)動的機(jī)制是Windows編程的最大特點(diǎn)。
WinMain函數(shù)通常要完成以下幾步工作:
定義並調(diào)用API函數(shù)RegisterClass註冊應(yīng)用程式的窗口類。
調(diào)用相關(guān)API函數(shù)創(chuàng)建和顯示窗口,並進(jìn)行其他必要的初始化處理。其中,函數(shù)CreateWindow用來創(chuàng)建已註冊窗口類的窗口。創(chuàng)建和啟動應(yīng)用程式的消息迴圈。Windows應(yīng)用程式接受各種不同的消息,包括鍵盤消息、滑鼠以及窗口產(chǎn)生的各種消息。Windows系統(tǒng)首先將消息放入消息佇列中,應(yīng)用程式的消息迴圈就是從應(yīng)用程式的消息佇列中檢取消息,並將消息發(fā)送相應(yīng)的窗口過程函數(shù)中作進(jìn)一步處理。API函數(shù)GetMessage和DispatchMessage就是起到這樣的作用。如果接收到WM_QUIT消息,則退出應(yīng)用程式。4.1從C++到Windows編程圖形設(shè)備介面(GDI)
Windows提供了一個(gè)抽象的圖形設(shè)備介面(GraphicalDeviceInterface,簡稱GDI),使用戶直接利用系統(tǒng)的GDI函數(shù)就能方便實(shí)現(xiàn)圖形和文本的輸出,而不必關(guān)心與系統(tǒng)相連的外部設(shè)備的類型。
基於資源的程式設(shè)計(jì)
Windows應(yīng)用程式常常包含眾多圖形元素。每一個(gè)這樣的資源都用相應(yīng)的識別字來區(qū)分,而且Windows內(nèi)部也有預(yù)定義的資源。在Windows環(huán)境下,每一個(gè)資源元素都作為一種可以裝入應(yīng)用程式的資源來存放。這些資源可以被編輯、修改,也可以被其他應(yīng)用程式所共用。動態(tài)鏈接庫
動態(tài)鏈接庫提供一些特定結(jié)構(gòu)的函數(shù),能被應(yīng)用程式在運(yùn)行過程中裝入和連接,且多個(gè)程式可以共用同一個(gè)動態(tài)鏈接庫。
Windows提供了應(yīng)用程式可調(diào)用的豐富的函數(shù),大多數(shù)用於實(shí)現(xiàn)其用戶介面和在顯示器上顯示的文本和圖形,都是通過動態(tài)鏈接庫來實(shí)現(xiàn)的。這些動態(tài)鏈接庫是一些具有DLL擴(kuò)展名或者有時(shí)是EXE擴(kuò)展名的檔。在Windows操作系統(tǒng)中,最主要的DLL有KERNEL32.DLL、GDI32.DLL和USER32.DLL。其中,KERNEL32.DLL用來處理記憶體低層功能、任務(wù)和資源管理等Windows核心服務(wù);GDI32.DLL用來提供圖形設(shè)備介面,管理用戶介面和圖形繪製,包括Windows元檔、位圖、設(shè)備描述表和字體等;而USER32.DLL負(fù)責(zé)窗口的管理,包括消息、菜單、游標(biāo)、計(jì)時(shí)器以及其他與控制窗口顯示相關(guān)的一些功能。4.1從C++到Windows編程4.1.3Windows基本數(shù)據(jù)類型
4.1從C++到Windows編程4.1.4MFC應(yīng)用程式框架類型
MFC把編程規(guī)範(fàn)中的大多數(shù)內(nèi)容封裝成為各種類,使程式員從繁雜的編程中解脫出來。VisualC++還提供大量的嚮導(dǎo)和可視化編輯工具,使得用戶不需要添加太多的代碼就能實(shí)現(xiàn)不同風(fēng)格和用途的應(yīng)用程式。
MFCAppWizard就是VisualC++6.0提供的一個(gè)非常有用的嚮導(dǎo),它能為用戶快速、高效、自動地生成一些常用的標(biāo)準(zhǔn)程式結(jié)構(gòu)和編程風(fēng)格。
MFCAppWizard(exe)應(yīng)用程式框架包含用戶最常用、最基本的三種應(yīng)用程式類型:單文檔、多文檔和基於對話框的應(yīng)用程式。單文檔應(yīng)用程式每次只能打開和處理一個(gè)文檔對話框的程式?jīng)]有菜單、工具欄及狀態(tài)欄,也不能處理文檔,但它的好處是速度快,代碼少,程式員所花費(fèi)的開發(fā)和調(diào)試時(shí)間短。多文檔應(yīng)用程式,能允許同時(shí)打開和處理多個(gè)文檔。與單文檔應(yīng)用程式相比,增加了許多功能,因而需要大量額外的編程工作。4.1從C++到Windows編程表4.2MFCAppWizard創(chuàng)建的應(yīng)用程式類型
4.1從C++到Windows編程4.1.5創(chuàng)建一個(gè)應(yīng)用程式框架
[例Ex_SDI]創(chuàng)建一個(gè)默認(rèn)的單文檔應(yīng)用程式。
開始 選擇“檔”
“新建”菜單,在彈出的“新建”對話框中選擇“工程”標(biāo)籤,這時(shí)顯示出一系列的應(yīng)用程式專案類型;選擇MFCAppWizard(exe)的專案類型(該類型用於創(chuàng)建可執(zhí)行的Windows應(yīng)用程式),將專案工作檔夾定位在“…\VisualC++6.0程式\對話框”,並在工程框中輸入專案名Ex_SDI。
4.1從C++到Windows編程選擇程式類型 單擊[確定]按鈕,進(jìn)行下列選擇:(1)
從應(yīng)用程式類型單個(gè)文檔(SingleDocument,簡稱SDI)、多重文檔(MultipleDocument,簡稱MDI)和基本對話(DialogBased,基於對話框的應(yīng)用程式)中選擇“單個(gè)文檔”。(2)
決定應(yīng)用程式中是否需要MFC的文檔視圖(“文檔/查看體系結(jié)構(gòu)支持”)結(jié)構(gòu)的支持。若不選定此項(xiàng),則程式中的磁片檔的打開、保存以及文檔和視圖的相互作用等功能需要用戶來實(shí)現(xiàn)。一般情況下,應(yīng)選中此項(xiàng)。(3)選擇資源所使用的語言,這裏是“中文[中國]”。4.1從C++到Windows編程簡單創(chuàng)建
保留默認(rèn)的選項(xiàng),單擊[完成]按鈕,顯示出用戶在步驟中作出的選擇,單擊[確定]按鈕系統(tǒng)開始創(chuàng)建。
4.1從C++到Windows編程編譯並運(yùn)行
到這裏為止,用戶雖然沒有編寫任何程式代碼,但MFCAppWizard已經(jīng)根據(jù)用戶的選擇內(nèi)容自動生成基本的應(yīng)用程式框架。單擊編譯工具條 上的運(yùn)行工具按鈕“”或按快捷鍵Ctrl+F5,系統(tǒng)開始編連並運(yùn)行生成的單文檔應(yīng)用程式可執(zhí)行檔Ex_SDI.exe。
4.2添加並使用對話框
4.2.1資源與資源標(biāo)識
資源的分類
將上例Ex_SDI的專案工作區(qū)窗口切換到“ResourceView”頁面。
資源可分為下列幾類:
(1)快捷鍵列表(Accelerator):一系列組合鍵的集合,被應(yīng)用程式用來引發(fā)一個(gè)動作。該列表一般與菜單命令相關(guān)聯(lián),用來代替滑鼠操作。
(2)對話框(Dialog):含有按鈕、列表框、編輯框等各種控件的窗口。
(3)圖示(Icon):代表應(yīng)用程式顯示在Windows桌面上的位圖,它同時(shí)有32
32像素和16
16像素兩種規(guī)格。
(4)菜單(Menu):用戶通過菜單可完成應(yīng)用程式的大部分操作。 (5)字串表(StringTable):應(yīng)用程式使用的全局字串或其他識別字。
(6)工具欄按鈕(Toolbar):工具欄外觀是以一系列具有相同尺寸的位圖組成的,它通常與一些菜單命令項(xiàng)相對應(yīng),用以提高用戶的工作效率。
(7)版本資訊(Version):包含應(yīng)用程式的版本、用戶註冊碼等相關(guān)資訊。
4.2添加並使用對話框識別字
每一個(gè)資源類別下都有一個(gè)或多個(gè)相關(guān)資源,每一個(gè)資源均是由識別字來定義的。當(dāng)添加或創(chuàng)建一個(gè)新的資源或資源對象時(shí),系統(tǒng)會為其提供默認(rèn)的名稱,如IDR_MAINFRAME等。用戶可重新命名,但要按一定的規(guī)則來進(jìn)行。一般地,要遵循下列規(guī)則:
(1)
在識別字名稱中允許使用字母a~z、A~Z、0~9以及下劃線。
(2)
識別字名稱不區(qū)分大小寫字母,如new_idd與New_Idd是相同的識別字。
(3)
不能以數(shù)字開頭,如8BIT是不合法的識別字名。
(4)
字元個(gè)數(shù)不得超過247個(gè)。4.2添加並使用對話框4.2.2添加對話框資源
添加對話框資源一般可按下列步驟(在上例Ex_SDI基礎(chǔ)上進(jìn)行):
(1)選擇“插入”
“資源”菜單,或按快捷鍵Ctrl+R打開“插入資源”對話框,在對話框中可以看到資源列表中存在Dialog項(xiàng),若單擊Dialog項(xiàng)左邊的“+”號,將展開對話框資源的不同類型選項(xiàng)。
4.2添加並使用對話框
(2)對展開的不同類型的對話框資源不作任何選擇,選中“Dialog”,單擊[新建]按鈕,系統(tǒng)就會自動為當(dāng)前應(yīng)用程式添加了一個(gè)對話框資源。
系統(tǒng)為對話框資源自動賦給它一個(gè)默認(rèn)的識別字名稱(第一次為IDD_DIALOG1,以後依次為IDD_DIALOG2、IDD_DIALOG3、...)。使用通用的對話框範(fàn)本創(chuàng)建新的對話框資源。對話框的默認(rèn)標(biāo)題為Dialog,有[OK]和[Cancel]兩個(gè)按鈕,這兩個(gè)按鈕的識別字分別為IDOK和IDCANCEL。對話框範(fàn)本資源所在的窗口稱為對話框資源編輯器,在這裏可以通過控件工具欄和佈局工具欄向?qū)υ捒蛱砑雍蛠丫挚丶?,並可設(shè)置對話框的屬性。4.2添加並使用對話框4.2.3設(shè)置對話框?qū)傩?/p>
在對話框範(fàn)本處右擊滑鼠,從彈出的快捷菜單中選擇“屬性”菜單項(xiàng)。
表4.5對話框的General屬性
4.2添加並使用對話框?qū)⑻砑拥膶υ捒虻膶傩赃M(jìn)行如下三點(diǎn)修改:將對話框識別字改成IDD_DIALOG_FIRST;
將對話框標(biāo)題改為“我的第一個(gè)對話框”;單擊[字體]按鈕,通過彈出的字體對話框?qū)υ捒騼?nèi)的文本設(shè)置成“宋體,9”
,以使自己的對話框和Windows中的對話框保持外觀上的一致。
4.2添加並使用對話框4.2.4添加和佈局控件 在對話框中添加一個(gè)控件的方法:在控件工具欄中單擊某控件;在對話框指定位置單擊滑鼠左鍵,則此控件被添加到對話框的相應(yīng)位置,再拖動選擇框可改變控件的大小和位置。在控件工具欄中單擊某控件,此時(shí)的滑鼠箭頭對話框內(nèi)變成“十”字形狀;在指定位置處單擊滑鼠左鍵不放,拖動滑鼠至滿意位置,釋放滑鼠鍵。用滑鼠左鍵點(diǎn)中控件工具欄中的某控件,並按住滑鼠左鍵不放;在移動滑鼠到對話框的指定位置的過程中,用戶會看到一個(gè)虛線框,下麵帶有該控件的標(biāo)記;釋放滑鼠左鍵,新添加的控件立即出現(xiàn)在對話框中。
控件的選擇靜態(tài)文本組框複選框組合框水準(zhǔn)滾動條旋轉(zhuǎn)按鈕滑動條列表視圖標(biāo)籤複合編輯月曆用戶定制工具靜態(tài)圖片編輯框按鈕單選框列表框垂直滾動條進(jìn)展條熱鍵樹形視圖動畫日期選擇IP地址組合框的擴(kuò)展圖4.14控件工具欄和各按鈕含義4.2添加並使用對話框控件的選取
選取單個(gè)控件,則可以下列方法。用滑鼠直接選取。用助記符來選取。用Tab鍵選取。對於多個(gè)控件的選取,可採用下列方法:先在對話框內(nèi)按住滑鼠左鍵不放,拖出一個(gè)大的虛框,然後釋放滑鼠,則被該虛框所包圍的控件都將被選取。先按住Shift鍵不放,然後用滑鼠選取控件,直到所需要的多個(gè)控件選取之後再釋放Shift鍵。若在選取時(shí),對已選取的控件再選取一下,則取消該控件選取。需要注意的是:(1)
一旦單個(gè)控件被選取後,其四周由選擇框包圍著,選擇框上還有幾個(gè)(通常是八個(gè))藍(lán)色實(shí)心小方塊,拖動它可改變控件的大小。(2)多個(gè)控件被選取後,其中只有一個(gè)控件的選擇框有幾個(gè)藍(lán)色實(shí)心小方塊,這個(gè)控件稱為主要控件,而其他控件的選擇框的小方塊是空心的。(b)圖4.15單個(gè)控件和多個(gè)控件的選擇框(a)4.2添加並使用對話框控件的刪除、複製和佈局
與佈局工具相對應(yīng)的菜單命令在“編排”菜單下,而且大部分命令均有相應(yīng)的快捷鍵
圖4.17“編排”菜單命令項(xiàng)4.2添加並使用對話框注意:大多數(shù)佈置控件的命令使用前,都需要用戶選取多個(gè)控件,且“主要控件”起到了關(guān)鍵作用。例如用戶選取多個(gè)控件後,使用“MakeSameSize”命令只改變其他控件的大小,並與“主要控件”的尺寸一致。因此,在多個(gè)控件的佈置過程中,常需要重新設(shè)置“主要控件”。設(shè)置的方法是按住Ctrl或Shift鍵,然後用滑鼠單擊所要指定的控件即可。為了便於用戶在對話框內(nèi)精確定位各個(gè)控件,系統(tǒng)還提供了網(wǎng)格、尺規(guī)等輔助工具。在圖4.16的控件佈局工具欄的最後兩個(gè)按鈕分別用來網(wǎng)格和尺規(guī)的切換。一旦網(wǎng)格顯示,添加或移動控件時(shí)都將自動定位在網(wǎng)格線上。
表4.6“編排”菜單命令的快捷鍵及功能描述
4.2添加並使用對話框測試對話框
“編排”菜單下的Test命令或佈局工具欄上的測試按鈕是用來模擬所編輯的對話框的運(yùn)行情況,幫助用戶檢驗(yàn)對話框是否符合用戶的設(shè)計(jì)要求以及控件功能是否有效等。
操作示例
向?qū)υ捒蛱砑右粋€(gè)靜態(tài)文本控件。一個(gè)靜態(tài)文本控件就是一個(gè)文本標(biāo)籤。 右擊添加的控件,從彈出的快捷菜單中選擇“屬性”。
4.2添加並使用對話框4.2.5創(chuàng)建對話框類
在對話框資源範(fàn)本的空白區(qū)域內(nèi)雙擊滑鼠,彈出對話框,詢問是否為對話框資源創(chuàng)建一個(gè)新類。單擊[OK]按鈕,彈出NewClass對話框。Name框是用來輸入用戶定義的類名,單擊[Change]按鈕可改變默認(rèn)的原始檔案名稱及其在磁片中的位置。從Baseclass框的內(nèi)容看出,用戶對話框類是從基類CDialog派生而來的。在Name框中輸入類名CFirstDlg,單擊[O
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025建筑工程分包合同(2)
- 2025加盟連鎖店合作協(xié)議合同
- 2025國際貿(mào)易合同協(xié)議書標(biāo)準(zhǔn)版范本
- 2025年商業(yè)店鋪裝修合同書及其清單
- 2025年新《勞動法》與《勞動合同法》知識考試題庫(附答案)
- 2024年內(nèi)江市市中區(qū)社會選聘社區(qū)工作者真題
- 2025屆高考數(shù)學(xué)模擬試題(卷)(5)(教師版)
- 呼職院幼兒音樂教學(xué)法教學(xué)大綱、教學(xué)內(nèi)容、教案、試題
- 2025年二手交易電商平臺信用體系建設(shè)與消費(fèi)者權(quán)益保護(hù)創(chuàng)新報(bào)告001
- 紅色革命基地游行業(yè)深度調(diào)研及發(fā)展項(xiàng)目商業(yè)計(jì)劃書
- 醫(yī)學(xué)研究中期進(jìn)展報(bào)告范文
- 塑料零件的快速換模技術(shù)考核試卷
- 律師事務(wù)所調(diào)查報(bào)告范文
- 基于SysML的空中分布式作戰(zhàn)體系建模研究
- 中國糖尿病防治指南(2024版)解讀2
- 《化工過程本質(zhì)安全化評估技術(shù)指南》
- DB51T 1466-2012 馬尾松二元立木材積表、單木出材率表
- 《有機(jī)化學(xué)》課件-第九章 醛和酮
- 文獻(xiàn)管理與信息分析學(xué)習(xí)通超星期末考試答案章節(jié)答案2024年
- 創(chuàng)業(yè)管理實(shí)戰(zhàn)學(xué)習(xí)通超星期末考試答案章節(jié)答案2024年
- 直播助農(nóng)創(chuàng)業(yè)計(jì)劃書
評論
0/150
提交評論