博覽網(wǎng):C++面向?qū)ο蟾呒壘幊蹋ㄏ拢┑诙芄P記

一斋泄、虛指正(vptr)和虛表(vtbl)

我們以下圖介紹上述兩者:

1岔留、當(dāng)類中存在虛函數(shù)就會出現(xiàn)虛指針vpt吨拗,無論虛函數(shù)有多少個庵佣,有且僅有一個虛函數(shù)歉胶,指向虛表(rvtbl)的地址;

2巴粪、虛表是什么呢??

我們可以將它理解為一種表格通今,每個表格的位置存放一個虛函數(shù)對應(yīng)內(nèi)存的地址;

例如:基類A中包含兩個虛函數(shù)vfunc1()肛根、vfunc2()辫塌,那么類A的對象在在內(nèi)存中表現(xiàn)如上圖a(A object),其存儲類的兩個基本數(shù)據(jù):m_data1派哲、2m_data2以及兩個虛函數(shù)對應(yīng)的虛指針vptr臼氨,而虛指針指向虛表的地址,虛表存放虛函數(shù)內(nèi)存的兩個地址:0x401ED0芭届、0x401FD0储矩;同理,A類的子類B褂乍,B類的子類C也有類似的原理持隧;

將vptr實現(xiàn)vtbl內(nèi)容翻譯為C:

(*p->vptr)n;

(* p->vptr[n])(p);

3、動態(tài)綁定: 虛機制

動態(tài)綁定(dynamic binding):動態(tài)綁定是指在執(zhí)行期間(非編譯期)判斷所引用對象的實際類型逃片,根據(jù)其實際的類型調(diào)用其相應(yīng)的方法屡拨。

C++中,通過基類的引用或指針調(diào)用虛函數(shù)時褥实,發(fā)生動態(tài)綁定呀狼。引用(或指針)既可以指向基類對象也可以指向派生類對象,這一事實是動態(tài)綁定的關(guān)鍵损离。用引用(或指針)調(diào)用的虛函數(shù)在運行時確定哥艇,被調(diào)用的函數(shù)是引用(或指針)所指對象的實際類型所定義的;

C++中動態(tài)綁定條件發(fā)生需要滿足2個條件:

(1)只有指定為虛函數(shù)的成員函數(shù)才能進行動態(tài)綁定草冈,成員函數(shù)默認為非虛函數(shù)她奥,非虛函數(shù)不能進行動態(tài)綁定

(2)必須通過基類類型的引用或指針進行函數(shù)調(diào)用

所謂的動態(tài)類型,當(dāng)引用或指針調(diào)用了虛函數(shù)時怎棱,它就是動態(tài)類型,它的行為要到程序運行時才能定義 绷跑;

當(dāng)我們用派生類去初始化基類的引用或指針后拳恋,假如調(diào)用的是非虛函數(shù),那么這時實際調(diào)用的函數(shù)是基類的函數(shù)砸捏;假如調(diào)用的是虛函數(shù)谬运,那么這是調(diào)用的是派生類自己定義的虛函數(shù) ?下面是具體的例子來說明靜態(tài)類型和動態(tài)類型

