?一、類
1枯饿、C++擴(kuò)充的結(jié)構(gòu)體一般格式如下:
? struct 結(jié)構(gòu)名 {
???? 數(shù)據(jù)番川;//數(shù)據(jù)成員
???? 函數(shù)邑狸;//成員函數(shù)
? }懈糯;
Complex? A;//定義結(jié)構(gòu)體Complex的[變量A]
?A.init(1.1,2.2);//?調(diào)用成員函數(shù)init,給real和imag賦初值.【編譯通過】
因?yàn)樵谀J(rèn)情況下,結(jié)構(gòu)體中的成員是公有的单雾。
2赚哗、類類型代替結(jié)構(gòu)體類型
Complex? A;//定義類Complex的[對象A]
?A.init(1.1,2.2);//【編譯不通過】
因?yàn)樗接谐蓡T不能被類外的對象訪問,編譯錯(cuò)誤硅堆。
總結(jié):????
類和結(jié)構(gòu)的主要區(qū)別是:?在默認(rèn)情況下,
??? ?【結(jié)構(gòu)體中的成員是公有的;
? ? ? ? 類中的成員是私有的】屿储。
? ??????常見的叫法:【聲明類、定義對象】
說明:
1硬萍、不能在類聲明中給數(shù)據(jù)成員賦初值,只有在對象定義之后才能給數(shù)據(jù)成員賦初值围详。
????class?abc {
????? private:
????????char a=‘q’朴乖;//錯(cuò)誤
? ??? ??int? b=33;//錯(cuò)誤
};
3助赞、成員函數(shù)的聲明(在類中)與定義【三種】
第一種定義方式:在類聲明中只給出成員函數(shù)的原型买羞,而將成員函數(shù)的定義放在類外部。
第二種定義方式:將成員函數(shù)直接定義在類內(nèi)部雹食,編譯時(shí)是作為內(nèi)聯(lián)函數(shù)的方式來處理(內(nèi)聯(lián)函數(shù)隱式定義)
第三種方式:在類外部成員函數(shù)的定義前冠以關(guān)鍵字“inline”,使它起到內(nèi)聯(lián)函數(shù)的作用畜普。【代碼置換作用】
4群叶、對象的定義【兩種】
方法1:在聲明類的同時(shí)吃挑,直接定義對象,即在聲明類的右花括號“ }”后街立,直接寫出屬于該類的對象名表舶衬。
? ?class?Student{【聲明類】
??????//..? ..
???}? stu1,stu2;
? 方法 2:?聲明了類之后,在使用時(shí)再定義對象赎离。?
? class? Student {
???????// …
? } ;
?Student? stu1, stu2逛犹;
請注意:
1、聲明了一個(gè)類便聲明了一種類型梁剔,這時(shí)沒有給它分配存儲空間虽画,只有定義了對象后,系統(tǒng)才為對象分配存儲空間荣病。
5码撰、對象中成員的訪問【三種】
(1) 通過對象名和對象選擇符訪問對象中的成員(“.”操作符)
注:類外部的對象可以通過公有成員函數(shù)對私有成員進(jìn)行間接訪問
(2)通過指向?qū)ο蟮闹羔?/b>訪問對象中的成員(“->”操作符)
Date d, *ptr;??? //定義對象d和指向類Date的指針變量ptr
ptr=&d;????????? //使ptr指向?qū)ο骴
cout<<ptr->year; ?//輸出ptr指向?qū)ο笾械某蓡Tyear
(3)通過對象的引用訪問對象中的成員
Date d1; //定義類Date的對象d1
Date &d2=d1; //定義類Date的引用d2,
cout<<d1.year;
cout<<d2.year;
6、類的作用域和類成員的訪問屬性
所謂類的作用域就是指【在類的聲明中的一對花括號所形成的作用域】
二个盆、構(gòu)造函數(shù)與析構(gòu)函數(shù)
都是一種特殊的成員函數(shù)
1灸拍、對象的定義
2做祝、對象的初始化
3、 對象的初始化可采用以下幾種方法:【三種】
? ? 1. 定義對象時(shí)對數(shù)據(jù)成員直接賦值
? ? ? ? Complex c1={1.1,2.2};
????????//注意{}號鸡岗,[要求類中所有的成員,都是公有的]
? ? 2. 調(diào)用普通的成員函數(shù)來完成【常用】
? ? ? Complex A;
? ? ? A.init(1.1,2.2);
? ? 3. 調(diào)用構(gòu)造函數(shù)來完成【重視】
【構(gòu)造函數(shù):它是在定義對象的同時(shí)被自動(dòng)調(diào)用的】混槐。
【默認(rèn)構(gòu)造函數(shù):不帶任何參數(shù),只能為對象開辟一個(gè)存儲空間,而不能給對象中的數(shù)據(jù)成員賦初值⌒裕】
?形式一: 類名 對象名[(實(shí)參表)];//【注意與java的初始化不一樣声登,無new】
? ??????Complex A(1.1,2.2);// 建立對象時(shí),編譯系統(tǒng)會自動(dòng)地調(diào)用構(gòu)造函數(shù),對對象進(jìn)行初始化
形式二:類名 *指針變量名=new 類名[(實(shí)參表)];
????????Complex *pa = new Complex(1.1,2.2);
例如:下面的用法是錯(cuò)誤的:
? ???????? A.Complex(1.1,2.2);(X)
三揣苏、用成員初始化列表對【數(shù)據(jù)成員初始化】
1悯嗓、在【構(gòu)造函數(shù)】中一般用【賦值語句】對數(shù)據(jù)成員的初始化進(jìn)行
2、用【成員初始化列表】來實(shí)現(xiàn)對數(shù)據(jù)成員的初始化
A(int i1卸察,float f1):i(i1),f(f1){ [記一下]
// i=i1脯厨;
// f=f1
}
說明:
1、【對于用const修飾的數(shù)據(jù)成員】坑质,或是【引用類型的數(shù)據(jù)成員】,是不允許用賦值語句直接賦值的合武。因此,只能用成員初始化列表對其進(jìn)行初始化。
2涡扼、數(shù)據(jù)成員是按照它們在類中聲明的順序進(jìn)行初始化的,與它們在成員初始化列表中列出的順序無關(guān)稼跳。
四、構(gòu)造函數(shù)的重載
只要一個(gè)類定義了一個(gè)構(gòu)造函數(shù),系統(tǒng)將不再給它提供默認(rèn)的構(gòu)造函數(shù)吃沪。
定義對象A3時(shí),不能調(diào)用自動(dòng)生成的默認(rèn)的構(gòu)造函數(shù),于是出現(xiàn)【編譯出錯(cuò)】汤善。
五、帶【默認(rèn)參數(shù)】的構(gòu)造函數(shù)
為什么要使用默認(rèn)參數(shù):【因?yàn)橛行?gòu)造函數(shù)的參數(shù)值在大部分情況是相同的票彪,例如大學(xué)學(xué)年制度4年】
調(diào)用構(gòu)造函數(shù)產(chǎn)生的【二義性】:
聲明了Complex(double r=0.0,double i=0.0);
就不能再聲明無參數(shù)的構(gòu)造函數(shù)Complex( );
Complex S1; 因?yàn)檎{(diào)用這句語句時(shí)红淡,編譯系統(tǒng)將無法判斷應(yīng)該調(diào)用哪個(gè)構(gòu)造函數(shù),因此產(chǎn)生了二義性
六、析構(gòu)函數(shù)
任務(wù)有:
1. 釋放分配給對象的內(nèi)存空間降铸。
2. 其他指定的任務(wù)
識別:
①析構(gòu)函數(shù)與類名相同锉屈,但它前面必須加一個(gè)波浪號(~)
②析構(gòu)函數(shù)沒有參數(shù),也沒有返回值垮耳,因此它不能被重載颈渊。
③當(dāng)撤消對象時(shí),編譯系統(tǒng)會自動(dòng)地調(diào)用析構(gòu)函數(shù)
一個(gè)類可以有多個(gè)構(gòu)造函數(shù),但是只能有一個(gè)析構(gòu)函數(shù)终佛。
說明:
?(1) 若沒有顯式地為一個(gè)類定義析構(gòu)函數(shù)俊嗽,編譯系統(tǒng)會自動(dòng)地生成一個(gè)缺省的析構(gòu)函數(shù)。
Student∷~student(){?
}
在以下情況,對象將被撤消铃彰,編譯系統(tǒng)也會自動(dòng)地調(diào)用析構(gòu)函數(shù):
① 主程序main()運(yùn)行結(jié)束绍豁。
② 如果一個(gè)對象被定義在一個(gè)函數(shù)體內(nèi),則當(dāng)這個(gè)函數(shù)結(jié)束時(shí),該對象的析構(gòu)函數(shù)被自動(dòng)調(diào)用。
?③ 若一個(gè)對象是使用new運(yùn)算符動(dòng)態(tài)創(chuàng)建的,在使用delete運(yùn)算符釋放它時(shí),delete會自動(dòng)調(diào)用析構(gòu)函數(shù)
7牙捉、對象數(shù)組與對象指針
(1)對象數(shù)組初始化方法:
情況一:帶有一個(gè)參數(shù)的構(gòu)造函數(shù)【兩種】
構(gòu)造函數(shù)只有一個(gè)參數(shù)exam(int n){ x=n; }
exam ob[4]={11, 22, 33, 44};//通過[初始值表]給對象數(shù)組賦值
exam ob[4]={exam(11), exam(22),exam(33), exam(44)};//通過[初始值表]給對象數(shù)組賦值的另一種方法[記一下竹揍,因?yàn)椴怀S玫絔
情況二:不帶參數(shù)的構(gòu)造函數(shù)和帶一個(gè)參數(shù)的構(gòu)造函數(shù)
exam( ){ x=123;}
exam(int n) { x=n;}
exam ob[4]={55,66};
for循環(huán)打印運(yùn)行結(jié)果: 55 66 123 123
情況三:帶有多個(gè)參數(shù)的構(gòu)造函數(shù)[記一下敬飒,難理解,可以用構(gòu)造函數(shù)直接初始化對象]
Box(int h=10,int w=10,int len=10) { height=h; width=w; length=len; }
Box box1[3]={ Box(10,12,15)芬位,Box(15,18,20), Box(16,20,26) }//box1[0]无拗,box1[1],box1[2]
(2)對象指針
1昧碉、對象指針就是用于存放對象地址的指針變量英染。
exe *p;? //定義類exe的對象指針變量P
2、用對象指針訪問對象數(shù)組[也記一下]
? ? exe *p被饿;? ? //定義對象指針變量p
? ? exe ob[2];? ?//定義對象數(shù)組ob[2]
? ? p=ob四康;? ? ? //把對象數(shù)組的第一個(gè)元素的地址賦給對象指針變量p
????p++;? ? ? ? //訪問第二個(gè)元素
3狭握、this指針
this指針屬于對象指針
當(dāng)一個(gè)對象要調(diào)用成員函數(shù)時(shí)闪金,this指針中就裝著該對象的地址, 成員函數(shù)就根據(jù)這個(gè)指針,找到相應(yīng)的數(shù)據(jù),然而進(jìn)行相應(yīng)的操作。
例如:當(dāng)執(zhí)行a.disp()時(shí)论颅,相當(dāng)于執(zhí)行cout<<"\nthis="<<&a<<"when x="<<a.x
存在形式:可隱可顯
4哎垦、string類
string str1,str2;? ?//定義string類對象str1和str2
string str3(“China”);??//定義string類對象str3,同時(shí)對其初始化
5嗅辣、向函數(shù)傳遞對象
(1)傳值參數(shù)
(2)傳址調(diào)用?
用變量指針做函數(shù)參數(shù)????swap(int* m,int* n){}
調(diào)用???? swap(&a,&b)撼泛;
(3)傳址調(diào)用
void swap(int& m,int& n){}
swap(a,b)挠说;
(4)對象作為參數(shù)
?傳值調(diào)用:
void swap(op ob){}
obj.swap(obj);
傳址調(diào)用:
void swap(op *ob){}
obj.swap(&obj);
(5)對象引用作為參數(shù)【更加方便直接】
void swap(op &ob){}
obj.swap(obj);
6澡谭、對象的賦值和拷貝
對象的賦值說明:
(1)在使用對象賦值語句進(jìn)行對象賦值時(shí),兩個(gè)對象的類型必須相同损俭,否則編譯錯(cuò)誤
(2) 對象賦值是通過默認(rèn)賦值運(yùn)算符函數(shù)實(shí)現(xiàn)的
拷貝構(gòu)造函數(shù):其作用是在建立一個(gè)新對象時(shí),使用一個(gè)已經(jīng)存在的對象去初始化這個(gè)新對象蛙奖。
Point p2(p1);
point(int a,int b) //構(gòu)造函數(shù)
{x=a杆兵;y=b}
point(const point& p) //自定義拷貝構(gòu)造函數(shù)雁仲,相當(dāng)于: const point& p=p1
注還有一個(gè)默認(rèn)的拷貝構(gòu)造函數(shù),代碼不給出
特點(diǎn):
①該函數(shù)與類同名,并且不能指定返回值類型(因?yàn)樗彩且环N構(gòu)造函數(shù))
②該函數(shù)只有一個(gè)參數(shù),并且是同類對象的引用
③每個(gè)類必須有一個(gè)拷貝構(gòu)造函數(shù)
調(diào)用拷貝構(gòu)造函數(shù)的兩種方法:
? ①? “代入”法調(diào)用 point p2(p1);
? ②? “賦值”法調(diào)用 point? p2=p1;
調(diào)用拷貝構(gòu)造函數(shù)的三種情況:P124-P126(不易理解)
(1) 當(dāng)用類的一個(gè)對象去初始化該類的另一個(gè)對象時(shí)
(2) 當(dāng)函數(shù)的形參是類的對象, 在調(diào)用函數(shù)進(jìn)行形參和實(shí)參結(jié)合時(shí)
(3) 當(dāng)函數(shù)的返回值是類的對象, 在函數(shù)調(diào)用完畢將返回值(對象)帶回函數(shù)調(diào)用處時(shí)
P128
8琐脏、靜態(tài)成員
1攒砖、靜態(tài)數(shù)據(jù)成員---訪問
private:
????int count;
public:
????Student( ) { count++;? }
main(){
????int count=0;
????Stu1.count?
????Stu2.count}
實(shí)際打印結(jié)果:?count=0 count= -858993459count= -858993459
二者是獨(dú)立的,互不相干
分析:一個(gè)學(xué)生對象的count僅僅屬于這個(gè)學(xué)生對象,而不是所有學(xué)生對象所共享的,因此count不能表示所有學(xué)生的總?cè)藬?shù)
解決辦法:為了實(shí)現(xiàn)同一個(gè)類的多個(gè)對象之間的數(shù)據(jù)【共享】,C++提出了【靜態(tài)數(shù)據(jù)成員】的概念日裙。
private:
????static int count;
用類名訪問靜態(tài)數(shù)據(jù)成員并初始化int Student::count=0;
說明:
(1) 靜態(tài)數(shù)據(jù)成員屬于類(準(zhǔn)確地說吹艇,是屬于類中一個(gè)對象集合),而不像普通數(shù)據(jù)成員那樣屬于某一對象昂拂,因此可以使用“類名∷”訪問靜態(tài)的數(shù)據(jù)成員受神。
(2) 靜態(tài)數(shù)據(jù)成員初始化應(yīng)在類外單獨(dú)進(jìn)行,而且應(yīng)在定義對象之前進(jìn)行。一般在主函數(shù)main?之前,類聲明之后的特殊地帶為它提供定義和初始化格侯。
(3) 如果末對靜態(tài)數(shù)據(jù)成員賦初值,則編譯系統(tǒng)會自動(dòng)賦予初值0鼻听。
(4)公有靜態(tài)數(shù)據(jù)成員可以在對象定義之前被訪問[下圖]
(5)公有靜態(tài)數(shù)據(jù)成員可通過對象進(jìn)行訪問[下圖]
(6) 私有的靜態(tài)數(shù)據(jù)成員不能被外界直接訪問财著。必須通過公有的成員函數(shù)間接訪問
(7) C++支持靜態(tài)數(shù)據(jù)成員的一個(gè)主要原因是可以不必使用全局變量,靜態(tài)數(shù)據(jù)成員的主要用途是定義各個(gè)對象所公用的數(shù)據(jù)撑碴,如統(tǒng)計(jì)總數(shù)撑教、平均數(shù)等。
2灰羽、靜態(tài)成員函數(shù)static---調(diào)用
靜態(tài)成員函數(shù)屬于整個(gè)類驮履,是該類所有對象共享的成員函數(shù),而不屬于類中的某個(gè)對象廉嚼。
調(diào)用公有靜態(tài)成員函數(shù)的一般格式有如下幾種:
? ? 類名::靜態(tài)成員函數(shù)名(實(shí)參表)
? ? 對象.靜態(tài)成員函數(shù)名(實(shí)參表)
? ? 對象指針->靜態(tài)成員函數(shù)名(實(shí)參表)
說明:
(1) 一般情況下,靜態(tài)函數(shù)成員主要用來訪問靜態(tài)數(shù)據(jù)成員玫镐,達(dá)到了對同一個(gè)類中對象之間共享數(shù)據(jù)的目的。
(2)靜態(tài)成員函數(shù)一般為公有的
(3) 使用靜態(tài)成員函數(shù)的一個(gè)原因是,可以在建立任何對象之前調(diào)用靜態(tài)成員函數(shù),以處理靜態(tài)數(shù)據(jù)成員,這是普通成員函數(shù)不能實(shí)現(xiàn)的功能怠噪。
int main()
? { Small_cat::total_disp();?
? ? Small_cat w1(0.5),w2(0.6),w3(0.4);
? ? …
? ? return 0;}
(4) 編譯系統(tǒng)將靜態(tài)成員函數(shù)限定為內(nèi)部連接,與現(xiàn)行文件相連接的其他文件中的同名函數(shù)不會與該函數(shù)發(fā)生沖突恐似。
(6) 一般而言,靜態(tài)成員函數(shù)不訪問類中的非靜態(tài)成員,非靜態(tài)成員由普通成員函數(shù)訪問?
(7)若靜態(tài)成員函數(shù)需要訪問非靜態(tài)成員傍念,靜態(tài)成員函數(shù)只能通過對象名(對象指針或引用)訪問該對象的非靜態(tài)成員矫夷。
9、友元函數(shù)
A憋槐、【友元函數(shù)不是當(dāng)前類的成員函數(shù):所以它不能直接調(diào)用對象成員双藕,它必須通過對象(對象指針或?qū)ο笠?作為入口參數(shù),來調(diào)用該對象的成員】,但它可以訪問該類所有的成員,包括私有成員(從而提高了程序運(yùn)行的效率)、保護(hù)成員和公有成員阳仔。在類中聲明友元函數(shù)時(shí),需在其函數(shù)名前加上關(guān)鍵字friend
調(diào)用友元函數(shù):
main(){
disp(g1); } //調(diào)用友元函數(shù)}
說明:
(1) 一個(gè)函數(shù)可以是多個(gè)類的友元函數(shù)忧陪。【當(dāng)一個(gè)函數(shù)需要訪問多個(gè)類時(shí)近范,友元函數(shù)非常有用】
例如; 定義函數(shù)prdata()是類girl和類boy的友元函數(shù)[記得要其中一個(gè)類的提前引用聲明]
(2)不足之處: 破壞了數(shù)據(jù)的隱蔽性和類的封裝性
B嘶摊、友元成員函數(shù)
一個(gè)類的成員函數(shù)也可以作為另一個(gè)類的友元,這種成員函數(shù)稱為【友元成員函數(shù)】评矩,友元成員函數(shù)不僅可以訪問自己所在類對象中的私有成員和公有成員,還可以訪問friend聲明語句所在類對象中的所有成員
C叶堆、友元類
一個(gè)類可以作為另一個(gè)類的友元
說明方法是在另一個(gè)類聲明中加入語句:friend 類名;
class Y { … };
class X {
? ? ? friend? Y斥杜;//類Y中的所有成員函數(shù)都可以訪問類X中的公有和私有成員
? ? }虱颗;
D、類的組合
在一個(gè)類中內(nèi)嵌另一個(gè)類的對象作為數(shù)據(jù)成員,稱為類的組合蔗喂。該內(nèi)嵌對象稱為對象成員,也稱為子對象
E忘渔、?常引用
如果在說明引用時(shí)用const修飾,只能讀弱恒,不能寫,則被說明的引用為常引用辨萍。
F、?常對象【 在定義對象時(shí)必須進(jìn)行初始化,且不能更新】
類名 const 對象名[(參數(shù)表)];
或
const 類名 對象名[(參數(shù)表)];
需要注意的地方:
錯(cuò)誤1:不允許間接地更改常對象的數(shù)據(jù)成員
錯(cuò)誤2:不允許直接更改常對象的數(shù)據(jù)成員
錯(cuò)誤3:不允許常對象調(diào)用普通的成員函數(shù)【常對象只能調(diào)用它的常成員函數(shù),而不能調(diào)用普通的成員函數(shù)】
G锈玉、常對象成員
1爪飘、使用const說明的數(shù)據(jù)成員
只能通過初始化列表對該數(shù)據(jù)成員進(jìn)行初始化
Date::Date(int y,int m,int d) :year(y),month(m),day(d)
{ }
2、常成員函數(shù)
void showDate();//普通成員函數(shù)
void showDate() const;//常成員函數(shù)
void Date::showDate() const//別忘了,這里也要加上const