成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

C++對(duì)象模型

何為C++對(duì)象模型?

成都創(chuàng)新互聯(lián)為企業(yè)級(jí)客戶提高一站式互聯(lián)網(wǎng)+設(shè)計(jì)服務(wù),主要包括成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站、成都App定制開發(fā)、成都微信小程序、宣傳片制作、LOGO設(shè)計(jì)等,幫助客戶快速提升營銷能力和企業(yè)形象,創(chuàng)新互聯(lián)各部門都有經(jīng)驗(yàn)豐富的經(jīng)驗(yàn),可以確保每一個(gè)作品的質(zhì)量和創(chuàng)作周期,同時(shí)每年都有很多新員工加入,為我們帶來大量新的創(chuàng)意。 

  1. 語言中直接支持面向?qū)ο蟮牟糠?/p>

  2. 對(duì)于各種支持的底層實(shí)現(xiàn)機(jī)制

語言中直接支持面向?qū)ο蟪绦蛟O(shè)計(jì)的部分,如構(gòu)造函數(shù),析構(gòu)函數(shù),虛函數(shù),繼承(單繼承,虛繼承)、多態(tài)等等。

在C語言中,數(shù)據(jù)和處理操作是分開來聲明的,也就是說,語言中沒有支持“數(shù)據(jù)和函數(shù)”之間的關(guān)聯(lián)性,在C++中,通過抽象數(shù)據(jù)類型(abstract data type,ADT),在類中定義數(shù)據(jù)和函數(shù),來實(shí)現(xiàn)數(shù)據(jù)和函數(shù)的直接綁定。

概括來說,在C++類中有兩種成員數(shù)據(jù):static,nonstatic;三種成員函數(shù):static, nonstatic, virtual。

C++對(duì)象模型
如下面定義Base類

Base類定義:
#pragma once
#include<iostream>
using namespace std;
class Base
{
public:
Base(int);
virtual ~Base(void);

int getIBase() const;
static int instanceCount();
virtual void print() const;

protected:

int iBase;
static int count;
};

Base類在機(jī)器中是如何構(gòu)建出各種成員數(shù)據(jù)和成員函數(shù)呢?

基本C++對(duì)象模型

有兩種,簡單對(duì)象模型和表格驅(qū)動(dòng)模型

C++對(duì)象模型

所有相同的成員占用的空間(跟類型無關(guān)),對(duì)象只是維護(hù)了一個(gè)包含成員指針的一個(gè)表。表中放的是成員地址,無論是成員變量還是成員函數(shù),都是這樣處理。對(duì)象并沒有直接保存成員而是保存了成員的指針。

表格驅(qū)動(dòng)模型

C++對(duì)象模型

這個(gè)模型在簡單模型基礎(chǔ)上又填了間接層。將成員分成函數(shù)和數(shù)據(jù),并且用兩個(gè)表格保存,然后對(duì)象只保存了兩個(gè)指向表格的指針,這個(gè)模型可以保證所有對(duì)象具有相同的大小,比如簡單對(duì)象模型還與成員個(gè)數(shù)有關(guān),其中數(shù)據(jù)成員表中還包含實(shí)際數(shù)據(jù);函數(shù)成員表中包含實(shí)際函數(shù)地址(與數(shù)據(jù)成員相比,多一次尋址)

C++對(duì)象模型

C++對(duì)象模型

這個(gè)模型結(jié)合表格驅(qū)動(dòng)模型總的特點(diǎn),并對(duì)內(nèi)存存取和空間進(jìn)行了優(yōu)化。在此模型中,nostatic數(shù)據(jù)成員被放在對(duì)象內(nèi)部,static數(shù)據(jù)成員,static和nonstatic函數(shù)成員均被列到對(duì)象之外,對(duì)于虛函數(shù)的支持則分成兩步完成

  1. 每一個(gè)class產(chǎn)生一堆指向虛函數(shù)的指針,放在表格中。這個(gè)表格稱為虛函數(shù)表。

  2. 每一個(gè)對(duì)象被添加一個(gè)指針,指向相關(guān)函數(shù)的vtbl。通常這個(gè)指針被稱為Vptr。vptr的設(shè)定和重置都有每個(gè)class的構(gòu)造函數(shù),析構(gòu)函數(shù)和拷貝賦值運(yùn)算符自動(dòng)完成。

  3. 另外,虛函數(shù)表地址的前面設(shè)置了一個(gè)指向type_info的指針,RTTI運(yùn)行時(shí)類型識(shí)別是由編譯器在編譯期生成的特殊類型信息,包括對(duì)象繼承關(guān)系,對(duì)象本身的描述,RTTI是為多態(tài)而生成的信息,所以只有具有虛函數(shù)的對(duì)象才會(huì)生成。

