大綱:?
1. 類函數(shù)
2. 構(gòu)造函數(shù), 析構(gòu)函數(shù), 拷貝函數(shù)?
3.友元函數(shù)
4. 靜態(tài)變量
5. this指針
--------------------------------------------------
1. 類和對(duì)象
類只是一種復(fù)雜數(shù)據(jù)類型的聲明嘉栓,不占用內(nèi)存空間替饿。而對(duì)象是類這種數(shù)據(jù)類型的一個(gè)變量
類只是一張圖紙,起到說(shuō)明的作用摘符,不占用內(nèi)存空間;對(duì)象才是具體的零件喂急,要有地方來(lái)存放摊欠,才會(huì)占用內(nèi)存空間
類和結(jié)構(gòu)體的區(qū)別: 類里面可以放函數(shù)!?
2. 類的創(chuàng)建方式
new 關(guān)鍵字,new出來(lái)的是指針, 指針操作,通過(guò)箭頭—>, 指針不能用.對(duì)象才能用.
c++中,創(chuàng)建對(duì)象,是否要用new
有2種創(chuàng)建對(duì)象的方式!?
可以不申請(qǐng)new, 直接用嗎?
是的, 不new 直接用就是在棧中, 如果new就是在堆中!?
反問(wèn): 對(duì)象豈不是沒(méi)有空指針!? 如果不new處理 ,不走構(gòu)造函數(shù)??
可以在堆上創(chuàng)建也可以在棧上創(chuàng)建!?
很重要:? 如果是棧,對(duì)象在方法執(zhí)行完釋放了, 容易調(diào)用析構(gòu)函數(shù), 同時(shí)變量會(huì)被釋放! 會(huì)產(chǎn)生很大問(wèn)題(嚴(yán)重)
4.?類成員函數(shù)?
成員函數(shù)可以聲名, 成員函數(shù)也可以定義!?
成員函數(shù)可以定義在類定義內(nèi)部吠式,或者單獨(dú)使用范圍解析運(yùn)算符 ::?來(lái)定義,在 :: 運(yùn)算符之前必須使用類名
在類定義中定義的成員函數(shù)把函數(shù)聲明為內(nèi)聯(lián)的,即便沒(méi)有使用 inline 標(biāo)識(shí)符
類中的函數(shù),入?yún)?shù)可以是Void?
類中可以定義成員函數(shù), 沒(méi)有執(zhí)行題
need-to-insert-img
構(gòu)造函數(shù)也是函數(shù), 所以成員函數(shù)定義, 包括構(gòu)造函數(shù)
// 成員函數(shù)定義总寒,包括構(gòu)造函數(shù)
Line::Line( double len)
{
? ? cout << "Object is being created, length = " << len << endl;
? ? length = len;
}
類.start() 訪問(wèn)方法的話, 要把方法的實(shí)現(xiàn)改成類函數(shù)才能訪問(wèn)的到!?
need-to-insert-img
12. c++中::是什么意思
1).用于類成員函數(shù)
2).訪問(wèn)靜態(tài)函數(shù)
3).用于靜態(tài)變量的訪問(wèn)
總的來(lái)說(shuō): ::符號(hào)是用來(lái)訪問(wèn)函數(shù)的!?
例如:聲明了一個(gè)類A扶歪,類A里聲明了一個(gè)成員函數(shù)void f( ),但沒(méi)有在類的聲明里給出f的定義摄闸,那么在類外定義f時(shí)善镰, 就要寫成void A::f( ),表示這個(gè)f( )函數(shù)是類A的成員函數(shù)年枕。
不用 ::的話, 即使是public也不能訪問(wèn)到變量?
need-to-insert-img
5. 構(gòu)造函數(shù)中如何調(diào)用構(gòu)造函數(shù)?
錯(cuò)誤的寫法, 構(gòu)造函數(shù)不需要返回值
void Box::Box(){
}
應(yīng)該是這樣.和java一樣
Box::Box(){
}
比如java中的自定義View
6.析構(gòu)函數(shù)(只能有一個(gè))
臨終遺言:
java中的臨終遺言是: finalize
析構(gòu)函數(shù)(Destructor)也是一種特殊的成員函數(shù)炫欺,沒(méi)有返回值,不需要程序員顯式調(diào)用(程序員也沒(méi)法顯式調(diào)用)熏兄,而是在銷毀對(duì)象時(shí)自動(dòng)執(zhí)行
析構(gòu)函數(shù)的名稱與類的名稱是完全相同的品洛,只是在前面加了個(gè)波浪號(hào)(~)作為前綴,它不會(huì)返回任何值霍弹,也不能帶有任何參數(shù)毫别。析構(gòu)函數(shù)有助于在跳出程序(比如關(guān)閉文件、釋放內(nèi)存等)前釋放資源
classBox{
doublestate;
friendvoidstart(Boxbox);
public:
doublelength;
doublebreadth;
doubleheight;
voidset(doublelen,doublebre,doublehei);
doubleget();
Box();
~Box();
};
Box::~Box(){
cout<<"Box"<<"Box delete:"<<endl;
}
Box::Box(){
cout<<"Box"<<"Box create:"<<endl;
}
voidstart(Boxbox){
cout<<"start:"<<"ss:"<<endl;
}
doubleBox::get(){
returnlength*breadth*height;
}
voidBox::set(doublelen,doublebre,doublehei){
length=len;
breadth=bre;
height=hei;
}
intmain(){
Boxbox1;
box1.length=1.0;
box1.breadth=1.0;
box1.height=1.0;
box1.set(1.9,1.1,1.1);
start(box1);
cout<<"Box2 的體積:"<<box1.length<<endl;
return0;
}
結(jié)果:? 析構(gòu)函數(shù)執(zhí)行了2次!?
為啥2次, 方法釋放的時(shí)候調(diào)用??還是因?yàn)橛之a(chǎn)生了一個(gè)對(duì)象!?
應(yīng)該是方法執(zhí)行完, 棧被釋放了. 然后就調(diào)用了析構(gòu)函數(shù)!?
BoxBox create:
start:ss:
BoxBox delete:
Box2 的體積:1.9
BoxBox delete:
分析: 用到了棧, 然后傳遞了對(duì)象!!
正確寫法: 不要java那種寫法, 應(yīng)該傳遞地址!?
析構(gòu)函數(shù):如果有在對(duì)象內(nèi)部開(kāi)辟堆內(nèi)存典格,可以在析構(gòu)函數(shù)中釋放內(nèi)存
用 new 分配內(nèi)存時(shí)會(huì)調(diào)用構(gòu)造函數(shù)岛宦,用 delete 釋放內(nèi)存時(shí)會(huì)調(diào)用析構(gòu)函數(shù)()
new 創(chuàng)建的對(duì)象位于堆區(qū),通過(guò) delete 刪除時(shí)才會(huì)調(diào)用析構(gòu)函數(shù)耍缴;如果沒(méi)有 delete砾肺,析構(gòu)函數(shù)就不會(huì)被執(zhí)行挽霉。
如果是?new?的對(duì)象,則必須調(diào)用?delete?才會(huì)調(diào)用到析構(gòu)函數(shù), 如果用了c的free會(huì)怎么樣?
malloc/free 他們是一套变汪, new/delete 它們是一套
malloc/free 不會(huì)去調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)
new/delete 會(huì)調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)
7.? 拷貝構(gòu)造函數(shù) (很重要,會(huì)和析構(gòu)函數(shù)相結(jié)合)
拷貝構(gòu)造函數(shù)和構(gòu)造函數(shù)哪個(gè)先執(zhí)行?
調(diào)用構(gòu)造函數(shù)調(diào)用拷貝構(gòu)造函數(shù)并為指針 ptr 分配內(nèi)存
一個(gè)對(duì)象給另外一個(gè)對(duì)象賦值:?
Person person1={}
Person person2=person1;
賦值,是把所有的屬性賦值了! 原理: 調(diào)用了拷貝構(gòu)造函數(shù)!?
?這個(gè)拷貝是淺拷貝,拷貝的是值
使用場(chǎng)景:?
1. 作為參數(shù)返回的時(shí)候會(huì)調(diào)用拷貝構(gòu)造函數(shù)
2. 作為參數(shù)傳遞的時(shí)候會(huì)調(diào)用拷貝構(gòu)造函數(shù)!
3. 一般要重寫拷貝構(gòu)造函數(shù), 防止2次析構(gòu)導(dǎo)致異常(釋放)
classLine
{
public:
intgetLength(void);
Line(intlen);// 簡(jiǎn)單的構(gòu)造函數(shù)
Line(constLine&obj);// 拷貝構(gòu)造函數(shù)
~Line();
3.屬性私有,公有--------->想到有友元函數(shù)!?
關(guān)鍵字:privite和 public
默認(rèn)情況下侠坎,類的所有成員都是私有的
8. 友元函數(shù)---->為了訪問(wèn)類的私有函數(shù)或者屬性 (我么是朋友, 我可以訪問(wèn)你)
友元函數(shù)是不能用類::freind
類的友元函數(shù)是定義在類外部,但有權(quán)訪問(wèn)類的所有私有(private)成員和保護(hù)(protected)成員裙盾。盡管友元函數(shù)的原型有在類的定義中出現(xiàn)過(guò)实胸,但是友元函數(shù)并不是成員函數(shù)。
友元可以是一個(gè)函數(shù)番官,該函數(shù)被稱為友元函數(shù)庐完;友元也可以是一個(gè)類,該類被稱為友元類徘熔,在這種情況下门躯,整個(gè)類及其所有成員都是友元。
如果要聲明函數(shù)為一個(gè)類的友元酷师,需要在類定義中該函數(shù)原型前使用關(guān)鍵字?friend
注意: 1. 友元函數(shù)定義在類里面聲明, 不要在函數(shù)的實(shí)現(xiàn)里面定義!?
2. 友元函數(shù)的作用,是讓你可以通過(guò)方法訪問(wèn)類的私有屬性,而不是方法方法私有性!
/* 因?yàn)?printWidth() 是 Box 的友元讶凉,它可以直接訪問(wèn)該類的任何成員 */
所以定義的時(shí)候,這樣定義
friend void start(Box box);
need-to-insert-img
6.1 友元函數(shù)與普通函數(shù)的區(qū)別
友元函數(shù):直接方法名調(diào)用。
普通函數(shù):需要對(duì)象名::+方法名?調(diào)用
友元類是: 一個(gè)類里面放另一個(gè)類的定義! 哪個(gè)類定義了友元,服務(wù)于他本身!?
#include<iostream>
usingnamespacestd;
classCCar;//提前聲明CCar類山孔,以便后面的CDriver類使用
classCDriver
{
public:
voidModifyCar(CCar*pCar);//改裝汽車
};
classCCar
{
private:
intprice;
friendintMostExpensiveCar(CCarcars[],inttotal);//聲明友元
friendvoidCDriver::ModifyCar(CCar*pCar);//聲明友元
};
voidCDriver::ModifyCar(CCar*pCar)
{
pCar->price+=1000;//汽車改裝后價(jià)值增加
}
intMostExpensiveCar(CCarcars[],inttotal)//求最貴氣車的價(jià)格
{
inttmpMax=-1;
for(inti=0;i<total;++i)
if(cars[i].price>tmpMax)
tmpMax=cars[i].price;
returntmpMax;
}
intmain()
{
return0;
}
9. 靜態(tài)變量和靜態(tài)函數(shù)
c++沒(méi)有靜態(tài)類, 但是有靜態(tài)變量和靜態(tài)方法!?
內(nèi)存中位置: 棧? 堆? 常量池?
它在常量池中, 不在棧, 也不在堆中!?
靜態(tài)屬性在c++中必須要出時(shí)候,初始化必須這么寫,?靜態(tài)成員變量必須初始化懂讯,而且只能在類體外進(jìn)行! 否則報(bào)錯(cuò),如下
need-to-insert-img
? ?static int objectCount;
定義初始化這么定義:?
int Box::objectCount=10;
而不是這樣;
? static int objectCount=10;
可是有時(shí)候我們希望在多個(gè)對(duì)象之間共享數(shù)據(jù),對(duì)象 a 改變了某份數(shù)據(jù)后對(duì)象 b 可以檢測(cè)到饱须。
共享數(shù)據(jù)的典型使用場(chǎng)景是計(jì)數(shù)域醇,以前面的 Student 類為例,如果我們想知道班級(jí)中共有多少名學(xué)生蓉媳,就可以設(shè)置一份共享的變量譬挚,每次創(chuàng)建對(duì)象時(shí)讓該變量加 1
我們可以使用靜態(tài)成員變量來(lái)實(shí)現(xiàn)多個(gè)對(duì)象共享數(shù)據(jù)的目標(biāo)。
運(yùn)算符?::?來(lái)重新聲明靜態(tài)變量從而對(duì)它進(jìn)行初始化
類的靜態(tài)成員變量為什么必須得在類外初始化酪呻?
我的理解: 由于靜態(tài)變量在編譯期間必須初始化减宣,全局變量的靜態(tài)或者非靜態(tài)的變量都可以賦初值0。而類中的變量要用構(gòu)造函數(shù)來(lái)初始化玩荠,但是在編譯期間沒(méi)有創(chuàng)造對(duì)象漆腌,所以就沒(méi)有運(yùn)行構(gòu)造方法。故在編譯期間沒(méi)有給類的靜態(tài)變量初始化阶冈。所以要在類外 main之前要給該靜態(tài)變量初始化闷尿,不管該靜態(tài)變量的作用域?yàn)閜rivate還是public,因?yàn)榫幾g期間private沒(méi)有影響女坑。但是一旦進(jìn)入運(yùn)行時(shí)填具,就不可以調(diào)用類中的private變量。
static int objectCount;
cout << "Total objects: " << Box::objectCount << endl;
2. static 關(guān)鍵字
總結(jié):
靜態(tài)的屬性定義時(shí)**必須要初始化** (實(shí)現(xiàn))?int Student::tag = 12;
靜態(tài) 可以直接用類名去操作 ::?Student::tag += 12;
靜態(tài)的方法只能去操作靜態(tài)的屬性或者方法
10.自帶this指針
this 是 const 指針,原因: 他是共享的,?它的值是不能被修改的.?
在 C++ 中劳景,每一個(gè)對(duì)象都能通過(guò)?this?指針來(lái)訪問(wèn)自己的地址誉简。this?指針是所有成員函數(shù)的隱含參數(shù)。因此盟广,在成員函數(shù)內(nèi)部闷串,它可以用來(lái)指向調(diào)用對(duì)象。
不用this, 在類的內(nèi)部, 也可以訪問(wèn)里面的變量和訪問(wèn),那么為什么還要this?
和java一樣, 為了防止全局變量名和局部變量名!?
友元函數(shù)沒(méi)有?this?指針筋量,因?yàn)橛言皇穷惖某蓡T烹吵。只有成員函數(shù)才有?this?指針。
有指針, 指針訪問(wèn)變量或者函數(shù)可以通過(guò) -->的方式!?
需要對(duì) C 結(jié)構(gòu)有基本的了解毛甲,并懂得如何使用箭頭 -> 運(yùn)算符來(lái)訪問(wèn)結(jié)構(gòu)成員年叮。
cout?<<?"月:?"<<?1?+?ltm->tm_mon<<?endl;
void func()??{? ??
? ? static int val;
}
中,變量 val 的內(nèi)存地址位于:?
A. 已初始化數(shù)據(jù)段
B.未初始化數(shù)據(jù)段? ???
C.堆
D.棧?
【標(biāo)準(zhǔn)答案】B
11. 要定義.h文件,原因是!
12. 對(duì)象大小