版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
C++基礎(chǔ)
2.1類和對(duì)象
2.1.1從結(jié)構(gòu)到類
2.1.2類的定義
一般地分為聲明部分和實(shí)現(xiàn)部分。聲明部分是用來(lái)聲明該類中的成員,含數(shù)據(jù)成員和成員函數(shù)的聲明。成員函數(shù)是用來(lái)對(duì)數(shù)據(jù)成員進(jìn)行操作的。實(shí)現(xiàn)部分是用來(lái)對(duì)成員函數(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ù)來(lái)描述的,因此數(shù)據(jù)成員又可稱為“成員變數(shù)”。
public和private聲明了類中的成員和程式其他部分的關(guān)係。對(duì)於public類成員來(lái)說(shuō),它們是公有的,能被外面的程式訪問(wèn);對(duì)於private類成員來(lái)說(shuō),它們是私有的,只能由類中的函數(shù)所使用,而不能被外面的程式所訪問(wèn)。
<各個(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)算符“::”來(lái)通知編譯系統(tǒng)該函數(shù)所屬的類。
2.1類和對(duì)象
定義類時(shí)還應(yīng)注意:(1)
在“public:”或“private:”後面定義的所有成員都是公有或私有的,直到下一個(gè)“public:”或“private:”出現(xiàn)為止。若成員前面沒(méi)有類似“public:”或“private:”,則所定義的成員是private(私有),這是類的默認(rèn)設(shè)置。(2)
關(guān)鍵字public和private可以在類中出現(xiàn)多次,且前後的順序沒(méi)有關(guān)係。但最好先聲明公有成員,後聲明私有成員,因?yàn)閜ublic成員是用戶最關(guān)心的。(3)
除了public和private外,關(guān)鍵字protected(保護(hù))也可修飾成員的類型,它與private兩者基本相似,但在類的繼承時(shí)有所不同。(4)
數(shù)據(jù)成員的類型可以是任意的,包含整型、浮點(diǎn)型、字元型、數(shù)組、指針等,也可以是另一個(gè)類的對(duì)象,但不允許對(duì)所定義的成員變數(shù)進(jìn)行初始化。
(5)儘量將類單獨(dú)存放在一個(gè)檔中或?qū)㈩惖穆暶鞣旁?h檔中而將成員函數(shù)的實(shí)現(xiàn)放在與.h檔同名的.cpp檔中。以後將會(huì)看到,VisualC++6.0為用戶創(chuàng)建的應(yīng)用程式框架中都是將各個(gè)類以.h和同名的.cpp檔來(lái)組織的。
2.1類和對(duì)象2.1.3對(duì)象的定義
一個(gè)類定義後,就可以定義該類的對(duì)象,格式: <類名><對(duì)象名列表>
類名是用戶已定義過(guò)的類的識(shí)別字,對(duì)象名可以有一個(gè)或多個(gè),多個(gè)時(shí)要用逗號(hào)分隔。被定義的對(duì)象既可以是一個(gè)普通對(duì)象,也可以是一個(gè)數(shù)組對(duì)象或指針對(duì)象。一個(gè)對(duì)象的成員就是該對(duì)象的類所定義的成員,引用(訪問(wèn))時(shí)可用下列方式:
<對(duì)象名>.<成員名> <對(duì)象名>.<成員名>(<參數(shù)表>)。前者用來(lái)表示引用數(shù)據(jù)成員,後者用來(lái)表示引用成員函數(shù)。“.”是一個(gè)成員運(yùn)算符,用來(lái)引用對(duì)象的成員對(duì)於指針對(duì)象的成員引用可用下列方式:
<對(duì)象指針名>-><成員名> <對(duì)象指針名>-><成員名>(<參數(shù)表>)“->”與“.”運(yùn)算符的區(qū)別是:“->”用來(lái)訪問(wèn)指針對(duì)象的成員,“.”用來(lái)訪問(wèn)一般對(duì)象的成員。需要說(shuō)明的是,下麵的兩種表示是等價(jià)的:
<對(duì)象指針名>-><成員名> (*<對(duì)象指針名>).<成員名>
這對(duì)於成員函數(shù)也適用,例如two->GetAverage()和(*two).GetAverage()是等價(jià)的,由於成員運(yùn)算符“.”的優(yōu)先順序比取內(nèi)容運(yùn)算符“*”高。若結(jié)構(gòu)成員前面沒(méi)有“public:”或“private:”,則所定義的成員是public(公有)。
2.2類的成員及特性
2.2.1構(gòu)造函數(shù)
使用構(gòu)造函數(shù)能給數(shù)據(jù)成員自動(dòng)設(shè)置某些初始值。它的最大特點(diǎn)是在對(duì)象建立時(shí)它會(huì)被自動(dòng)執(zhí)行,因此用於變數(shù)、對(duì)象的初始化代碼一般放在構(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é)號(hào)
...}
(1)
程式中的strcpy是一個(gè)庫(kù)函數(shù),用來(lái)複製字串,使用時(shí)要頭檔string.h。
(2)
類定義時(shí),如沒(méi)有定義任何構(gòu)造函數(shù),編譯器自動(dòng)為類生成一個(gè)不帶任何參數(shù)的默認(rèn)構(gòu)造函數(shù)。
(3)
由於構(gòu)造函數(shù)的參數(shù)只能在定義對(duì)象時(shí)指定。
2.2類的成員及特性2.2.2析構(gòu)函數(shù)
與構(gòu)造函數(shù)相對(duì)應(yīng)的另一種特殊的C++成員函數(shù)是析構(gòu)函數(shù),它的功能是用來(lái)釋放一個(gè)對(duì)象,在對(duì)象刪除前,用它來(lái)做一些清理工作,它與構(gòu)造函數(shù)的功能正好相反。 析構(gòu)函數(shù)也要與相應(yīng)的類同名,並在名稱前面加上一個(gè)“~”符號(hào)。每一個(gè)類只有唯一的一個(gè)析構(gòu)函數(shù),沒(méi)有任何參數(shù),也不返回任何值,也不能被重載。例如:
classCStuScore { public: ... ~CStuScore() { } //析構(gòu)函數(shù)
...}
同樣,如果一個(gè)類中沒(méi)有定義析構(gòu)函數(shù)時(shí),則編譯系統(tǒng)也會(huì)為類自動(dòng)生成一個(gè)默認(rèn)析構(gòu)函數(shù),其格式如下(以類CStuScore為例):
~CStuScore() //默認(rèn)析構(gòu)函數(shù)的形式
{}需要說(shuō)明的是,析構(gòu)函數(shù)只有在下列兩種情況下才會(huì)被自動(dòng)調(diào)用:
(1)
當(dāng)對(duì)象定義在一個(gè)函數(shù)體中,該函數(shù)調(diào)用結(jié)束後,析構(gòu)函數(shù)被自動(dòng)調(diào)用。
(2)
用new為對(duì)象分配動(dòng)態(tài)記憶體後,當(dāng)使用delete釋放對(duì)象時(shí),析構(gòu)函數(shù)被自動(dòng)調(diào)用。
2.2類的成員及特性2.2.3對(duì)象成員初始化 構(gòu)造函數(shù)定義格式:
<類名>::<構(gòu)造函數(shù)名>(形參表):對(duì)象1(參數(shù)表),對(duì)象2(參數(shù)表),…,對(duì)象n(參數(shù)表) {…… }
對(duì)象1、對(duì)象2、…、對(duì)象n就是該類使用的其他類的對(duì)象,冒號(hào)“:”後面的列表稱為成員初始化列表。說(shuō)明:(1)
類的對(duì)象成員必須初始化,但不能將對(duì)象成員直接在構(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)
對(duì)象成員初始化時(shí),必須有相應(yīng)的構(gòu)造函數(shù),且多個(gè)對(duì)象成員的構(gòu)造次序不是按初始化成員列表的順序,而是按各類聲明的先後次序進(jìn)行的,從上例的運(yùn)行結(jié)果可以得到證明。(3)
對(duì)象成員初始化也可在類構(gòu)造函數(shù)定義時(shí)進(jìn)行。(4)事實(shí)上,成員初始化列表也可用於類中的普通數(shù)據(jù)成員的初始化。
2.2類的成員及特性2.2.4常類型
常對(duì)象 常對(duì)象是指對(duì)象常量,定義格式:<類名>const<對(duì)象名>
定義常對(duì)象時(shí)要進(jìn)行初始化,並且該對(duì)象不能再被更新,修飾符const可以放在類名後面,也可以放在類名前面。
常成員函數(shù)
使用const關(guān)鍵字進(jìn)行聲明的成員函數(shù)。只有常成員函數(shù)才有資格操作常量或常對(duì)象。說(shuō)明格式: <類型說(shuō)明符><函數(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不僅可以說(shuō)明成員函數(shù),也可以說(shuō)明數(shù)據(jù)成員。由於const類型對(duì)象必須被初始化,並且不能更新,因此,在類中聲明const數(shù)據(jù)成員後,只能通過(guò)構(gòu)造函數(shù)成員初始化方式來(lái)對(duì)常數(shù)據(jù)成員初始化。
2.2類的成員及特性2.2.5this指針
類中總有一個(gè)特殊的指針this,它指向類自己。該指針可以在類中訪問(wèn)類的成員變數(shù)和成員函數(shù)。但在實(shí)際運(yùn)用中,一般不需要顯式地使用this指針來(lái)引用成員。
[例Ex_This]this指針的使用。
#include<iostream.h> classCOne { public: COne() {x=y=0;} COne(inta,intb) {x=a; y=b;} //對(duì)象引用作函數(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獲得的某對(duì)象的值賦給操作該成員函數(shù)的對(duì)象。在本例中,就是將對(duì)象two賦給對(duì)象one。2.2類的成員及特性2.2.6類的作用域和對(duì)象的生存期類的作用域是指在類的定義中由一對(duì)花括弧所括起來(lái)的部分。類作用域中定義的變數(shù)不能使用auto,register和extern等修飾符,只能使用static修飾符,而定義的函數(shù)也不能用extern修飾符。檔作用域中可以包含類作用域,類作用域小於檔作用域。某個(gè)類A中某個(gè)成員M在下列情況下具有類A的作用域:(1)
成員M出現(xiàn)在類A的某個(gè)成員函數(shù)中,並且該成員函數(shù)沒(méi)有定義同名識(shí)別字。(2)
成員M出現(xiàn)在a.M或A::M運(yùn)算式中,其中a是A的對(duì)象。(3)
成員M出現(xiàn)在pa->M這樣的運(yùn)算式中,其中pa是一個(gè)指向A類對(duì)象的指針。對(duì)象的生存期是指對(duì)象從被創(chuàng)建開(kāi)始到被釋放為止的時(shí)間。生存期的不同對(duì)象分:(1)
局部對(duì)象:當(dāng)對(duì)象被定義時(shí)調(diào)用構(gòu)造函數(shù),該對(duì)象被創(chuàng)建,當(dāng)程式退出定義該對(duì)象所在的函數(shù)體或程式塊時(shí),調(diào)用析構(gòu)函數(shù),釋放該對(duì)象。(2)
靜態(tài)對(duì)象:當(dāng)程式第一次執(zhí)行所定義的靜態(tài)對(duì)象時(shí),該對(duì)象被創(chuàng)建,當(dāng)程式結(jié)束時(shí),該對(duì)象被釋放。(3)
全局對(duì)象:當(dāng)程式開(kāi)始時(shí),調(diào)用構(gòu)造函數(shù)創(chuàng)建該對(duì)象,當(dāng)程式結(jié)束時(shí)調(diào)用析構(gòu)函數(shù)釋放該對(duì)象。局部對(duì)象是被定義在一個(gè)函數(shù)體或程式塊內(nèi)的,它的作用域小,生存期也短。靜態(tài)對(duì)象是被定義在一個(gè)檔中,它的作用域從定義時(shí)起到檔結(jié)束時(shí)止。它的作用域比較大,它的生存期也比較長(zhǎng)。全局對(duì)象是被定義在某個(gè)檔中,而它的作用域卻在包含該檔的整個(gè)程式中,它的作用域是最大的,它的生存期也是最長(zhǎng)的。
2.2類的成員及特性2.2.7靜態(tài)成員
靜態(tài)數(shù)據(jù)成員
靜態(tài)數(shù)據(jù)成員是同一個(gè)類中所有對(duì)象共用的成員。使用靜態(tài)數(shù)據(jù)成員可以節(jié)省記憶體。靜態(tài)數(shù)據(jù)成員的值對(duì)每個(gè)對(duì)象都是一樣,但它的值是可以更新的。靜態(tài)數(shù)據(jù)成員是靜態(tài)存儲(chǔ)的,具有靜態(tài)生存期。它是這樣的定義的:
(1)
使用關(guān)鍵字static聲明靜態(tài)數(shù)據(jù)成員。
(2)
對(duì)靜態(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)成員,但它不是對(duì)象成員。因此,對(duì)靜態(tài)成員的引用不要用對(duì)象名。在靜態(tài)成員函數(shù)的實(shí)現(xiàn)中不能直接引用類中的非靜態(tài)成員,但可以引用類中的靜態(tài)成員。如果靜態(tài)成員函數(shù)中一定要引用非靜態(tài)成員時(shí),則可通過(guò)對(duì)象來(lái)引用。公有的靜態(tài)成員函數(shù)既可以通過(guò)相應(yīng)的對(duì)象訪問(wèn),也可以通過(guò)其所屬的類名來(lái)引用。
2.2類的成員及特性2.2.8友元
類的重要特性是使數(shù)據(jù)封裝與隱藏,但同時(shí)也給外部函數(shù)訪問(wèn)類中的私有和保護(hù)類型數(shù)據(jù)成員帶來(lái)了不便,為此,C++使用一個(gè)特殊的函數(shù)——“友元函數(shù)”來(lái)解決這個(gè)問(wèn)題。
“友元函數(shù)”必須在類中進(jìn)行聲明而在類外定義,聲明時(shí)須在函數(shù)類型前面加上關(guān)鍵字friend。友元函數(shù)雖不是類的成員函數(shù),但它可以訪問(wèn)類中的私有和保護(hù)類型數(shù)據(jù)成員。
friend除了可以定義友元函數(shù)外,還可以定義友元類,即一個(gè)類可以作另一個(gè)類的友元。當(dāng)一個(gè)類作為另一個(gè)類的友元時(shí),這就意味著這個(gè)類的所有成員函數(shù)都是另一個(gè)類的友元函數(shù)。
2.3繼承和派生類
通過(guò)繼承可以在一個(gè)一般類的基礎(chǔ)上建立新類。被繼承的類稱為基類(baseclass),在基類上建立的新類稱為派生類(derivedclass)。如果一個(gè)類只有一個(gè)基類則稱為單繼承,否則稱為多繼承。通過(guò)進(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),而基類的私有成員仍然是私有的。注意的是:派生類中或派生類的對(duì)象可以使用基類的公有成員(包括保護(hù)成員),例如CStudent類的成員函數(shù)Print中調(diào)用了基類CPerson的Output函數(shù),stu對(duì)象調(diào)用了基類的SetData成員函數(shù),但基類或基類的對(duì)象卻不可以使用派生類的成員。
2.3繼承和派生類私有繼承(private)
特點(diǎn)是基類的公有成員和保護(hù)成員都作為派生類的私有成員,並且不能被這個(gè)派生類的子類所訪問(wèn)。保護(hù)繼承(protected)
特點(diǎn)是基類的所有公有成員和保護(hù)成員都成為派生類的保護(hù)成員,並且只能被它的派生類成員函數(shù)或友元訪問(wèn),基類的私有成員仍然是私有的。注意:一定要區(qū)分清楚派生類的對(duì)象和派生類中的成員函數(shù)對(duì)基類的訪問(wèn)是不同的。例如,在公有繼承時(shí),派生類的對(duì)象可以訪問(wèn)基類中的公有成員,派生類的成員函數(shù)可以訪問(wèn)基類中的公有成員和保護(hù)成員。在私有繼承和保護(hù)繼承時(shí),基類的所有成員不能被派生類的對(duì)象訪問(wèn),而派生類的成員函數(shù)可以訪問(wèn)基類中的公有成員和保護(hù)成員。2.3繼承和派生類2.3.2派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù)
派生類對(duì)象在建立時(shí),先執(zhí)行基類的構(gòu)造函數(shù),然後執(zhí)行派生類的構(gòu)造函數(shù)。但對(duì)於析構(gòu)函數(shù)來(lái)說(shuō),其順序剛好相反,先執(zhí)行派生類的析構(gòu)函數(shù),而後執(zhí)行基類的析構(gòu)函數(shù)。注意:基類的構(gòu)造函數(shù)和析構(gòu)函數(shù)不能被派生類繼承。 派生類進(jìn)行初始化對(duì)基類設(shè)置初值格式:
<派生類名>(總參表):<基類1>(參數(shù)表1),<基類2>(參數(shù)表2),…,<基類n>(參數(shù)表n),對(duì)象成員1(對(duì)象成員參數(shù)表1),對(duì)象成員2(對(duì)象成員參數(shù)表2),…,對(duì)象成員n(對(duì)象成員參數(shù)表n) {...}
構(gòu)造函數(shù)總參表後面給出的是需要用參數(shù)初始化的基類名、對(duì)象成員名及各自對(duì)應(yīng)的參數(shù)表,基類名和對(duì)象成員名之間的順序可以是任意的,且對(duì)於使用默認(rèn)構(gòu)造函數(shù)的基類和對(duì)象成員,可以不列出基類名和對(duì)象成員名。這裏所說(shuō)的對(duì)象成員是指在派生類中新聲明的數(shù)據(jù)成員,它屬於另外一個(gè)類的對(duì)象。對(duì)象成員必須在初始化列表中進(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ù)
說(shuō)明:
(1)
虛函數(shù)在重新定義時(shí)參數(shù)的個(gè)數(shù)和類型必須和基類中的虛函數(shù)完全匹配,這一點(diǎn)和函數(shù)重載完全不同。
(2)
虛函數(shù)所具備的上述功能,只有通過(guò)基類指針才可實(shí)現(xiàn)。虛函數(shù)在用對(duì)象名和成員運(yùn)算符以正常方式調(diào)用時(shí),不能達(dá)到其效果。
(3)
如果不使用new來(lái)創(chuàng)建相應(yīng)的派生類對(duì)象,也可用下列方法來(lái)實(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ù)。通常在釋放基類及其派生類中的動(dòng)態(tài)申請(qǐng)的存儲(chǔ)空間時(shí),也要把析構(gòu)函數(shù)定義為虛函數(shù),以便實(shí)現(xiàn)撤銷對(duì)象時(shí)的多態(tài)性。
3.1多態(tài)和虛函數(shù)3.1.2純虛函數(shù)和抽象類
定義一個(gè)基類時(shí),會(huì)遇到這樣的情況:無(wú)法定義基類中虛函數(shù)的具體實(shí)現(xiàn),其實(shí)現(xiàn)完全依賴於其不同的派生類。例如,一個(gè)“形狀類”由於沒(méi)有確定的具體形狀,因此其計(jì)算面積的函數(shù)也就無(wú)法實(shí)現(xiàn)。這時(shí)可將基類中的虛函數(shù)聲明為純虛函數(shù)。
聲明純虛函數(shù)的一般格式為:
virtual<函數(shù)類型><函數(shù)名>(<形數(shù)表>)=0;它與一般虛函數(shù)不同的是:在純虛函數(shù)的形參表後面多了個(gè)“=0”。把函數(shù)名賦於0,本質(zhì)上是將指向函數(shù)的指針的初值賦為0。需要說(shuō)明的是,純虛函數(shù)不能有具體的實(shí)現(xiàn)代碼。
抽象類是指至少包含一個(gè)純虛函數(shù)的特殊的類。它本身不能被實(shí)例化,也就是說(shuō)不能聲明一個(gè)抽象類的對(duì)象。必須通過(guò)繼承得到派生類後,在派生類中定義了純虛函數(shù)的具有實(shí)現(xiàn)代碼,才能獲得一個(gè)派生類的對(duì)象。與虛函數(shù)使用方法相同,也可以聲明指向抽象類的指針,雖然該指針不能指向任何抽象類的對(duì)象,但可以通過(guò)該指針獲得對(duì)派生類成員函數(shù)的調(diào)用。事實(shí)上,純虛函數(shù)是一個(gè)特殊的虛函數(shù)。
3.2運(yùn)算符重載
3.2.1運(yùn)算符重載的語(yǔ)法
<函數(shù)類型><類名>::operator<重載的運(yùn)算符>(<形參表>) {…} //函數(shù)體 運(yùn)算符重載函數(shù)的函數(shù)是以特殊的關(guān)鍵字operator開(kāi)始的,因而編譯器很容易與其他的函數(shù)名區(qū)分開(kāi)來(lái)。
重載的運(yùn)算符必須是合法的運(yùn)算符。說(shuō)明:(1)
當(dāng)用成員函數(shù)實(shí)現(xiàn)雙目運(yùn)算符的重載時(shí),運(yùn)算符的左運(yùn)算元一定是對(duì)象,右運(yùn)算元作為調(diào)用運(yùn)算符重載函數(shù)的參數(shù),參數(shù)可以是對(duì)象、對(duì)象的引用或是其他類型的參數(shù)。(2)
不是所有的運(yùn)算符都可以重載。不允許重載的運(yùn)算符除三目運(yùn)算符“?:”外,還有成員操作符“.”、成員指針取值操作符“*”、作用域操作符“::”以及sizeof運(yùn)算符。(3)
只能對(duì)已定義了的運(yùn)算符進(jìn)行重載,而且當(dāng)重載一個(gè)運(yùn)算符時(shí),該運(yùn)算符的運(yùn)算元個(gè)數(shù)、優(yōu)先順序和結(jié)合性是不能改變的。[例Ex_Complex]運(yùn)算符的簡(jiǎ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();}
對(duì)運(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ù)沒(méi)有參數(shù)。
3.2運(yùn)算符重載3.2.2賦值運(yùn)算符的重載
對(duì)象的成員中有數(shù)組或動(dòng)態(tài)的數(shù)據(jù)類型時(shí),就不能直接相互賦值,否則在程式的編譯或執(zhí)行過(guò)程中出現(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)的輸入輸出流來(lái)輸入輸出自己定義的數(shù)據(jù)類型(包括類),實(shí)現(xiàn)對(duì)象的輸入輸出。 重載這兩個(gè)運(yùn)算符時(shí)最好將重載聲明為類的友元函數(shù),以便訪問(wèn)類中的私有成員。
友元重載的一般格式如下:
friend<函數(shù)類型>operator<重載的運(yùn)算符>(<形參>) //單目
{…} friend<函數(shù)類型>operator<重載的運(yùn)算符>(<形參1,形數(shù)2)//雙目
{…} 對(duì)於單目運(yùn)算符的友元重載函數(shù),只有一個(gè)形參,形參類型可以是類的對(duì)象,可以是引用,這取決於不同的運(yùn)算符。對(duì)於雙目運(yùn)算符的友元重載函數(shù)來(lái)說(shuō),它有兩個(gè)形參,這兩個(gè)形參中必須有一個(gè)是類的對(duì)象。需要說(shuō)明的是,=、()、[]和->運(yùn)算符不能用友元來(lái)重載。
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é)號(hào)
floatfScore[3]; //三門(mén)成績(jī)
};ostream&operator<<(ostream&os,CStudent&stu){ os<<endl<<"學(xué)生資訊如下:"<<endl; os<<"姓名:"<<stu.strName<<endl; os<<"學(xué)號(hào):"<<stu.strID<<endl; os<<"成績(jī):"<<stu.fScore[0]<<",\t" <<stu.fScore[1]<<",\t" <<stu.fScore[2]<<endl; returnos;}istream&operator>>(istream&is,CStudent&stu){ cout<<"請(qǐng)輸入學(xué)生資訊"<<endl; cout<<"姓名:"; is>>stu.strName; cout<<"學(xué)號(hào):"; is>>stu.strID; cout<<"三門(mén)成績(jī):"; is>>stu.fScore[0]>>stu.fScore[1]>>stu.fScore[2]; returnis; }voidmain(){ CStudentone; cin>>one; cout<<one; }3.3輸入輸出流庫(kù)
3.3.1概述
輸入輸出操作是由“流”來(lái)處理的。數(shù)據(jù)從一個(gè)位置到另一個(gè)位置的流動(dòng)抽象為“流”。當(dāng)流被建立後就可以使用一些特定的操作從流中獲取數(shù)據(jù)或向流中添加數(shù)據(jù)。從流中獲取數(shù)據(jù)的操作稱為“提取”操作,向流中添加數(shù)據(jù)的操作稱為“插入”操作。
ios類提供對(duì)流狀態(tài)進(jìn)行設(shè)置的功能,是虛基類,其他類都是從這個(gè)派生而來(lái)的。
streambuf不是ios類的派生類,在類ios中只是有一個(gè)指針成員,指向streambuf類的一個(gè)對(duì)象。streambuf類是用來(lái)為ios類及其派生類提供對(duì)數(shù)據(jù)的緩衝支持。itream和ostream類是ios的公有派生類,前者向流中插入數(shù)據(jù)的有關(guān)操作,後者從流中提取數(shù)據(jù)的有關(guān)操作。iostream類是itream和ostream類公有派生的。
四個(gè)預(yù)定義的標(biāo)準(zhǔn)流對(duì)象:cin、cout、cerr和clog。當(dāng)用戶在程式中包含了頭檔“iostream.h”,編譯器調(diào)用相應(yīng)的構(gòu)造函數(shù),產(chǎn)生這四個(gè)標(biāo)準(zhǔn)流對(duì)象,用戶在程式中就可以直接使用它們了。其中,cin是istream類的對(duì)象,用處理標(biāo)準(zhǔn)輸入cout是ostream類的對(duì)象,用處理標(biāo)準(zhǔn)輸出。cerr和clog都是ostream類的對(duì)象,用來(lái)處理標(biāo)準(zhǔn)出錯(cuò)資訊,並將資訊顯示在螢?zāi)簧?。在這四個(gè)標(biāo)準(zhǔn)流對(duì)象中,除了cerr不支持緩衝外,其餘三個(gè)都帶有緩衝區(qū)。標(biāo)準(zhǔn)流通常使用提取運(yùn)算符“>>”和插入運(yùn)算符“<<”來(lái)進(jìn)行輸入輸出操作的,而且系統(tǒng)還會(huì)自動(dòng)地完成數(shù)據(jù)類型的轉(zhuǎn)換。
3.3輸入輸出流庫(kù)3.3.2cout和cin輸出流(cout)
cout可以輸出一個(gè)整數(shù)、實(shí)數(shù)、字元及字串,cout中的插入符“<<”可以連續(xù)寫(xiě)多個(gè),每個(gè)後面可以跟一個(gè)要輸出的常量、變數(shù)、轉(zhuǎn)義序列符、對(duì)象以及運(yùn)算式等。
(1)
width函數(shù) 格式:intwidth(); intwidth(int);
第一種格式用來(lái)獲取當(dāng)前輸出數(shù)據(jù)時(shí)的寬度。另一種格式是用來(lái)設(shè)置當(dāng)前輸出數(shù)據(jù)時(shí)的寬度。 (2)
precision函數(shù) 格式:intprecision(); intprecision(int);
這兩種格式分別用來(lái)獲取和設(shè)置當(dāng)前浮點(diǎn)數(shù)的有效數(shù)字的個(gè)數(shù),第二種格式函數(shù)還將返回設(shè)置前的有效數(shù)字的個(gè)數(shù)。需要說(shuō)明的是,C++默認(rèn)的有效數(shù)字的個(gè)數(shù)為6。
(3)
fill函數(shù) 格式:charfill(); charfill(char);
這兩種格式分別用來(lái)獲取和設(shè)置當(dāng)前寬度內(nèi)的填充字元,第二種格式函數(shù)還將返回設(shè)置前的填充字元。
3.3輸入輸出流庫(kù)輸入流(cin)
格式: cin>><運(yùn)算式1>[>><運(yùn)算式2>...]
提取符“>>”可以連續(xù)寫(xiě)多個(gè),每個(gè)後面跟一個(gè)運(yùn)算式,該運(yùn)算式通常是獲得輸入值的變數(shù)或?qū)ο蟆?/p>
intx1,x2,x3;cin>>x1>>x2>>x3;
要求用戶從鍵盤(pán)上輸入三個(gè)整數(shù)。輸入時(shí),必須在三個(gè)數(shù)值之間加上一些空格來(lái)分隔,空格的個(gè)數(shù)不限,最後用回車鍵結(jié)束輸入;或者在每個(gè)數(shù)值之後按回車鍵。格式算子oct、dec和hex
格式算子oct、dec和hex能分別將輸入或輸出的數(shù)值轉(zhuǎn)換成八進(jìn)制、十進(jìn)位及十六進(jìn)制。3.3輸入輸出流庫(kù)
輸入輸出過(guò)程中發(fā)現(xiàn)操作錯(cuò)誤,流就會(huì)將發(fā)生的錯(cuò)誤記錄下來(lái)。用戶可以使用錯(cuò)誤檢測(cè)功能,檢測(cè)和查明錯(cuò)誤發(fā)生的原因和性質(zhì),然後調(diào)用clear函數(shù)清除錯(cuò)誤狀態(tài),使流能夠恢復(fù)處理。
在ios類中,定義了一個(gè)公有枚舉成員io_state來(lái)記錄各種錯(cuò)誤的性質(zhì):
enumio_state{ goodbit =0x00, //正常
eofbit =0x01, //已達(dá)到檔尾
failbit =0x02, //操作失敗
badbit =0x04 //非法操作}; 在ios類中又定義了檢測(cè)上述流狀態(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輸入輸出流庫(kù)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輸入輸出流庫(kù)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)的,在檔每一次打開(kāi)時(shí),檔指針指向檔的開(kāi)始,隨著對(duì)檔的處理,檔指針不斷地在檔中移動(dòng),並一直指向最新處理的字元(位元組)位置。檔處理方式,一種稱為檔的順序處理。另一種稱為檔的隨機(jī)處理,並指向所要處理的字元(位元組)位置。按照這兩種處理方式,可將檔相應(yīng)地稱為順序檔和隨機(jī)檔。3.3輸入輸出流庫(kù)3.3.6順序檔操作
檔的打開(kāi)和關(guān)閉
聲明一個(gè)ifstream、ofstream或fstream類對(duì)象。
使用檔流類的成員函數(shù)打開(kāi)或創(chuàng)建一個(gè)指定的檔,使得該檔與聲明的檔流對(duì)象聯(lián)繫起來(lái),這樣對(duì)流對(duì)象的操作也就是對(duì)檔的操作。
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輸入輸出流庫(kù)檔的讀寫(xiě)
[例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不能打開(kāi)!\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輸入輸出流庫(kù)3.3.7隨機(jī)檔操作 隨機(jī)檔可以在檔中來(lái)回移動(dòng)檔指針,從而可以實(shí)現(xiàn)非順序讀寫(xiě)檔數(shù)據(jù)的功能,達(dá)到快速檢索、修改和刪除檔數(shù)據(jù)的效果。
seekg和seekp函數(shù)將檔指針移動(dòng)到指定的位置。它們的原型如下:
istream&seekg(longpos); istream&seekg(longoff,ios::seek_dirdir); ostream&seekp(longpos); ostream&seekp(longoff,ios::seek_dirdir);
其中,pos用來(lái)指定檔指針的絕對(duì)位置。若用off指定檔指針的相對(duì)偏移量時(shí),檔指針的最終位置還需根據(jù)dir值才能確定。dir值可以是:
ios::beg 從檔流的頭部開(kāi)始
ios::cur 從當(dāng)前的檔指針位置開(kāi)始
ios::end
從檔流的尾部開(kāi)始
3.4範(fàn)本
3.4.1函數(shù)重載機(jī)制的不足
函數(shù)重載方便用戶對(duì)函數(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è)問(wèn)題就是使用函數(shù)範(fàn)本。3.4.2函數(shù)範(fàn)本
格式:
template<數(shù)據(jù)類型聲明>
函數(shù)體
template是一個(gè)聲明範(fàn)本的關(guān)鍵字,數(shù)據(jù)類型聲明是使用class關(guān)鍵字來(lái)定義類型名稱,而函數(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類名
{ ... //成員的定義
}; 注意:大括弧後的分號(hào)不能省略。3.4.4標(biāo)準(zhǔn)範(fàn)本庫(kù)簡(jiǎn)介
標(biāo)準(zhǔn)範(fàn)本庫(kù)STL(StandardTemplateLibrary)是通過(guò)STL中的相應(yīng)運(yùn)算法則在應(yīng)用程式的迭代子(iterator)、容器以及其他定義的序列中建立一種統(tǒng)一的標(biāo)準(zhǔn)。從根本上來(lái)說(shuō),STL是一個(gè)基於範(fàn)本的群體類庫(kù),它包含群體類(鏈表或列表、向量、棧、佇列、集合、映象)、演算法(排序、查找)以及迭代子。
STL中的群體類是基於範(fàn)本的,包含線性群體類,也包含非線性群體類。其主要群體類有:
deque(雙端佇列) list(鏈表、列表) map(映象) multimap(多重映象)
multiset(多重集合) set(集合) vector(向量)3.4範(fàn)本
STL的迭代子有順序和直接訪問(wèn),順序迭代子使用++、--等進(jìn)行指針移動(dòng),只能順序訪問(wèn)群體類中的對(duì)象,而直接訪問(wèn)迭代子是通過(guò)iterator_traits來(lái)直接訪問(wèn)群體類中的某個(gè)特定對(duì)象。iterator_traits用來(lái)指定要訪問(wèn)的屬性類型,它可以有:
iterator_category(目錄類型) value_type(數(shù)值類型) difference_type(距離類型,表示兩個(gè)指針的地址之間的距離) pointer(指針類型) reference(引用類型)
STL的演算法是用函數(shù)範(fàn)本實(shí)現(xiàn)的,可以實(shí)現(xiàn)對(duì)不同類型對(duì)象的通用操作。演算法與STL群體類之間是通過(guò)迭代子iterator來(lái)進(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)
對(duì)話框
4.1從C++到Windows編程
4.1.1簡(jiǎn)單的Windows應(yīng)用程式
[例Ex_HelloMsg]一個(gè)最簡(jiǎn)單的Windows應(yīng)用程式。
(1)選擇“檔”
“新建”菜單命令,顯示出“新建”對(duì)話框。單擊“工程”標(biāo)籤,從列表框中選中Win32Application(Win32應(yīng)用程式)項(xiàng)。
(2)在工程名稱框中鍵入Win32應(yīng)用程式專案名稱Ex_HelloMsg。在“位置”下的編輯框中直接鍵入檔夾名稱,或單擊流覽按鈕(...)選擇一個(gè)已有的檔夾。
(3)單擊[確定]按鈕繼續(xù)。一個(gè)詢問(wèn)專案類型的Win32應(yīng)用程式嚮導(dǎo)將被顯示,選中Anemptyproject項(xiàng)。單擊[完成]按鈕,系統(tǒng)將顯示AppWizard的創(chuàng)建資訊,單擊[確定]按鈕系統(tǒng)將自動(dòng)創(chuàng)建此應(yīng)用程式。
4.1從C++到Windows編程(4)再次選擇“檔”
“新建”菜單命令,顯示出“新建”對(duì)話框。單擊“檔”標(biāo)籤,在左邊的列表框中選擇C++SourceFile項(xiàng),在右邊的“檔”下的編輯框中鍵入Ex_HelloMsg.cpp,單擊[確定]按鈕。
(5)
輸入下麵的代碼:
#include<windows.h> intWINAPIWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,LPSTRlpCmdLine,intnCmdShow) { MessageBox(NULL,"你好,我的VisualC++世界!","問(wèn)候",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)識(shí)Windows資源和設(shè)備等對(duì)象的變數(shù),或者是一個(gè)對(duì)操作系統(tǒng)資源的間接引用。每一個(gè)用C/C++編寫(xiě)的Windows應(yīng)用程式都需要Windows.h頭檔,它還包含了其他的一些Windows頭檔。這些頭檔定義了Windows的所有數(shù)據(jù)類型、函數(shù)調(diào)用、數(shù)據(jù)結(jié)構(gòu)和符號(hào)常量。程式中,MessageBox是一個(gè)Win32API(ApplicationProgrammingInterface,應(yīng)用程式介面)函數(shù),用來(lái)彈出一個(gè)對(duì)話框窗口,顯示短資訊。該函數(shù)第一個(gè)參數(shù)用來(lái)指定父窗口句柄,即對(duì)話框所在的窗口句柄。第二、三個(gè)參數(shù)分別用來(lái)指定顯示的消息內(nèi)容和對(duì)話框窗口的標(biāo)題,最後一個(gè)參數(shù)用來(lái)指定在對(duì)話框中顯示的按鈕。
4.1從C++到Windows編程4.1.2Windows編程特點(diǎn)
Windows應(yīng)用程式具有這樣的一些特性:消息驅(qū)動(dòng)機(jī)制、圖形設(shè)備介面(GDI)、基於資源的程式設(shè)計(jì)、動(dòng)態(tài)鏈接庫(kù)。消息驅(qū)動(dòng)機(jī)制
DOS程式是通過(guò)調(diào)用系統(tǒng)的函數(shù)來(lái)獲得用戶輸入的,Windows程式是通過(guò)操作系統(tǒng)發(fā)送的消息來(lái)處理用戶輸入的。消息驅(qū)動(dòng)的機(jī)制是Windows編程的最大特點(diǎn)。
WinMain函數(shù)通常要完成以下幾步工作:
定義並調(diào)用API函數(shù)RegisterClass註冊(cè)應(yīng)用程式的窗口類。
調(diào)用相關(guān)API函數(shù)創(chuàng)建和顯示窗口,並進(jìn)行其他必要的初始化處理。其中,函數(shù)CreateWindow用來(lái)創(chuàng)建已註冊(cè)窗口類的窗口。創(chuàng)建和啟動(dòng)應(yīng)用程式的消息迴圈。Windows應(yīng)用程式接受各種不同的消息,包括鍵盤(pán)消息、滑鼠以及窗口產(chǎn)生的各種消息。Windows系統(tǒng)首先將消息放入消息佇列中,應(yīng)用程式的消息迴圈就是從應(yīng)用程式的消息佇列中檢取消息,並將消息發(fā)送相應(yīng)的窗口過(guò)程函數(shù)中作進(jìn)一步處理。API函數(shù)GetMessage和DispatchMessage就是起到這樣的作用。如果接收到WM_QUIT消息,則退出應(yīng)用程式。4.1從C++到Windows編程圖形設(shè)備介面(GDI)
Windows提供了一個(gè)抽象的圖形設(shè)備介面(GraphicalDeviceInterface,簡(jiǎn)稱GDI),使用戶直接利用系統(tǒng)的GDI函數(shù)就能方便實(shí)現(xiàn)圖形和文本的輸出,而不必關(guān)心與系統(tǒng)相連的外部設(shè)備的類型。
基於資源的程式設(shè)計(jì)
Windows應(yīng)用程式常常包含眾多圖形元素。每一個(gè)這樣的資源都用相應(yīng)的識(shí)別字來(lái)區(qū)分,而且Windows內(nèi)部也有預(yù)定義的資源。在Windows環(huán)境下,每一個(gè)資源元素都作為一種可以裝入應(yīng)用程式的資源來(lái)存放。這些資源可以被編輯、修改,也可以被其他應(yīng)用程式所共用。動(dòng)態(tài)鏈接庫(kù)
動(dòng)態(tài)鏈接庫(kù)提供一些特定結(jié)構(gòu)的函數(shù),能被應(yīng)用程式在運(yùn)行過(guò)程中裝入和連接,且多個(gè)程式可以共用同一個(gè)動(dòng)態(tài)鏈接庫(kù)。
Windows提供了應(yīng)用程式可調(diào)用的豐富的函數(shù),大多數(shù)用於實(shí)現(xiàn)其用戶介面和在顯示器上顯示的文本和圖形,都是通過(guò)動(dòng)態(tài)鏈接庫(kù)來(lái)實(shí)現(xiàn)的。這些動(dòng)態(tài)鏈接庫(kù)是一些具有DLL擴(kuò)展名或者有時(shí)是EXE擴(kuò)展名的檔。在Windows操作系統(tǒng)中,最主要的DLL有KERNEL32.DLL、GDI32.DLL和USER32.DLL。其中,KERNEL32.DLL用來(lái)處理記憶體低層功能、任務(wù)和資源管理等Windows核心服務(wù);GDI32.DLL用來(lái)提供圖形設(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)容封裝成為各種類,使程式員從繁雜的編程中解脫出來(lái)。VisualC++還提供大量的嚮導(dǎo)和可視化編輯工具,使得用戶不需要添加太多的代碼就能實(shí)現(xiàn)不同風(fēng)格和用途的應(yīng)用程式。
MFCAppWizard就是VisualC++6.0提供的一個(gè)非常有用的嚮導(dǎo),它能為用戶快速、高效、自動(dòng)地生成一些常用的標(biāo)準(zhǔn)程式結(jié)構(gòu)和編程風(fēng)格。
MFCAppWizard(exe)應(yīng)用程式框架包含用戶最常用、最基本的三種應(yīng)用程式類型:?jiǎn)挝臋n、多文檔和基於對(duì)話框的應(yīng)用程式。單文檔應(yīng)用程式每次只能打開(kāi)和處理一個(gè)文檔對(duì)話框的程式?jīng)]有菜單、工具欄及狀態(tài)欄,也不能處理文檔,但它的好處是速度快,代碼少,程式員所花費(fèi)的開(kāi)發(fā)和調(diào)試時(shí)間短。多文檔應(yīng)用程式,能允許同時(shí)打開(kāi)和處理多個(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)用程式。
開(kāi)始 選擇“檔”
“新建”菜單,在彈出的“新建”對(duì)話框中選擇“工程”標(biāo)籤,這時(shí)顯示出一系列的應(yīng)用程式專案類型;選擇MFCAppWizard(exe)的專案類型(該類型用於創(chuàng)建可執(zhí)行的Windows應(yīng)用程式),將專案工作檔夾定位在“…\VisualC++6.0程式\對(duì)話框”,並在工程框中輸入專案名Ex_SDI。
4.1從C++到Windows編程選擇程式類型 單擊[確定]按鈕,進(jìn)行下列選擇:(1)
從應(yīng)用程式類型單個(gè)文檔(SingleDocument,簡(jiǎn)稱SDI)、多重文檔(MultipleDocument,簡(jiǎn)稱MDI)和基本對(duì)話(DialogBased,基於對(duì)話框的應(yīng)用程式)中選擇“單個(gè)文檔”。(2)
決定應(yīng)用程式中是否需要MFC的文檔視圖(“文檔/查看體系結(jié)構(gòu)支持”)結(jié)構(gòu)的支持。若不選定此項(xiàng),則程式中的磁片檔的打開(kāi)、保存以及文檔和視圖的相互作用等功能需要用戶來(lái)實(shí)現(xiàn)。一般情況下,應(yīng)選中此項(xiàng)。(3)選擇資源所使用的語(yǔ)言,這裏是“中文[中國(guó)]”。4.1從C++到Windows編程簡(jiǎn)單創(chuàng)建
保留默認(rèn)的選項(xiàng),單擊[完成]按鈕,顯示出用戶在步驟中作出的選擇,單擊[確定]按鈕系統(tǒng)開(kāi)始創(chuàng)建。
4.1從C++到Windows編程編譯並運(yùn)行
到這裏為止,用戶雖然沒(méi)有編寫(xiě)任何程式代碼,但MFCAppWizard已經(jīng)根據(jù)用戶的選擇內(nèi)容自動(dòng)生成基本的應(yīng)用程式框架。單擊編譯工具條 上的運(yùn)行工具按鈕“”或按快捷鍵Ctrl+F5,系統(tǒng)開(kāi)始編連並運(yùn)行生成的單文檔應(yīng)用程式可執(zhí)行檔Ex_SDI.exe。
4.2添加並使用對(duì)話框
4.2.1資源與資源標(biāo)識(shí)
資源的分類
將上例Ex_SDI的專案工作區(qū)窗口切換到“ResourceView”頁(yè)面。
資源可分為下列幾類:
(1)快捷鍵列表(Accelerator):一系列組合鍵的集合,被應(yīng)用程式用來(lái)引發(fā)一個(gè)動(dòng)作。該列表一般與菜單命令相關(guān)聯(lián),用來(lái)代替滑鼠操作。
(2)對(duì)話框(Dialog):含有按鈕、列表框、編輯框等各種控件的窗口。
(3)圖示(Icon):代表應(yīng)用程式顯示在Windows桌面上的位圖,它同時(shí)有32
32像素和16
16像素兩種規(guī)格。
(4)菜單(Menu):用戶通過(guò)菜單可完成應(yīng)用程式的大部分操作。 (5)字串表(StringTable):應(yīng)用程式使用的全局字串或其他識(shí)別字。
(6)工具欄按鈕(Toolbar):工具欄外觀是以一系列具有相同尺寸的位圖組成的,它通常與一些菜單命令項(xiàng)相對(duì)應(yīng),用以提高用戶的工作效率。
(7)版本資訊(Version):包含應(yīng)用程式的版本、用戶註冊(cè)碼等相關(guān)資訊。
4.2添加並使用對(duì)話框識(shí)別字
每一個(gè)資源類別下都有一個(gè)或多個(gè)相關(guān)資源,每一個(gè)資源均是由識(shí)別字來(lái)定義的。當(dāng)添加或創(chuàng)建一個(gè)新的資源或資源對(duì)象時(shí),系統(tǒng)會(huì)為其提供默認(rèn)的名稱,如IDR_MAINFRAME等。用戶可重新命名,但要按一定的規(guī)則來(lái)進(jìn)行。一般地,要遵循下列規(guī)則:
(1)
在識(shí)別字名稱中允許使用字母a~z、A~Z、0~9以及下劃線。
(2)
識(shí)別字名稱不區(qū)分大小寫(xiě)字母,如new_idd與New_Idd是相同的識(shí)別字。
(3)
不能以數(shù)字開(kāi)頭,如8BIT是不合法的識(shí)別字名。
(4)
字元個(gè)數(shù)不得超過(guò)247個(gè)。4.2添加並使用對(duì)話框4.2.2添加對(duì)話框資源
添加對(duì)話框資源一般可按下列步驟(在上例Ex_SDI基礎(chǔ)上進(jìn)行):
(1)選擇“插入”
“資源”菜單,或按快捷鍵Ctrl+R打開(kāi)“插入資源”對(duì)話框,在對(duì)話框中可以看到資源列表中存在Dialog項(xiàng),若單擊Dialog項(xiàng)左邊的“+”號(hào),將展開(kāi)對(duì)話框資源的不同類型選項(xiàng)。
4.2添加並使用對(duì)話框
(2)對(duì)展開(kāi)的不同類型的對(duì)話框資源不作任何選擇,選中“Dialog”,單擊[新建]按鈕,系統(tǒng)就會(huì)自動(dòng)為當(dāng)前應(yīng)用程式添加了一個(gè)對(duì)話框資源。
系統(tǒng)為對(duì)話框資源自動(dòng)賦給它一個(gè)默認(rèn)的識(shí)別字名稱(第一次為IDD_DIALOG1,以後依次為IDD_DIALOG2、IDD_DIALOG3、...)。使用通用的對(duì)話框範(fàn)本創(chuàng)建新的對(duì)話框資源。對(duì)話框的默認(rèn)標(biāo)題為Dialog,有[OK]和[Cancel]兩個(gè)按鈕,這兩個(gè)按鈕的識(shí)別字分別為IDOK和IDCANCEL。對(duì)話框範(fàn)本資源所在的窗口稱為對(duì)話框資源編輯器,在這裏可以通過(guò)控件工具欄和佈局工具欄向?qū)υ捒蛱砑雍蛠丫挚丶?,並可設(shè)置對(duì)話框的屬性。4.2添加並使用對(duì)話框4.2.3設(shè)置對(duì)話框?qū)傩?/p>
在對(duì)話框範(fàn)本處右擊滑鼠,從彈出的快捷菜單中選擇“屬性”菜單項(xiàng)。
表4.5對(duì)話框的General屬性
4.2添加並使用對(duì)話框?qū)⑻砑拥膶?duì)話框的屬性進(jìn)行如下三點(diǎn)修改:將對(duì)話框識(shí)別字改成IDD_DIALOG_FIRST;
將對(duì)話框標(biāo)題改為“我的第一個(gè)對(duì)話框”;單擊[字體]按鈕,通過(guò)彈出的字體對(duì)話框?qū)?duì)話框內(nèi)的文本設(shè)置成“宋體,9”
,以使自己的對(duì)話框和Windows中的對(duì)話框保持外觀上的一致。
4.2添加並使用對(duì)話框4.2.4添加和佈局控件 在對(duì)話框中添加一個(gè)控件的方法:在控件工具欄中單擊某控件;在對(duì)話框指定位置單擊滑鼠左鍵,則此控件被添加到對(duì)話框的相應(yīng)位置,再拖動(dòng)選擇框可改變控件的大小和位置。在控件工具欄中單擊某控件,此時(shí)的滑鼠箭頭對(duì)話框內(nèi)變成“十”字形狀;在指定位置處單擊滑鼠左鍵不放,拖動(dòng)滑鼠至滿意位置,釋放滑鼠鍵。用滑鼠左鍵點(diǎn)中控件工具欄中的某控件,並按住滑鼠左鍵不放;在移動(dòng)滑鼠到對(duì)話框的指定位置的過(guò)程中,用戶會(huì)看到一個(gè)虛線框,下麵帶有該控件的標(biāo)記;釋放滑鼠左鍵,新添加的控件立即出現(xiàn)在對(duì)話框中。
控件的選擇靜態(tài)文本組框複選框組合框水準(zhǔn)滾動(dòng)條旋轉(zhuǎn)按鈕滑動(dòng)條列表視圖標(biāo)籤複合編輯月曆用戶定制工具靜態(tài)圖片編輯框按鈕單選框列表框垂直滾動(dòng)條進(jìn)展條熱鍵樹(shù)形視圖動(dòng)畫(huà)日期選擇IP地址組合框的擴(kuò)展圖4.14控件工具欄和各按鈕含義4.2添加並使用對(duì)話框控件的選取
選取單個(gè)控件,則可以下列方法。用滑鼠直接選取。用助記符來(lái)選取。用Tab鍵選取。對(duì)於多個(gè)控件的選取,可採(cǎi)用下列方法:先在對(duì)話框內(nèi)按住滑鼠左鍵不放,拖出一個(gè)大的虛框,然後釋放滑鼠,則被該虛框所包圍的控件都將被選取。先按住Shift鍵不放,然後用滑鼠選取控件,直到所需要的多個(gè)控件選取之後再釋放Shift鍵。若在選取時(shí),對(duì)已選取的控件再選取一下,則取消該控件選取。需要注意的是:(1)
一旦單個(gè)控件被選取後,其四周由選擇框包圍著,選擇框上還有幾個(gè)(通常是八個(gè))藍(lán)色實(shí)心小方塊,拖動(dòng)它可改變控件的大小。(2)多個(gè)控件被選取後,其中只有一個(gè)控件的選擇框有幾個(gè)藍(lán)色實(shí)心小方塊,這個(gè)控件稱為主要控件,而其他控件的選擇框的小方塊是空心的。(b)圖4.15單個(gè)控件和多個(gè)控件的選擇框(a)4.2添加並使用對(duì)話框控件的刪除、複製和佈局
與佈局工具相對(duì)應(yīng)的菜單命令在“編排”菜單下,而且大部分命令均有相應(yīng)的快捷鍵
圖4.17“編排”菜單命令項(xiàng)4.2添加並使用對(duì)話框注意:大多數(shù)佈置控件的命令使用前,都需要用戶選取多個(gè)控件,且“主要控件”起到了關(guān)鍵作用。例如用戶選取多個(gè)控件後,使用“MakeSameSize”命令只改變其他控件的大小,並與“主要控件”的尺寸一致。因此,在多個(gè)控件的佈置過(guò)程中,常需要重新設(shè)置“主要控件”。設(shè)置的方法是按住Ctrl或Shift鍵,然後用滑鼠單擊所要指定的控件即可。為了便於用戶在對(duì)話框內(nèi)精確定位各個(gè)控件,系統(tǒng)還提供了網(wǎng)格、尺規(guī)等輔助工具。在圖4.16的控件佈局工具欄的最後兩個(gè)按鈕分別用來(lái)網(wǎng)格和尺規(guī)的切換。一旦網(wǎng)格顯示,添加或移動(dòng)控件時(shí)都將自動(dòng)定位在網(wǎng)格線上。
表4.6“編排”菜單命令的快捷鍵及功能描述
4.2添加並使用對(duì)話框測(cè)試對(duì)話框
“編排”菜單下的Test命令或佈局工具欄上的測(cè)試按鈕是用來(lái)模擬所編輯的對(duì)話框的運(yùn)行情況,幫助用戶檢驗(yàn)對(duì)話框是否符合用戶的設(shè)計(jì)要求以及控件功能是否有效等。
操作示例
向?qū)υ捒蛱砑右粋€(gè)靜態(tài)文本控件。一個(gè)靜態(tài)文本控件就是一個(gè)文本標(biāo)籤。 右擊添加的控件,從彈出的快捷菜單中選擇“屬性”。
4.2添加並使用對(duì)話框4.2.5創(chuàng)建對(duì)話框類
在對(duì)話框資源範(fàn)本的空白區(qū)域內(nèi)雙擊滑鼠,彈出對(duì)話框,詢問(wèn)是否為對(duì)話框資源創(chuàng)建一個(gè)新類。單擊[OK]按鈕,彈出NewClass對(duì)話框。Name框是用來(lái)輸入用戶定義的類名,單擊[Change]按鈕可改變默認(rèn)的原始檔案名稱及其在磁片中的位置。從Baseclass框的內(nèi)容看出,用戶對(duì)話框類是從基類CDialog派生而來(lái)的。在Name框中輸入類名CFirstDlg,單擊[O
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 工作總結(jié)之互聯(lián)網(wǎng)實(shí)習(xí)總結(jié)
- 2024年無(wú)機(jī)械動(dòng)力飛機(jī)項(xiàng)目資金申請(qǐng)報(bào)告代可行性研究報(bào)告
- 《侵犯人身權(quán)利罪》課件
- 銀行員工績(jī)效評(píng)估制度
- 酒店餐飲服務(wù)流程優(yōu)化與提升制度
- 【大學(xué)課件】學(xué)習(xí)科學(xué)與技術(shù)
- 《保險(xiǎn)業(yè)務(wù)需求分析》課件
- 學(xué)生關(guān)于珍愛(ài)生命的演講稿(34篇)
- 陜西省咸陽(yáng)市武功縣2024屆九年級(jí)上學(xué)期期末考試數(shù)學(xué)試卷(含答案)
- 2024數(shù)字醫(yī)療年度創(chuàng)新白皮書(shū) 醫(yī)療大模型開(kāi)啟“百模大戰(zhàn)”數(shù)字醫(yī)療單筆融資創(chuàng)紀(jì)錄
- 財(cái)務(wù)共享服務(wù)建設(shè)方案
- 幕墻工程全面策劃創(chuàng)效指導(dǎo)清單
- 人教版(2019)高中生物選擇性必修2《生物與環(huán)境》全冊(cè)考點(diǎn)復(fù)習(xí)提綱
- 2024年四川省廣安市中考物理試題含答案
- 與信仰對(duì)話 課件-2024年入團(tuán)積極分子培訓(xùn)
- 湖南省岳陽(yáng)市2023-2024學(xué)年高一上學(xué)期1月期末聯(lián)考物理試題 含解析
- 涉水作業(yè)安全指導(dǎo)手冊(cè)
- 北京市道德與法治初二上學(xué)期期末試題與參考答案(2024年)
- 人教版數(shù)學(xué)五年級(jí)上冊(cè)期末考試試卷附答案
- 世界一流港口綜合評(píng)價(jià)報(bào)告
評(píng)論
0/150
提交評(píng)論