C++筆記五(面向?qū)ο缶幊滔拢?/h1>

十六 對(duì)象模型:關(guān)于vptr和vtbl

55.png

如圖模型所示幢痘,B類繼承A類,C類繼承B類家破,子類有父類的成分颜说,繼承的包括數(shù)據(jù)购岗、非虛函數(shù)和虛函數(shù)。當(dāng)類里面有虛函數(shù)门粪,無論多少數(shù)量喊积,會(huì)多一個(gè)指針,如圖vptr(虛指針)玄妈,指向vtbl(虛函數(shù)表)乾吻。虛函數(shù)的調(diào)用是通過虛函數(shù)表實(shí)現(xiàn),無論子類是否要重寫函數(shù)拟蜻。
有一個(gè)指針p指向c(new c)绎签,通過p調(diào)用vfunc1(),先調(diào)用虛函數(shù)表酝锅,在虛函數(shù)表上找到對(duì)應(yīng)編號(hào)的函數(shù)诡必,實(shí)現(xiàn)調(diào)用,這種方式叫做動(dòng)態(tài)綁定屈张。解析成c語(yǔ)言的形式如下:

(*(p->vptr)[n])(p)擒权; //n是在虛函數(shù)表中函數(shù)的編號(hào),根據(jù)你寫的代碼的順序排
 //或者
(* p->vptr[n])(p)阁谆;
56.png

(1)如圖左下角實(shí)現(xiàn)不同形狀的draw()碳抄,1.將指向A(shape類)的指針放到容器里面;2.將draw()寫成虛函數(shù)场绿;3.具體形狀類(例如rect類)繼承抽象類shape剖效。
注:為了讓容器容納各種各樣的形狀,容器里面放的是指針焰盗,因?yàn)槿萜骼锩鏀?shù)據(jù)類型必須一致璧尸,指針必須指向父類,這樣聲明的時(shí)候指向父類熬拒,用的時(shí)候就可以指向子類爷光。
(2)對(duì)比c語(yǔ)言的實(shí)現(xiàn)方法,c語(yǔ)言是先判斷哪一種形狀澎粟,然后調(diào)用其draw()函數(shù)蛀序,這樣寫要添加某個(gè)形狀,重新寫判斷類型代碼活烙,不方便徐裸。

總結(jié):C++編譯器看到函數(shù),有兩個(gè)考量啸盏。
一是靜態(tài)綁定重贺,編譯成Call、XXX(地址);
二是動(dòng)態(tài)綁定(虛機(jī)制:動(dòng)態(tài)綁定的形式)气笙,要符合三個(gè)條件:1.通過指針調(diào)用 2.這個(gè)指針向上轉(zhuǎn)型3.調(diào)用虛函數(shù)次企。調(diào)用哪個(gè)虛函數(shù),要看p指向什么健民,這就是理解動(dòng)態(tài)綁定抒巢。

結(jié)合第四周作業(yè)探究?jī)?nèi)存模型:
內(nèi)存模型測(cè)試.png

內(nèi)存模型.png

內(nèi)存模型2.png

所以根據(jù)測(cè)試代碼sizeof大小組成如圖所示
Fruit:8+(4+4)+8+(1+7)=32
Apple:8+(4+4)+8+(1+3+4)+(1+7)=40

測(cè)試代碼:
#include <iostream>
using namespace std;