優(yōu)點(diǎn):它的空間和存取時(shí)間的效率高。

缺點(diǎn):如果程序本身未改變,但當(dāng)使用的類的nonstatic數(shù)據(jù)成員添加刪除或修改時(shí),需要重新編譯

C++對(duì)象模型加入單繼承

不管單繼承多繼承還是虛繼承,如果基于“簡單對(duì)象模型”,每一個(gè)基類都可以被派生類中的slot指出,該slot內(nèi)包含基類對(duì)象的地址,這個(gè)機(jī)制主要缺點(diǎn)是,因?yàn)殚g接性而導(dǎo)致空間和存取時(shí)間上的額外負(fù)擔(dān),優(yōu)點(diǎn)則是派生類對(duì)象的大小不會(huì)因?yàn)榛惖母淖兌苡绊憽?/p>

無重寫的單繼承

//Derived類:
#pragma once
#include "base.h"

class Derived :
public Base
{
public:
Derived(int);
virtual ~Derived(void);
virtual void derived_print(void);

protected:
int iDerived;
};

Base、Derived的類圖

C++對(duì)象模型

C++對(duì)象模型

注:子類沒有重新父類函數(shù)的情況

  1. 父類的虛函數(shù)在虛函數(shù)表的【前面】

  2. 子類的虛函數(shù)在虛函數(shù)表的【后面】

有重寫的單繼承

//Derived_Overwrite類:
#pragma once
#include "base.h"
class Derived_Overrite :
public Base
{
public:
Derived_Overrite(int);
virtual ~Derived_Overrite(void);
virtual void print(void) const;

protected:
int iDerived;
};
C++對(duì)象模型

C++對(duì)象模型

注:子類有函數(shù)重寫父類函數(shù)的情況

1.父類的虛函數(shù)在虛函數(shù)表的【前面】

2.子類的虛函數(shù)在虛函數(shù)表的【后面】

3.子類重寫父類的虛函數(shù),替換父類對(duì)應(yīng)的虛函數(shù),出現(xiàn)在虛函數(shù)表里【前面】

C++對(duì)象模型中加入多繼承

從單繼承可以知道,派生類中只是擴(kuò)充了基類的虛函數(shù)表。如果是多繼承的話,又是如何擴(kuò)充的呢?

1)每個(gè)基類都有自己的虛表

2)子類的成員函數(shù)放到了第一個(gè)基類的表中

3)內(nèi)存布局中,其父類布局一次按聲明順序排列

4)每個(gè)基類的虛表中的Print()函數(shù)被overwrite成了子類的Print()。這樣做就是為了解決不同基類類型的指針指向同一個(gè)子類的實(shí)例,而能夠調(diào)用到實(shí)際的函數(shù)。

C++對(duì)象模型

上面3個(gè)類,Derived_Mutlip_Inherit繼承自Base、Base_1兩個(gè)類,Derived_Mutlip_Inherit的結(jié)構(gòu)如下所示:

C++對(duì)象模型

C++對(duì)象模型中加入虛繼承

虛繼承是為了解決重復(fù)繼承中多個(gè)間接父類的問題的,所以不能使用上面簡單的擴(kuò)充并為每個(gè)虛基類 提供一個(gè)虛函數(shù)指針(這樣做會(huì)導(dǎo)致重復(fù)繼承的基類會(huì)有多個(gè)虛函數(shù)表)形式。虛繼承的派生類的內(nèi)存結(jié)構(gòu),和普通繼承完全不同,虛繼承的子類,有單獨(dú)的虛函數(shù)表,另外也單獨(dú)保存一份父類的虛函數(shù)表,兩部分之間用一個(gè)四個(gè)字節(jié)的0x00000000來作為分界,派生類的內(nèi)存中,首先是自己的虛函數(shù)表,然后是派生類成員的數(shù)據(jù),然后是0x0,之后就是基類的虛函數(shù)表,之后是基類數(shù)據(jù)成員。

如果派生類沒有自己的虛函數(shù),那么派生類就不會(huì)有虛函數(shù)表,但是派生類數(shù)據(jù)和基類數(shù)據(jù)之間,還需要用0x0來間隔。因此在虛繼承中,派生類和基類的數(shù)據(jù),是完全間隔的,先存放派生類自己的虛函數(shù)表和數(shù)據(jù),中間以0x分界,然后保存基類的虛函數(shù)和數(shù)據(jù),如果派生類重載了父類的虛函數(shù),那么則派生類內(nèi)存中的基類虛函數(shù)表的相應(yīng)函數(shù)替換。

簡單虛繼承(無重復(fù)繼承)

簡單虛繼承的2個(gè)類Base、Derived_Virtual_Inherit1的關(guān)系如下所示:

C++對(duì)象模型

Derived_Virtual_Inherit1的對(duì)象模型如下圖:

