C++面向?qū)ο缶幊蹋ㄏ拢?創(chuàng)新互聯(lián)

文章目錄
    • C++面向?qū)ο缶幊蹋ㄏ拢?/li>
      • 11. vtpr(virtual pointer)和vtbl(virtual table)
        • 1. 前提須知
        • 2. 靜態(tài)綁定和動(dòng)態(tài)綁定
        • 3. vtpr和vtbl
        • 4. 多態(tài)
        • 5. 圖示一
        • 6. 圖示二
        • 7. template method補(bǔ)充
      • 12. const member functions(常量成員函數(shù))
        • 1. 形式(const加的位置):
        • 2. member functions 與 object 的規(guī)則
        • 3. const member functions 和 non-const member functions 的特殊規(guī)則
      • 13. 重載operator new、delete、 new[]、delete[]
        • 1. 知識(shí)回顧
        • 2. 重載 ::operator new、new[] 和 ::operator delete、delete[]
        • 3. 重載 member operator new 和 member operator delete
        • 4. 重載 member operator new[] 和 member operator delete[]
        • 5. operator new、delete、 new[]、delete[] 使用示范
          • 1. member operator new、delete、 new[]、delete[]重載寫(xiě)法
          • 2. member operator new、delete、 new[]、delete[]調(diào)用過(guò)程
          • 3. 顯式調(diào)用global operator new、delete、 new[]、delete[]過(guò)程
      • 14. 重載member operator new(...) 、 delete(...)
        • 1. new(...) 、delete(...)和new、delete的區(qū)別
        • 2. member operator new(...)
        • 3. member operator delete(...)
        • 4. member operator new(...)、delete(...)重載書(shū)寫(xiě)和使用
        • 5. 標(biāo)準(zhǔn)庫(kù)string重載placement new

網(wǎng)站建設(shè)公司,為您提供網(wǎng)站建設(shè),網(wǎng)站制作,網(wǎng)頁(yè)設(shè)計(jì)及定制網(wǎng)站建設(shè)服務(wù),專(zhuān)注于成都定制網(wǎng)頁(yè)設(shè)計(jì),高端網(wǎng)頁(yè)制作,對(duì)戶(hù)外休閑椅等多個(gè)行業(yè)擁有豐富的網(wǎng)站建設(shè)經(jīng)驗(yàn)的網(wǎng)站建設(shè)公司。專(zhuān)業(yè)網(wǎng)站設(shè)計(jì),網(wǎng)站優(yōu)化推廣哪家好,專(zhuān)業(yè)seo優(yōu)化排名優(yōu)化,H5建站,響應(yīng)式網(wǎng)站。C++面向?qū)ο缶幊蹋ㄏ拢? 11. vtpr(virtual pointer)和vtbl(virtual table) 1. 前提須知
  • 實(shí)例對(duì)象在內(nèi)存的表現(xiàn):
    • 函數(shù)在內(nèi)存中的位置,與實(shí)例對(duì)象占用的內(nèi)存沒(méi)有關(guān)系;
    • 對(duì)于一個(gè)類(lèi)的多個(gè)對(duì)象,函數(shù)在內(nèi)存中也只會(huì)有一份;
    • 實(shí)例對(duì)象占用的內(nèi)存,只會(huì)包含對(duì)象的數(shù)據(jù);如果有虛函數(shù),還會(huì)包含一個(gè)虛指針;【無(wú)論有多少個(gè)虛函數(shù),都只會(huì)多占用一個(gè)指針的空間;】
  • 繼承:
    • 對(duì)于父類(lèi)中的函數(shù),子類(lèi)只是繼承了函數(shù)的調(diào)用權(quán),不會(huì)為子類(lèi)在內(nèi)存中另外生成一份函數(shù)【因?yàn)楹瘮?shù)始終只在內(nèi)存占一份】;
    • 如果父類(lèi)有虛函數(shù),那么子類(lèi)也一定有虛函數(shù)(繼承);
    • 雖然父類(lèi)和子類(lèi)中的非虛函數(shù)和數(shù)據(jù),命名可以重復(fù)(因?yàn)槎邲](méi)有什么關(guān)系),但這樣的命名風(fēng)格不好。