class Fruit 
{
public:
    int no;
    double weight;
    char key;
    void print() { }
    virtual void process() { }
};
//-------------------------------------------------
class Apple : public Fruit 
{
public:
    int size;
    char type;
    void save() { }
    virtual void process() { }
};
//-------------------------------------------------
int main(int argc, char const *argv[]) 
{
    Fruit fruit;
    Apple apple;

    cout << "--------------Fruit----------------" << endl;
    cout << "sizeof(Fruit) = " << sizeof(Fruit) << endl;
    printf("Fruit.vptr         = %x\n", &fruit);
    printf("Fruit.vptr_process = %x\n", *(int*)&fruit);
    printf("Fruit              = %x\n", &fruit);
    printf("Fruit.no           = %x\n", &fruit.no);
    printf("Fruit.weight       = %x\n", &fruit.weight);
    printf("Fruit.key          = %x\n", &fruit.key);
    
    cout << "--------------Apple----------------" << endl;
    cout << "sizeof(Apple) = " << sizeof(Apple) << endl;
    printf("Apple.vptr         = %x\n", &apple);
    printf("Apple.vptr_process = %x\n", *(int*)&apple);
    printf("Apple              = %x\n", &apple);
    printf("Apple.no           = %x\n", &apple.no);
    printf("Apple.weight       = %x\n", &apple.weight);
    printf("Apple.key          = %x\n", &apple.key);
    printf("Apple.size         = %x\n", &apple.size);
    printf("Apple.type         = %x\n", &apple.type);

    system("pause");
    return 0;
}

十七 對(duì)象模型:關(guān)于this

通過一個(gè)對(duì)象來調(diào)用一個(gè)函數(shù)贫贝,那個(gè)對(duì)象的地址就是this指針

57.png

第三周筆記有對(duì)這種模式具體的敘述及優(yōu)點(diǎn)秉犹,這里不再贅述。
鏈接:http://www.reibang.com/p/ca6613dd4c8d

十八 對(duì)象模型:關(guān)于Dynamic Binding

58.png

a是A的對(duì)象稚晚,雖然初值是b經(jīng)過強(qiáng)制類型轉(zhuǎn)換的崇堵,但因?yàn)槭峭ㄟ^對(duì)象調(diào)用,不是指針客燕,所以這是靜態(tài)綁定鸳劳。編譯的匯編碼為箭頭所指。


59.png

pa為動(dòng)態(tài)綁定也搓,滿足三個(gè)條件(new出來B赏廓,類型是A,是向上轉(zhuǎn)型)傍妒,call不是一個(gè)固定的地址幔摸。
(*(P->vptr)[n])(p)的解釋:通過指針p找到虛指針vptr,再找到虛表颤练,取出其中第n個(gè)既忆,把它當(dāng)成函數(shù)指針去調(diào)用,由于是通過p來調(diào)用嗦玖,所以p就是一個(gè)this指針患雇,(p)就是this指針。

十九 重談const

60.png

const第一周筆記有提過宇挫,鏈接:http://www.reibang.com/p/2fafca2021d5
(1)這里需要新提出的是:basic_string有兩個(gè)成員函數(shù)苛吱,一個(gè)operator[]函數(shù)后面有const,一個(gè)沒有const器瘪,這兩者可以存在翠储,且有const的不用寫COW,沒有const的必須寫COW娱局。
(2)常成員函數(shù)的const和non-const版本同時(shí)存在彰亥,const object只能調(diào)用const版本,non-const object只能調(diào)用non-const版本衰齐。

二十 關(guān)于New Delete

第二周有記載任斋,這里不再贅述。
鏈接:http://www.reibang.com/p/12dcce512fd4

重載Operator new,Operator delete

重載operator new和operator delete用來設(shè)計(jì)自己的內(nèi)存池废酷,也就是內(nèi)存管理瘟檩。

全局寫法:
void* myAlloy(size_t size)
{return malloc(size);}

void myFree(void* ptr)
{return free(ptr);}