class A{

public:

virtual void show(){cout<<"j基類的show()"<

void get(){cout<<"基類的get()"<

};

class B:public A{

public:

virtual void show(){cout<<“派生類的show()”<

void get(){cout<<"派生類的get()"<

};

main:

A a;

B b;

A &c=b;

c.show();//show函數(shù)是虛函數(shù)隙赁,并且此時使用派生類的對象去初始化基類的引用,發(fā)生了動態(tài)綁定梆暖,調(diào)用的是實際類        型B的show()----"派生類的show"

c.get();//此時不滿足動態(tài)綁定的條件伞访,c是靜態(tài)類型,結(jié)果是-------基類的get()

二轰驳、this指針

1厚掷、C++this指針,一個對象的this指針并不是對象本身的一部分级解,不會影響sizeof(對象)的結(jié)果冒黑。this作用域是在類內(nèi)部,當(dāng)在類的非靜態(tài)成員函數(shù)中訪問類的非靜態(tài)成員的時候勤哗,編譯器會自動將對象本身的地址作為一個隱含參數(shù)傳遞給函數(shù)抡爹。this指針是類的一個自動生成、自動隱藏的私有成員冬竟,它存在于類的非靜態(tài)成員函數(shù)中,指向被調(diào)用函數(shù)所在的對象民逼。全局僅有一個this指針,當(dāng)一個對象被創(chuàng)建時袋狞,this指針就存放指向?qū)ο髷?shù)據(jù)的首地址;

注:簡單點說早处,通過一個對象調(diào)用函數(shù)時,函數(shù)的地址就是this贬循;

舉例:

父類CDocument

子類CMyDoc,子類對虛函數(shù)Serialise()進行了重新定義咸包;

通過語句myDoc.OnFileOpen()調(diào)用父類函數(shù)時,子類對象myDoc的地址即為this杖虾,上述語句可表述為:CDocument::OnFileOpen(&myDoc)烂瘫,&myDoc就是this,this調(diào)用虛函數(shù)奇适,進行動態(tài)綁定坟比,通過this->Serialize()調(diào)用了子類的虛函數(shù)芦鳍,而不是父類的虛函數(shù),this->Serialize()也可以表達為虛指針葛账、虛表的形式柠衅,即:*(this->vptr)[n](this),這樣我們就可以更好的理解this以及虛機制籍琳;

三.動態(tài)綁定

再第一章節(jié)已介紹過動態(tài)綁定菲宴,這里就不再贅述;

四巩割、const

課件中已做了詳細的介紹裙顽,我這里簡單總結(jié)下,并做些衍生:

1宣谈、常數(shù)對象可以調(diào)用常函數(shù)愈犹;

非常數(shù)對象可以調(diào)用常函數(shù);

常數(shù)對象不可以調(diào)用非常函數(shù)闻丑;

非常數(shù)對象可以調(diào)用非常函數(shù)漩怎;

注:當(dāng)成員函數(shù)的常數(shù)版本和非常版本同時存在時(以函數(shù)重載形式出現(xiàn)),常數(shù)對象只可以調(diào)用常函數(shù)嗦嗡;非常數(shù)對象只可以調(diào)用非常函數(shù)勋锤。

2、注意的幾點:

1)const一般放在成員函數(shù)后頭,不放在全局函數(shù)后頭侥祭, 例:void function() const { return data;} 叁执;

2)在成員函數(shù)后面加const是屬于簽名, 就是當(dāng)兩個成員函數(shù)傳參相同,那么加不加const也會被區(qū)分成兩個函數(shù). ;

3矮冬、const的其他使用方法:

1)定義常量

(1)const修飾變量谈宛,以下兩種定義形式在本質(zhì)上是一樣的。

它的含義是:const修飾的類型為TYPE的變量value是不可變的胎署。

TYPE const ValueName = value;

const TYPE ValueName = value;

(2)將const改為外部連接,作用于擴大至全局,編譯時會分配內(nèi)存,并且可以不進行初始化,僅僅作為聲明,編譯器認為在程序其他地方進行了定義.

extend const int ValueName = value;

2)指針使用CONST

(1)指針本身是常量不可變

char* const pContent;

(2)指針?biāo)赶虻膬?nèi)容是常量不可變

const char *pContent;

(3)兩者都不可變

const char* const pContent;

(4)還有其中區(qū)別方法吆录,沿著*號劃一條線: 如果const位于*的左側(cè),則const就是用來修飾指針?biāo)赶虻淖兞壳砟粒粗羔樦赶驗槌A浚?如果const位于*的右側(cè)恢筝,const就是修飾指針本身,即指針本身是常量巨坊。

五撬槽、關(guān)于New,Delete