2. 靜態(tài)綁定和動(dòng)態(tài)綁定
  • 類(lèi)型:
    • 靜態(tài)類(lèi)型:對(duì)象在聲明時(shí)采用的類(lèi)型,在編譯期既已確定;
    • 動(dòng)態(tài)類(lèi)型:通常是指一個(gè)指針或引用目前所指對(duì)象的類(lèi)型,是在運(yùn)行期決定的;
  • 綁定(Binding):是指將變量和函數(shù)名轉(zhuǎn)換為地址的過(guò)程。
    • 靜態(tài)綁定:綁定的是靜態(tài)類(lèi)型,所對(duì)應(yīng)的函數(shù)或?qū)傩砸蕾?lài)于對(duì)象的靜態(tài)類(lèi)型,發(fā)生在編譯期;
      • 意味著綁定的函數(shù)或者變量,已經(jīng)在編譯階段,該語(yǔ)句已經(jīng)被編譯成“call 函數(shù)地址”或"callq 函數(shù)地址"這樣的匯編指令格式,并且這些匯編指令中的函數(shù)地址在程序編譯后是固定不變的,請(qǐng)記住,所有函數(shù)都有唯一的地址。
    • 動(dòng)態(tài)綁定:綁定的是動(dòng)態(tài)類(lèi)型,所對(duì)應(yīng)的函數(shù)或?qū)傩砸蕾?lài)于對(duì)象的動(dòng)態(tài)類(lèi)型,發(fā)生在運(yùn)行期;
  • 只有虛函數(shù)才使用的是動(dòng)態(tài)綁定(實(shí)現(xiàn)多態(tài)),其他的全部是靜態(tài)綁定;
  • 編譯器使用動(dòng)態(tài)綁定的三個(gè)條件:
    • 通過(guò)指針 / 引用調(diào)用函數(shù);
    • 指針是向上轉(zhuǎn)型后的指針(this指的是子類(lèi)對(duì)象,符合向上轉(zhuǎn)型);【即父類(lèi)指針指向子類(lèi)對(duì)象】
    • 指針調(diào)用的是虛函數(shù)。
    • 簡(jiǎn)單一句話使用基類(lèi)的引用(指針)調(diào)用虛函數(shù)

3. vtpr和vtbl
  • vtpr(虛指針):

    • 對(duì)于有virtual函數(shù)的類(lèi),它的實(shí)例化對(duì)象在內(nèi)存空間中除了包含數(shù)據(jù)的大小,還會(huì)多出一個(gè)指針(4個(gè)字節(jié))的大小,同時(shí)會(huì)放在內(nèi)存中最開(kāi)始的位置,這個(gè)指針就是vptr(虛指針),它指向了vtbl(虛函數(shù)表),即 vptr內(nèi)容 vtbl的地址。
  • vtbl(虛函數(shù)表):

    • vtbl 內(nèi)容:保存了一個(gè)類(lèi)持有的虛函數(shù)的地址;
    • 建兩個(gè)A對(duì)象,發(fā)現(xiàn)他們的虛函數(shù)指針相同,這說(shuō)明他們的虛函數(shù)表屬于類(lèi),不屬于對(duì)象。所以虛函數(shù)表應(yīng)該存在共有區(qū);
    • 位置:虛函數(shù)表放在了全局?jǐn)?shù)據(jù)段。
  • 查找過(guò)程:

    • 在編譯時(shí),編譯器會(huì)為【整個(gè)繼承關(guān)系中的每個(gè)虛函數(shù)】進(jìn)行順序編號(hào),按照這個(gè)編號(hào)順序,在vtbl中放置虛函數(shù)地址;
    • 調(diào)用一個(gè)實(shí)例化對(duì)象的虛函數(shù)過(guò)程:
      • 先找到vtptr(在實(shí)例化對(duì)象所在內(nèi)存的開(kāi)頭位置);
      • 通過(guò)vtptr內(nèi)容,找到vtbl;
      • 從vtbl找到對(duì)應(yīng)虛函數(shù)的地址,把它當(dāng)成函數(shù)指針去調(diào)用;
      • 函數(shù)指針調(diào)用的方式:后面的§,是傳遞隱藏參數(shù)this pointer;
        在這里插入圖片描述
4. 多態(tài)
  • 多態(tài)和動(dòng)態(tài)綁定是一回事(涉及虛函數(shù)、虛函數(shù)指針、虛函數(shù)表)

