你所不知道的C++ 之 C++虛類模型

來源:互聯網
上載者:User

標籤:

我們知道,一個C++類如果帶有virtual關鍵字的函數,那麼,它就是一個虛類。虛類都有虛函數表。這個虛函數表真的存在嗎?能摸得著、看得見嗎?

的確是可以的。下面我們就展示一下如何看到C++類的虛函數表。請注意,我使用的系統是Ubutu 10.04, g++ 4.6.3。


下面我們先定義一個簡單的純虛類和它的實作類別:

class BaseClassNoDeconstructor {public:    virtual void func() = 0;};class VirtualClassNoDeconstructor : public BaseClassNoDeconstructor{public:    virtual void func() {        cout << "VirtualClassNoDeconstructor func\n";    }};

然後,針對類VirtualClassNoDeconstructor,我們定義兩個等價的struct:

struct VirtualClassNoDeconstructorMember;struct VirtualClassNoDeconstructorVTable {    void (*func)(VirtualClassNoDeconstructorMember*);};struct VirtualClassNoDeconstructorMember {    VirtualClassNoDeconstructorVTable * vtable;};
然後,我們用VirtualClassNoDeconstructorMember來調用它:

void dofuncNoDeconstructor(BaseClassNoDeconstructor* bcd) {    cout <<"======= call by class no deconstructor by vtable: ===\n";    VirtualClassNoDeconstructorMember * pvcd = (VirtualClassNoDeconstructorMember*)bcd;    pvcd->vtable->func(pvcd);    cout <<"======== end =======\n";}
想看下輸出結果嗎?

======= call by class no deconstructor by vtable: ===VirtualClassNoDeconstructor func======== end =======

我想不用多說什麼了。


那麼,對於一個有虛析構造的類,情況又是什麼呢?首先,還是先看簡單的類:

class BaseClass {public:    virtual ~BaseClass() { }    virtual void func() = 0;};class VirtualClass : public BaseClass {public:    virtual ~VirtualClass(){        cout << "Virtual Class destory"<<endl;    }    virtual void func() {         cout << "Virtual Class : v="<<value<<endl;    }    VirtualClass(int v) : value(v) { };private:    int value;};
這兩個類有虛的析構造,對應的等價struct則需要定義為:

struct VirtualClassVTable {    void (*dector)(VirtualClassMember* self);    void (*delete_obj)(VirtualClassMember* self);    void (*func)(VirtualClassMember* self);};struct VirtualClassMember {    VirtualClassVTable* vtable;    int value;};
看,多了兩個函數:dector和delete_obj。先別著急,先看看測試代碼和輸出結果

void dofunc(BaseClass* bc) {    cout <<"====== call class by vtable: ===\n";    VirtualClassMember *pvcm = (VirtualClassMember*)bc;    cout <<"from member value="<< pvcm->value<<endl;    pvcm->vtable->func(pvcm);    pvcm->vtable->dector(pvcm);    printf("VTable %p: func=%p, ~=%p\n",pvcm->vtable, pvcm->vtable->func, pvcm->vtable->dector);    printf("pvcm->vtable->delete_obj=%p\n", pvcm->vtable->delete_obj);    printf("pvcm->vtable->dector=%p\n", pvcm->vtable->dector);    printf("pvcm->vtable->func=%p\n", pvcm->vtable->func);    cout <<"======== end ======\n";}

輸出結果呢,則是
====== call class by vtable: ===from member value=1234Virtual Class : v=1234Virtual Class destoryVTable 0x401150: func=0x400970, ~=0x400ce2pvcm->vtable->delete_obj=0x400d14pvcm->vtable->dector=0x400ce2pvcm->vtable->func=0x400970======== end ======

按照通常的做法,增加了一個析構造,應該增加一個函數才對,而實際上卻增加了兩個。其中一個就是真正的構造,而另外一個,是伴隨他產生的一個刪除函數:delete_obj。

這個函數是由編譯器自動產生的。那麼,他的作用是什嗎?為了搞清楚這個問題,我用objdump反編譯代碼,從其中摘抄了下面一段:

0000000000400d14 <_ZN9BaseClassD0Ev>:  400d14:55                   push   %rbp  400d15:48 89 e5             mov    %rsp,%rbp  400d18:48 83 ec 10          sub    $0x10,%rsp  400d1c:48 89 7d f8          mov    %rdi,-0x8(%rbp)  400d20:48 8b 45 f8          mov    -0x8(%rbp),%rax  400d24:48 89 c7             mov    %rax,%rdi  400d27:e8 b6 ff ff ff       callq  400ce2 <_ZN9BaseClassD1Ev>  400d2c:48 8b 45 f8          mov    -0x8(%rbp),%rax  400d30:48 89 c7             mov    %rax,%rdi  400d33:e8 d8 fb ff ff       callq  400910 <[email protected]>  400d38:c9                   leaveq   400d39:c3                   retq  
這一段彙編代碼的地址正是delete_obj函數指向的地址400d14。請看400d27位置的callq指令,調用的地址是400ce2。這個地址是dector的地址,即析構造的地址。再請看400d33的callq指令。[email protected]表示什麼意思呢?@plt表示這是一個引入了其他動態庫的函數。_ZdlPv用c++filt轉換後,就是名字"operator delete(void*)"。


在這裡,也提醒下各位,當使用虛類的時候,一定要帶上虛的析建構函式。否則在刪除一個虛類對象時,很可能會發生記憶體的泄漏!



你所不知道的C++ 之 C++虛類模型

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.