午夜视频在线网站,日韩视频精品在线,中文字幕精品一区二区三区在线,在线播放精品,1024你懂我懂的旧版人,欧美日韩一级黄色片,一区二区三区在线观看视频

分享

C++虛函數(shù)機制解析

 Double360 2014-06-09

C++的虛函數(shù)(Virtual Function)是通過一張?zhí)摵瘮?shù)表(Virtual Table)來實現(xiàn)的。簡稱為V-Table。 在這個表中,主是要一個類的虛函數(shù)的地址表,這張表解決了繼承、覆蓋的問題,保證其容真實反應實際的函數(shù)。這樣,在有虛函數(shù)的類的實例中這個表被分配在了 這個實例的內(nèi)存中,所以,當我們用父類的指針來操作一個子類的時候,這張?zhí)摵瘮?shù)表就顯得由為重要了,它就像一個地圖一樣,指明了實際所應該調(diào)用的函數(shù)。

1. 無繼承的情況

#include <iostream>
using namespace std;

class Base {
public:
    virtual void f() { cout << "Base::f()" << endl; }
    virtual void g() { cout << "Base::g()" << endl; }
    virtual void h() { cout << "Base::h()" << endl; }
};

int main()
{
    typedef void (*Fun)();

    Base *b = new Base;
    cout << *(int*)(&b) << endl; //虛函數(shù)表的地址存放在對象最開始的位置

    Fun funf = (Fun)(*(int*)*(int*)b);
    Fun fung = (Fun)(*((int*)*(int*)b + 1));
    Fun funh = (Fun)(*((int*)*(int*)b + 2));


    funf();
    fung();
    funh();


    cout << (Fun)(*((int*)*(int*)b + 3)); // 最后一個位置為0,表明虛函數(shù)表的結(jié)束

    return 0;
}


注意:在上面這個圖中,虛函數(shù)表中最后一個節(jié)點相當于字符串的結(jié)束符,其標志了虛函數(shù)表的結(jié)束,在Codeblocks下打印為0。 


2. 繼承,無虛函數(shù)覆蓋的情形

#include <iostream>
using namespace std;

class Base {
public:
    virtual void f() { cout << "Base::f()" << endl; }
    virtual void g() { cout << "Base::g()" << endl; }
    virtual void h() { cout << "Base::h()" << endl; }
};

class Derive: public Base {
    virtual void f1() { cout << "Derive::f1()" << endl; }
    virtual void g1() { cout << "Derive::g1()" << endl; }
    virtual void h1() { cout << "Derive::h1()" << endl; }
};

int main()
{
    typedef void (*Fun)();

    Base *b = new Derive;
    cout << *(int*)b << endl;
    Fun funf = (Fun)(*(int*)*(int*)b);
    Fun fung = (Fun)(*((int*)*(int*)b + 1));
    Fun funh = (Fun)(*((int*)*(int*)b + 2));
    Fun funf1 = (Fun)(*((int*)*(int*)b + 3));
    Fun fung1 = (Fun)(*((int*)*(int*)b + 4));
    Fun funh1 = (Fun)(*((int*)*(int*)b + 5));


    funf(); // Base::f()
    fung(); // Base::g()
    funh(); // Base::h()
    funf1(); // Derive::f1()
    fung1(); // Derive::g1()
    funh1(); // Derive::h1()

    cout << (Fun)(*((int*)*(int*)b + 6));
    return 0;
}


從上表可以發(fā)現(xiàn):

1.  虛函數(shù)按照其聲明順序放于表中。

2.  父類的虛函數(shù)在子類的虛函數(shù)前面。 



3. 繼承,虛函數(shù)覆蓋的情形


#include <iostream>
using namespace std;

class Base {
public:
    virtual void f() { cout << "Base::f()" << endl; }
    virtual void g() { cout << "Base::g()" << endl; }
    virtual void h() { cout << "Base::h()" << endl; }
};

class Derive: public Base {
    virtual void f() { cout << "Derive::f()" << endl; }
    virtual void g1() { cout << "Derive::g1()" << endl; }
    virtual void h1() { cout << "Derive::h1()" << endl; }
};

int main()
{
    typedef void (*Fun)();

    Base *b = new Derive;
    cout << *(int*)b << endl;
    Fun funf = (Fun)(*(int*)*(int*)b);
    Fun fung = (Fun)(*((int*)*(int*)b + 1));
    Fun funh = (Fun)(*((int*)*(int*)b + 2));
    Fun fung1 = (Fun)(*((int*)*(int*)b + 3));
    Fun funh1 = (Fun)(*((int*)*(int*)b + 4));


    funf(); // Derive::f()
    fung(); // Base::g()
    funh(); // Base::h()
    fung1(); // Derive::g1()
    funh1(); // Derive::h1()

    cout << (Fun)(*((int*)*(int*)b + 5));
    return 0;
}



從上表可以看出:


1.  覆蓋的f()函數(shù)被放到了虛表中原來父類虛函數(shù)的位置。

2.  沒有被覆蓋的函數(shù)依舊。

3.  可通過獲取獲取成員函數(shù)指針來調(diào)用成員函數(shù)(即使是private類型的),帶 來一定安全性的影響。



4. 多繼承的情形


#include <iostream>
using namespace std;

class Base1 {
public:
    virtual void f() { cout << "Base1::f()" << endl; }
    virtual void g() { cout << "Base1::g()" << endl; }
    virtual void h() { cout << "Base1::h()" << endl; }
};

class Base2 {
public:
    virtual void f() { cout << "Base2::f()" << endl; }
    virtual void g() { cout << "Base2::g()" << endl; }
    virtual void h() { cout << "Base2::h()" << endl; }
};


class Base3 {
public:
    virtual void f() { cout << "Base3::f()" << endl; }
    virtual void g() { cout << "Base3::g()" << endl; }
    virtual void h() { cout << "Base3::h()" << endl; }
};


class Derive: public Base1,public Base2, public Base3 {
    virtual void f() { cout << "Derive::f()" << endl; }
    virtual void g1() { cout << "Derive::g1()" << endl; }
};

int main()
{
    typedef void (*Fun)();

    Derive d;
    Base1 *b1 = &d;
    Base2 *b2 = &d;
    Base3 *b3 = &d;


    b1->f(); //Derive::f()
    b2->f(); //Derive::f()
    b3->f(); //Derive::f()
    b1->g(); //Base1::g()
    b2->g(); //Base2::g()
    b3->g(); //Base3::g()


    Fun b1fun = (Fun)(*(int*)*(int*)b1);
    Fun b2fun = (Fun)(*(int*)*((int*)b1+1));
    Fun b3fun = (Fun)(*(int*)*((int*)b1+2));

    b1fun(); // Derive::f()
    b2fun(); // Derive::f()
    b3fun(); // Derive::f()

    return 0;
}



從上表可以看出:


1. 每個父類都有自己的虛表。

2. 子類的成員函數(shù)被放到了第一個父類的表中。(所謂的第一個父類是按照聲明順序來判斷的)

3. 對于多繼承無虛函數(shù)覆蓋的情況,布局與上圖類似(Derive的位置對應Base)

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多