5. 圖示一
  • 圖中有A、B、C三個(gè)對(duì)象:
    • 對(duì)象關(guān)系:
      • B是A的子類(lèi),C是B的子類(lèi);
    • 對(duì)象內(nèi)容:
      • A對(duì)象:2個(gè)虛函數(shù),2個(gè)非虛函數(shù),2個(gè)int數(shù)據(jù);
      • B對(duì)象:
        • 自身的內(nèi)容:1個(gè)非虛函數(shù),1個(gè)int;
        • 繼承的內(nèi)容:繼承了A的2個(gè)虛函數(shù),但自己重新定義了其中一個(gè);繼承了A的2個(gè)非虛函數(shù);繼承了A的兩個(gè)int數(shù)據(jù);
        • 總內(nèi)容:2個(gè)虛函數(shù)(其中一個(gè)自定義),3個(gè)非虛函數(shù),3個(gè)int數(shù)據(jù);
      • C對(duì)象:
        • 自身的內(nèi)容:1個(gè)非虛函數(shù),2個(gè)int;
        • 繼承的內(nèi)容:繼承了B的2個(gè)虛函數(shù),但自己重新定義了其中一個(gè);繼承了B的3個(gè)非虛函數(shù);繼承了B的3個(gè)int數(shù)據(jù);
        • 總內(nèi)容::2個(gè)虛函數(shù)(其中一個(gè)自定義),4個(gè)非虛函數(shù),5個(gè)int數(shù)據(jù);
    • 三個(gè)類(lèi)的函數(shù)個(gè)數(shù):
      • 4個(gè)非虛函數(shù);
      • 4個(gè)虛函數(shù);
        在這里插入圖片描述
6. 圖示二
  • A為shape抽象類(lèi);
  • B、C為具體的形狀類(lèi);
  • A有draw虛函數(shù),B、C自定義了draw函數(shù)(相當(dāng)于上一頁(yè)的vfunc1());
  • 右下角的容器:
    • 使用父類(lèi)指針指向子類(lèi)的方式(多態(tài)),使容器可以包含多種類(lèi)型;
      在這里插入圖片描述

7. template method補(bǔ)充
  • 也可以使用基類(lèi)指針指向派生類(lèi)對(duì)象 CDocument* cdoc = new CMyDoc(),來(lái)調(diào)用OnFileOpen()函數(shù);
  • 執(zhí)行Serialize()函數(shù),滿足動(dòng)態(tài)綁定三個(gè)條件,編譯器會(huì)把Serialize()寫(xiě)出函數(shù)指針調(diào)用的形式(圖左邊);
  • 在動(dòng)態(tài)綁定三個(gè)條件中的第二個(gè),不太好理解:
    • 指針是向上轉(zhuǎn)型后的指針(this指的是子類(lèi)對(duì)象,符合向上轉(zhuǎn)型);
    • 【簡(jiǎn)單理解為只要this指的是子類(lèi)對(duì)象,就滿足這個(gè)條件。】
    • 可能右下角調(diào)用OnFileOpen()中的this指針類(lèi)型是父類(lèi)指針類(lèi)型。(這樣就有父類(lèi)指針指向子類(lèi)對(duì)象)
      在這里插入圖片描述

12. const member functions(常量成員函數(shù)) 1. 形式(const加的位置):
class Complex{
public:
    // const member function(常量成員函數(shù))
	double real () const { return resl; }
	double imag () const { return im; }
private:
	double re, im;
};
  • 常量成員函數(shù)顧名思義:
    • 只能定義在成員函數(shù)身上,全局函數(shù)不行;
2. member functions 與 object 的規(guī)則
  • const object (要求 data members 不能改動(dòng));
  • non-const object (data members 可改動(dòng));
  • const member functions(保證這個(gè)成員函數(shù)不更改 data members);
  • non-const member functions(不保證這個(gè)成員函數(shù)不更改 data members);
    在這里插入圖片描述
3. const member functions 和 non-const member functions 的特殊規(guī)則
  • 一個(gè) member function 如果同時(shí)存在 const 和 non-const 版本:

    • 明確了調(diào)用函數(shù)的對(duì)象是 const object,還是 non-const object;
    • 主要是明確了調(diào)用 const member functions 的對(duì)象(因?yàn)橐话闱闆r下,non-const object也可以調(diào)用const member functions,上面表的第一行)
      在這里插入圖片描述
  • 標(biāo)準(zhǔn)庫(kù)(string)的成員函數(shù)示范:

    • operator[] 函數(shù)同時(shí)存在 const 和 non-const 版本;
    • 常量成員函數(shù)的const是函數(shù)簽名的一部分,所以可以進(jìn)行函數(shù)重載;
    • 根據(jù)特殊規(guī)則:
      • 調(diào)用 const member functions 的對(duì)象,一定是const object;
      • 調(diào)用 non-const member functions 的對(duì)象,一定是non-const object;
        在這里插入圖片描述