C++對(duì)象模型

注:虛 基類的信息是獨(dú)立de

  1. 子類的虛函數(shù)表指針及數(shù)據(jù)成員(如果有的話)放在【前面】

  2. 虛基類的信息與子類的信息使用0x00000000與子類分隔開來,虛基類虛函數(shù)表的指針及數(shù)據(jù)成員【后面】

  3. 子類重寫虛基類,虛函數(shù)表中對(duì)應(yīng)的函數(shù)

菱形繼承(含重復(fù)繼承、多繼承情況)

菱形繼承關(guān)系如下:

C++對(duì)象模型

Derived_Virtual的對(duì)象模型如下圖:

C++對(duì)象模型

注:虛基類的信息是獨(dú)立的,多繼承的布局和之前一樣

1.基類的虛函數(shù)表指針及數(shù)據(jù)成員按照繼承的排序序列【前面】

2.虛基類的信息與子類的信息使用0x00000000與子類分隔開來,虛基類函數(shù)表指針及數(shù)據(jù)成員【后面】

3.子類重寫所有基類(包含虛基類)的虛函數(shù)表對(duì)應(yīng)的函數(shù)

對(duì)象大小問題

C++對(duì)象模型

三個(gè)類中的函數(shù)都是虛函數(shù)

●Derived繼承Base

●Derived_Virtual虛繼承Base

//測試對(duì)象大?。?void test_size()
{
Base b;
Derived d;
Derived_Virtual dv;
cout << "sizeof(b):\t" << sizeof(b) << endl;
cout << "sizeof(d):\t" << sizeof(d) << endl;
cout << "sizeof(dv):\t" << sizeof(dv) << endl;
}

輸出如下

C++對(duì)象模型

因?yàn)锽ase類中包含虛函數(shù)指針,所有size為4,;Derived繼承Base,只是擴(kuò)充基類的虛函數(shù)表,不會(huì)新增虛函數(shù)表指針,所以size也是4,Derived-Virtusl虛繼承Base,根據(jù)前面的模型知道,派生類有自己的虛函數(shù)表及指針,并且有分隔符(0x00000000)然后才有虛基類的虛函數(shù)表等信息,故大小為4+4+4=12

數(shù)據(jù)成員是如何訪問的?

跟實(shí)際對(duì)象模型相關(guān)聯(lián),根據(jù)對(duì)象地址+偏移量取得

靜態(tài)綁定與動(dòng)態(tài)綁定

綁定:把函數(shù)體與函數(shù)調(diào)用相聯(lián)系稱為綁定

程序調(diào)用函數(shù)時(shí),將使用哪個(gè)可執(zhí)行的代碼塊?編譯器負(fù)責(zé)回答這個(gè)問題,將源代碼中的函數(shù)調(diào)用解析為執(zhí)行特定函數(shù)代碼塊被稱為函數(shù)名綁定,在VC語言中,這非常簡單,因?yàn)槊總€(gè)函數(shù)名都對(duì)應(yīng)一個(gè)不同的額函數(shù),在C++中,由于函數(shù)重載的緣故,這項(xiàng)任務(wù)復(fù)雜,編譯器必須查看函數(shù)參數(shù)以及函數(shù)名才能確定使用哪個(gè)函數(shù),然而編譯器可以在編譯過程中完成這種綁定,這稱為靜態(tài)綁定,有稱為早起綁定。

然而虛函數(shù)使得這項(xiàng)工作變得困難,使用那個(gè)函數(shù)不是能在編譯階段確定的,因?yàn)榫幾g器不知道用戶選擇哪種類型。所以編譯器必須在程序運(yùn)行時(shí)選擇正確的函數(shù)代碼,這稱為動(dòng)態(tài)綁定,又稱為晚期綁定。

使用虛函數(shù)是有代價(jià)的,在內(nèi)存和執(zhí)行速度方面是有一定成本的,包括:

●每個(gè)對(duì)象都將增大,增大量為存儲(chǔ)虛函數(shù)表指針的大??;

●對(duì)于每個(gè)類,編譯器都創(chuàng)建一個(gè)虛函數(shù)地址表;

●對(duì)于每個(gè)函數(shù)調(diào)用,都需要執(zhí)行一項(xiàng)額外的操作,即到虛函數(shù)表中查找地址。

雖然非虛函數(shù)比虛函數(shù)效率稍高,單不具備動(dòng)態(tài)聯(lián)編能力。

當(dāng)前題目:C++對(duì)象模型
網(wǎng)站URL:http://www.jinyejixie.com/article28/jogsjp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信公眾號(hào)、網(wǎng)站排名營銷型網(wǎng)站建設(shè)、商城網(wǎng)站網(wǎng)站改版、電子商務(wù)

廣告

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

綿陽服務(wù)器托管