//他們不可以被聲明與一個(gè)namespace內(nèi)
inline void* operator new(size_t size)
{cout<<“jjhou global new()   \n";  return myAlloc(size);}
inline void* operator new[](size_t size)
{cout<<“jjhou global new[]()   \n";  return myAlloc(size);}
inline void* operator delete(void* ptr)
{cout<<“jjhou global delete()   \n";  myFree(ptr);}
inline void* operator delete[](void* ptr)
{cout<<“jjhou global delete[]()   \n";  myFree(ptr);}

new的時(shí)候三個(gè)動(dòng)作(其中一個(gè)調(diào)用new函數(shù),此new和前頭new不同)澈蟆,如果寫了自己的重載new函數(shù)墨辛,則調(diào)用該函數(shù),否則調(diào)用全局的new函數(shù)趴俘。
重載全局的函數(shù)睹簇,影響無遠(yuǎn)弗界。

成員函數(shù)寫法:
Foo* p=new Foo;
//try{
//     void* mem=operator new(sizeof(Foo));
//     p=static_cast<Foo*>(mem);
//     p->Foo::Foo();
//}
delete p
//p->~Foo();
//operator delete(p);
class Foo{
public:
    void* operator new(size_t);
    void  operator delete(void*,size_t); //size_t 可有可無
    //...
};  

示例

61.png

62.png

在G4.9中寥闪,數(shù)組大小是數(shù)組整包大小加上一個(gè)計(jì)數(shù)器太惠。

Foo* p=::new Foo(7);
::delete p;

Foo* pArray=::new Foo[5];
::delete[] pArray;

這樣調(diào)用(也就是寫上global scope operator::),會(huì)繞過前述overloaded functions疲憋,強(qiáng)迫使用global version凿渊。

重載new(),delete()

我們可以重載class member operator new()缚柳,寫出多個(gè)版本埃脏,前提是每一版本的聲明都必須有獨(dú)特的參數(shù)列,其中第一個(gè)參數(shù)必須是size_t秋忙,其余參數(shù)以new所指定的placement arguments為初值彩掐。出現(xiàn)于new(......)小括號(hào)內(nèi)的便是所謂placement arguments。

Foo* pf=new(300,'c')Foo;

我們也可以重載class member operator delete()翰绊,寫出多個(gè)版本佩谷。但它們絕不會(huì)被delete調(diào)用。只有當(dāng)new所調(diào)用的ctor拋出exception监嗜,才會(huì)調(diào)用這些重載版的operator delete()谐檀。他只可能這樣被調(diào)用。主要用來歸還未能完全創(chuàng)建成功的object所占用的memory裁奇。

Basic_String 使用new(extra)擴(kuò)充申請(qǐng)量

63.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者

  • 序言:七十年代末桐猬,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子刽肠,更是在濱河造成了極大的恐慌溃肪,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件音五,死亡現(xiàn)場(chǎng)離奇詭異惫撰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)躺涝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門厨钻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事夯膀∈洌” “怎么了?”我有些...
    開封第一講書人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵诱建,是天一觀的道長(zhǎng)蝴蜓。 經(jīng)常有香客問我,道長(zhǎng)俺猿,這世上最難降的妖魔是什么茎匠? 我笑而不...
    開封第一講書人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮辜荠,結(jié)果婚禮上汽抚,老公的妹妹穿的比我還像新娘。我一直安慰自己伯病,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開白布否过。 她就那樣靜靜地躺著午笛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪苗桂。 梳的紋絲不亂的頭發(fā)上药磺,一...
    開封第一講書人閱讀 51,598評(píng)論 1 305
  • 那天揍魂,我揣著相機(jī)與錄音午绳,去河邊找鬼。 笑死秃励,一個(gè)胖子當(dāng)著我的面吹牛便锨,可吹牛的內(nèi)容都是我干的围辙。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼放案,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼姚建!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起吱殉,我...
    開封第一講書人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤掸冤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后友雳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體稿湿,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年押赊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了饺藤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖策精,靈堂內(nèi)的尸體忽然破棺而出舰始,到底是詐尸還是另有隱情,我是刑警寧澤咽袜,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布丸卷,位于F島的核電站,受9級(jí)特大地震影響询刹,放射性物質(zhì)發(fā)生泄漏谜嫉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一凹联、第九天 我趴在偏房一處隱蔽的房頂上張望沐兰。 院中可真熱鬧,春花似錦蔽挠、人聲如沸住闯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)比原。三九已至,卻和暖如春杠巡,著一層夾襖步出監(jiān)牢的瞬間量窘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工氢拥, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蚌铜,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓嫩海,卻偏偏與公主長(zhǎng)得像冬殃,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子出革,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

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