13. 重載operator new、delete、 new[]、delete[] 1. 知識(shí)回顧
  • new過(guò)程(分三步):

    • 先使用operator new分配空間,底層使用malloc函數(shù);
    • 進(jìn)行指針類(lèi)型轉(zhuǎn)換;
    • 再調(diào)用構(gòu)造函數(shù):對(duì)于帶有指針的類(lèi),通過(guò)構(gòu)造函數(shù),分配指針指向的數(shù)據(jù);
  • delete過(guò)程(分兩步):

    • 先調(diào)用析構(gòu)函數(shù):對(duì)于帶有指針的類(lèi),通過(guò)析構(gòu)函數(shù),釋放指針指向的數(shù)據(jù);
    • 再使用operator delete釋放分配的空間,底層使用free函數(shù)。
  • 在new和delete的過(guò)程中,new和delete本身是不能重載的,但new和delete中operator new和operator delete操作是可以重載的:

    • operator new和operator delete的調(diào)用順序
      • 先找類(lèi)中的重載版本;
      • 再找全局版本。
2. 重載 ::operator new、new[] 和 ::operator delete、delete[]
  • 一般不重載全局operator new、delete、new[]、delete[];
    在這里插入圖片描述
3. 重載 member operator new 和 member operator delete
  • 圖中的member operator delete中的optional參數(shù)表示該參數(shù)可選;
  • 該類(lèi)進(jìn)行new和delete中,優(yōu)先找member operator new 和 member operator delete
    在這里插入圖片描述
4. 重載 member operator new[] 和 member operator delete[]
  • 圖中的optional指該參數(shù)可選;
  • 該類(lèi)進(jìn)行new[] 和delete[]中,優(yōu)先找member operator new[] 和 member operator delete[];
    在這里插入圖片描述
5. operator new、delete、 new[]、delete[] 使用示范 1. member operator new、delete、 new[]、delete[]重載寫(xiě)法
  • (僅僅增加打印信息)

  • 重載函數(shù):

    • operator new;
    • operator delete;
    • operator new[];
    • operator delete[];
  • global 與member operator new、delete、 new[]、delete[]相關(guān)函數(shù)的調(diào)用順序

    • // 優(yōu)先調(diào)用member version,如果沒(méi)有member version,就調(diào)用global version;
      Foo* pf = new Foo;
      delete pf;
    • // 強(qiáng)制調(diào)用global version;
      Foo* pf = ::new Foo;
      ::delete pf;

在這里插入圖片描述

2. member operator new、delete、 new[]、delete[]調(diào)用過(guò)程
  • 不帶有虛函數(shù)的類(lèi):

    • 由上一頁(yè)可知,sizeof(Foo) = 12【int:4個(gè)字節(jié),long:4個(gè)字節(jié),string:4個(gè)字節(jié)(指針)】;

    • 調(diào)用 operator new 和 delete:

      • // 調(diào)用 operator new 和 delete
        Foo* p = new Foo(7);	// 這個(gè)參數(shù)是構(gòu)造函數(shù)的參數(shù)
        delete p;
      • 分配一個(gè)對(duì)象的大小空間(這個(gè)例子 == 12);

      • 注意點(diǎn):

        • operator new的第一個(gè)參數(shù)是編譯器自動(dòng)傳遞的;
        • 下圖左邊①中后面的Foo(7)是Foo的構(gòu)造函數(shù),不要和new的參數(shù)混淆了;

    • 調(diào)用 operator new[] 和 delete[]:

      • // 調(diào)用 operator new[] 和 delete[]
        Foo* pArray = new Foo[5];
        delete pArray[];
      • 分配5個(gè)對(duì)象的大小空間 == 12*5 + 4 == 64;【調(diào)用operator new[] 時(shí),會(huì)有一個(gè)額外整型用于記錄數(shù)組的大小,整型4個(gè)字節(jié),面向?qū)ο髉art one中有講過(guò)】

    • new[] 和 delete[] 調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)的順序相反【看this指針順序】


  • 帶有虛函數(shù)的類(lèi):

    • 唯一不同在于,帶有虛函數(shù)的類(lèi),會(huì)多一個(gè)虛函數(shù)指針的大小;
    • sizeof(Foo) = 16
    • 分配5個(gè)的大小 == 16*5 + 4 = 84;
      在這里插入圖片描述
3. 顯式調(diào)用global operator new、delete、 new[]、delete[]過(guò)程
  • 強(qiáng)迫使用global version,沒(méi)有member version的打印信息;
    在這里插入圖片描述
14. 重載member operator new(…) 、 delete(…) 1. new(…) 、delete(…)和new、delete的區(qū)別
  • 括號(hào)的意義:operator new() 、delete() 額外設(shè)置了參數(shù);
  • placement術(shù)語(yǔ)介紹:
    • member operator new() == placement new;
    • member operator delete() == placement delete;