new對象的流程不能更改,但是實現(xiàn)過程中的函數(shù)可以被更改.

operator new

operator delete

array new一定要array delete;

回憶前邊的內(nèi)容:delete 某個對象抱究,其實質(zhì)是先調(diào)用析構(gòu)函數(shù)恢氯,再釋放內(nèi)存

六、重載::operator new, ::operator new[],::operator delete ,::operator delete[]

在全局當(dāng)中:

Note: 如果你重載了全局的操作符, 所以要額外小心.

這些重載不可以被聲明在一個namespace中.

//這里的函數(shù)是編譯器去調(diào)用, 所以size是編譯器給出.

void* operator new( size_t size )

{ return malloc(size);}

void* operator new[]( size_t size )

{ return malloc(size);}

void* operator delete(void* ptr )

{ free(ptr);}

void* operator delete[](void* ptr )

{ free(ptr);}

重載 member new , delete

在class里面重載new, delete

class foo{

public:

void* operator new(size_t size);

void operator delete(void *, size_t size); //size為可選

…….

};

那么你在:

foo *a = new foo;

delete a;

就會調(diào)用上面重載的函數(shù).

new[] , delete[] 也如此.

七鼓寺、實例

當(dāng)類中重載了new , delete , 而又想調(diào)用全局的new , delete

可以這樣寫:

::delete a;

string類內(nèi)其實是一個指針.

當(dāng)創(chuàng)建一個數(shù)組的時候, 內(nèi)存當(dāng)中就會多分配一個指針,該指針用于保存當(dāng)前數(shù)組個數(shù).

八勋拟、重載new(),delete()示例

允許重載成員函數(shù)new(….) 其中參數(shù)中,必須有第一個且第一個必須是size_t size. 其余參數(shù)以new所指定的placement argument為初值.

Foo* p = new(300,’c’)Foo; //這里是三個參數(shù)

我們也可以重載類成員函數(shù) operator delete() ,寫出多個版本. 但他們絕不會被 通常所使用的delete調(diào)用.只有當(dāng)new所調(diào)用的ctor拋出 異常,才會調(diào)用這些重載版的operator delete(). 它們只能這樣被調(diào)用,主要用來歸還未能完全創(chuàng)建成功的對象所占用的內(nèi)存.

九、Basic_String使用new(extra)擴充申請量

Basic_String在重載new()過后妈候,傳遞了一個extra參數(shù)敢靡, 用于后臺自動多申請extra空間。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末苦银,一起剝皮案震驚了整個濱河市啸胧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌幔虏,老刑警劉巖纺念,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異想括,居然都是意外死亡陷谱,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門瑟蜈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來烟逊,“玉大人,你說我怎么就攤上這事铺根∠芮” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵位迂,是天一觀的道長访雪。 經(jīng)常有香客問我,道長掂林,這世上最難降的妖魔是什么臣缀? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮党饮,結(jié)果婚禮上肝陪,老公的妹妹穿的比我還像新娘。我一直安慰自己刑顺,他們只是感情好氯窍,可當(dāng)我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蹲堂,像睡著了一般狼讨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上柒竞,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天政供,我揣著相機與錄音,去河邊找鬼。 笑死布隔,一個胖子當(dāng)著我的面吹牛离陶,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播衅檀,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼招刨,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了哀军?” 一聲冷哼從身側(cè)響起沉眶,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎杉适,沒想到半個月后谎倔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡猿推,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年片习,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片彤守。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡毯侦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出具垫,到底是詐尸還是另有隱情侈离,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布筝蚕,位于F島的核電站卦碾,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏起宽。R本人自食惡果不足惜洲胖,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望坯沪。 院中可真熱鬧绿映,春花似錦、人聲如沸腐晾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽藻糖。三九已至淹冰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間巨柒,已是汗流浹背樱拴。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工柠衍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人晶乔。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓珍坊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親瘪弓。 傳聞我的和親對象是個殘疾皇子垫蛆,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內(nèi)容