C++跟我一起透徹理解虛函數表,函數表

來源:互聯網
上載者:User

C++跟我一起透徹理解虛函數表,函數表

//首先讓我們來瞭解類對象的構造順序。#include <iostream>using namespace std;class A{public:    A(){ cout << "A" << endl; }    virtual void PrintfA() = 0;};class B {public:    B(){ cout << "B" << endl; }};class C :virtual public A , public B{    //關於構造對象順序:    //第一步先構造虛基類,例如此處的虛繼承。    //第二步構造一般繼承類,此處從左往右順序執行。    //第三部構造成員變數,記住這裡的成員變數的構造是順序執行的。    //第四構造自身的建構函式。public:    C()    { cout << "C" << endl; }    void PrintfA()    {        cout << "hello word!!" << endl;    }private:};int main(){    C c;    return 0;}

#include <iostream>using namespace std;typedef void (*Pfun)();class Base{public:    virtual void Printf()    {        cout << "Base::Printf()" << endl;    }    void PrintfBae()    {        cout << "Base::PrintfBase" << endl;    }};class Son1:public Base{public:    virtual void Printf()    {        cout << "Son1::Printf()" << endl;    }    void PrintfSon1()    {        cout << "Son1::PrintfSon1()" << endl;    }};class Son2 : public Son1{public:    void Printf()    {        cout << "Son2::Printf()" << endl;    }    virtual void hello()    {        cout << "hello" << endl;    }    void PrintfSon2()    {        cout << "Son2::Printf()" << endl;    }};int main(){    Son2 s2;    Base &b = s2;    //b.Printf();    //此處可以得出這三個類維護了一個共同的虛表,但是我們還無法知道他們的    //具體位置以及各個類裡面非虛函數的儲存關係,所以我們接下來驗證。    //Pfun fun = (Pfun)*((int *)(&(int*)&b)+1);    Pfun fun = (Pfun)*((int *)*(int *)(int *)(&b) + 0);    //這種做法基本沒有人解釋,所以我在後面用圖解釋了。    fun();    fun = (Pfun)*((int *)*(int *)(int *)(&b) + 1);    fun();    //--------------------------------------------------------    fun = (Pfun)*((int *)*(int *)(int *)(&s2) + 0);    fun();    fun = (Pfun)*((int *)*(int *)(int *)(&b) + 1);    fun();    //列印結果與上面一樣,可以得出這份虛表是所有繼承該擁有虛表基類的成員類所共用的。    //每個對象的產生必定有兩個資料,一個vptr指向虛表的指標,還有其自身的成員    //變數。    return 0;}//總結1:前提是基類是有虛表的,單一繼承,所有的成員類與基類共同維護同一個虛表,各自有//一個vptr指向這個虛表,子類如果會對虛表進行替換修改,具體會根據子類是否重載了基類的//虛函數來確定,我們成為覆蓋。多繼承下面討論,其實本質是一樣的,關鍵問題是,多繼承中//子類中到底有幾份虛vptr指標。

#include<iostream>using namespace std;class A{public:    virtual void Printf()    {        cout << "A::Printf()" << endl;    }    virtual void PrintfA()    {        cout << "A::PrintfA()" << endl;    }};class B{public:    virtual void PrintfB()    {        cout << "B::Printf()" << endl;    }    virtual void Printf()    {        cout << "B::Printf()" << endl;    }};class C : public A, public B{public:    void Printf()    {        cout << "C::Printf()" << endl;    }};int main(){    typedef void(*PFun)();    C c;    PFun fun = (PFun)*((int *)*(int *)((int *)(&c)+0) + 0);//第一個虛表指標vptr。    fun();//此處覆蓋了,調用的是C中的Printf();    fun = (PFun)* ((int *)*(int *)((int *)(&c) + 1) + 0);//第二個虛表指標vptr。    fun();    //此處還有一個亮點,就是為什麼(int *)(int *)兩次,這下你應該明白了吧,因為可能    //有多個虛指標,編譯器做的很好了,如果不這樣做編譯會報錯。    cout << sizeof(c) << endl;//終極測試結果8。    return 0;}//總結2:多繼承中每一個基類都維護一張自己的虛表,而子類中每繼承一個虛基類就會有存在一個//指向該基類虛表的指標,以上代碼測試結果是C對象中有兩個vptr指標,一個指向A基類的虛表,一//個指向B基類的虛表。

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.