2. member operator new(…)
  • member operator new() 可以有多個(gè)參數(shù),但第一個(gè)參數(shù)類(lèi)型一定是size_t(unsigned int),并且這個(gè)參數(shù)是由編譯器傳遞;

  • 不同版本的 member operator new() 必須有不同的參數(shù)列(才能進(jìn)行函數(shù)重載,函數(shù)簽名不同):

    • 即第一個(gè)參數(shù)之后的參數(shù),個(gè)數(shù)、類(lèi)型要有區(qū)別;
  • member operator new() 調(diào)用方式:

    • 調(diào)用時(shí),需要手動(dòng)傳遞的參數(shù)是第一個(gè)參數(shù)以后的參數(shù);

    • 下面的 member operator new() 說(shuō)明,定義時(shí)有三個(gè)參數(shù);

    • // 調(diào)用 operator new() 和 delete
      // new(300, 'c'):說(shuō)明這個(gè)operator new()有三個(gè)參數(shù),第一個(gè)參數(shù)不需要手動(dòng)傳遞。
      Foo* p = new(300, 'c') Foo(7);	// 注意傳遞new的參數(shù),以及構(gòu)造參數(shù)的位置
      delete p;
3. member operator delete(…)
  • member operator delete() 也可以重載,也可以不重載;
  • 這一步不是必須的,因?yàn)椴粫?huì)被delete調(diào)用【正常 delete 調(diào)用 void operator delete(void*, size_t) 版本】;
  • member operator delete() 調(diào)用:
    • 無(wú)論new調(diào)用的是哪種版本,只有一般版本的delete會(huì)被調(diào)用;
  • member operator delete() 作用:
    • new操作分為三步:
      • operator new;
      • 轉(zhuǎn)型;
      • 構(gòu)造函數(shù);
    • 只有當(dāng) new 中第三步,調(diào)用的構(gòu)造函數(shù)拋出異常,才會(huì)調(diào)用這些 member operator new() 版本對(duì)應(yīng)的 operator delete() ,釋放之前 member operator new() 分配的空間;
    • 它只可能這樣被調(diào)用,主要用來(lái)歸還未能完全創(chuàng)建成功的對(duì)象所占用的內(nèi)存空間。
      在這里插入圖片描述
4. member operator new(…)、delete(…)重載書(shū)寫(xiě)和使用
  • member operator new():

    • (1) ~ (4) 不同版本的 placement new;
    • (5):故意寫(xiě)錯(cuò)第一參數(shù)的 placement new 不合法版本;編譯器會(huì)報(bào)錯(cuò),要求第一個(gè)參數(shù)類(lèi)型是 size_t;
      在這里插入圖片描述
  • member operator delete():

    • (1) ~ (4) 的 placement delete 對(duì)應(yīng)上一頁(yè)不同版本的 placement new;
    • 【上一頁(yè)在構(gòu)造函數(shù)中故意拋出異常;】
    • 右邊⑤:構(gòu)造函數(shù)失?。⊕伋霎惓#?,是否會(huì)調(diào)用對(duì)應(yīng)的 placement delete,取決于編譯器;
    • 最下面的方框:
      • 沒(méi)有定義對(duì)應(yīng) operator new(…) 版本的 operator delete(…),也不會(huì)報(bào)錯(cuò);
      • 這意味著放棄構(gòu)造函數(shù)拋出的異常。
        在這里插入圖片描述
5. 標(biāo)準(zhǔn)庫(kù)string重載placement new
  • 重載 placement new 用于分配額外的空間,作為 string 的內(nèi)容空間;
  • Rep:是標(biāo)準(zhǔn)庫(kù) string 用于計(jì)數(shù)有多少用戶(hù)共用這個(gè)字符串對(duì)象的計(jì)數(shù)器(reference counting 技術(shù));
  • reference counting 技術(shù):
    • 允許多個(gè)擁有共同值的對(duì)象共享同一個(gè)對(duì)象實(shí)體,解決了同一個(gè)對(duì)象存在多分拷貝的問(wèn)題。
      在這里插入圖片描述

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

當(dāng)前文章:C++面向?qū)ο缶幊蹋ㄏ拢?創(chuàng)新互聯(lián)
文章出自:http://muchs.cn/article12/ejjdc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供做網(wǎng)站、定制開(kāi)發(fā)云服務(wù)器、定制網(wǎng)站網(wǎng)站收錄、面包屑導(dǎo)航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)