程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++虛函數表,函數表

C++虛函數表,函數表

編輯:C++入門知識

C++虛函數表,函數表


大家知道虛函數是通過一張虛函數表來實現的。在這個表中,主要是一個類的虛函數的地址表,這張表解決了繼承、覆蓋的問題,其內容真是反應實際的函數。這樣,在有虛函數的類的實例中,這個表分配在了這個實例的內存中,所以,當用父類的指針來操作一個子類的時候,這張虛函數表就顯得尤為重要了。它就像一個地圖一樣,指明了實際所應該調用的函數。

C++的標准規則中說到,編譯器必須保證虛函數表的指針存在於對象實例中最前面的位置(這樣是為了保證正確取到虛函數的偏移量)。這意味著通過對象實例的地址得到這張虛函數表,然後可以遍歷其中的函數指針,並調用相應的函數。

 

#include <iostream>
using namespace std;
class Base
{
public:
    virtual void fun1(){cout<<"Base::fun1\n";}
    virtual void fun2(){cout<<"Base::fun2\n";}
    virtual void fun3(){cout<<"Base::fun3\n";}
private:
    int num1;
    int num2;
};

typedef void (*Fun)(void);

int main()
{
    Base b;
    Fun pFun;
    //通過指針分別調用了對象b的3個虛函數。
    pFun = (Fun)* ( (int*)*(int*)(&b)+0 );
    pFun();
    pFun = (Fun)* ( (int*)*(int*)(&b)+1 );
    pFun();
    pFun = (Fun)* ( (int*)*(int*)(&b)+2 );
    pFun();
    return 0;
}
/*
程序執行結果如下:
Base::fun1
Base::fun2
Base::fun3
Press <RETURN> to close this window...
*/

程序中的Base對象b內存結構如下:

一個類會有多少張虛函數表呢?

對於一個單繼承的類,如果它有虛函數,則只有一張虛函數表。對於多重繼承的類,它可能有多張虛函數的表。

#include <iostream>
using namespace std;
class Base1
{
public:
    Base1(int num):num_1(num){}
    virtual void fun1(){cout<<"Base1::fun1 "<<num_1<<endl;}
    virtual void fun2(){cout<<"Base1::fun2 "<<num_1<<endl;}
    virtual void fun3(){cout<<"Base1::fun3 "<<num_1<<endl;}
private:
    int num_1;
};
class Base2
{
public:
    Base2(int num):num_2(num){}
    virtual void fun1(){cout<<"Base2::fun1 "<<num_2<<endl;}
    virtual void fun2(){cout<<"Base2::fun2 "<<num_2<<endl;}
    virtual void fun3(){cout<<"Base2::fun3 "<<num_2<<endl;}
private:
    int num_2;
};
class Base3
{
public:
    Base3(int num):num_3(num){}
    virtual void fun1(){cout<<"Base3::fun1 "<<num_3<<endl;}
    virtual void fun2(){cout<<"Base3::fun2 "<<num_3<<endl;}
    virtual void fun3(){cout<<"Base3::fun3 "<<num_3<<endl;}
private:
    int num_3;
};
class Derived1:public Base1
{
public:
    Derived1(int num):Base1(num){}
    virtual void fDer1_1(){cout<<"Derived1::fDer1_1\n";}//無覆蓋
    virtual void fDer1_2(){cout<<"Derived1::fDer1_2\n";}
};
class Derived2:public Base1
{
public:
    Derived2(int num):Base1(num){}
    virtual void fun2(){cout<<"Derived2::fun2 "<<endl;}//只覆蓋了Base1::fun2
    virtual void fDer2_1(){cout<<"Derived2::fDer2_1\n";}
    virtual void fDer2_2(){cout<<"Derived2::fDer2_2\n";}
};
class Derived3:public Base1,public Base2,public Base3//多重繼承,無覆蓋
{
public:
    Derived3(int num_1,int num_2,int num_3):Base1(num_1),Base2(num_2),Base3(num_3){}
    virtual void fDer3_1(){cout<<"Derived3::fDer3_1\n";}
    virtual void fDer3_2(){cout<<"Derived3::fDer3_2\n";}

};
class Derived4:public Base1,public Base2,public Base3//多重繼承,有覆蓋
{
public:
    Derived4(int num_1,int num_2,int num_3):Base1(num_1),Base2(num_2),Base3(num_3){}
    virtual void fun1(){cout<<"Derived4::fun1\n";}//覆蓋了所有基類的fun1函數
    virtual void fDer4_1(){cout<<"Derived4::fDer4_1\n";}

};
int main()
{
    Base1 *pBase1 = NULL;
    Base2 *pBase2 = NULL;
    Base3 *pBase3 = NULL;

    cout<<"-----  Generally inherited from Base1, no cover------\n";
    Derived1 d1(1);
    pBase1 = &d1;
    pBase1->fun1();

    cout<<"----- Generally inherited from Base1, covering fun2---\n";
    Derived2 d2(2);
    pBase1 = &d2;
    pBase1->fun2();

    cout<<"-----  Multiple inheritance, no cover-----------------\n";
    Derived3 d3(1,2,3);
    pBase1 = &d3;
    pBase2 = &d3;
    pBase3 = &d3;
    pBase1->fun1();
    pBase2->fun1();
    pBase3->fun1();

    cout<<"-----  Multiple inheritance, covering fun1-------------\n";
    Derived4 d4(1,2,3);
    pBase1 = &d4;
    pBase2 = &d4;
    pBase3 = &d4;
    pBase1->fun1();
    pBase2->fun1();
    pBase3->fun1();
    return 0;
}

/*
 * 程序運行結果如下:
-----  Generally inherited from Base1, no cover------
Base1::fun1 1
----- Generally inherited from Base1, covering fun2---
Derived2::fun2
-----  Multiple inheritance, no cover-----------------
Base1::fun1 1
Base2::fun1 2
Base3::fun1 3
-----  Multiple inheritance, covering fun1-------------
Derived4::fun1
Derived4::fun1
Derived4::fun1
Press <RETURN> to close this window...
*/

一般繼承(無虛函數覆蓋)

Derived1類繼承自Base1類,沒有任何覆蓋基類的函數,因此Dervied1的兩個虛擬函數被依次添加到了虛函數表的尾部。Derived1的虛函數表如下圖:

一般繼承(有虛函數的覆蓋)

Derived2繼承自Base1類,並對基類中的fun2()進行了覆蓋。所以虛函數表中的Derived2::fun2代替了Base::fun2,用時派生類中新的虛函數添加到虛函數的表尾。Derived2的虛函數表如下圖:

多重繼承(無虛函數覆蓋)

Derived3繼承自Base1,Base2,Base3,其虛函數表如下:

Base2 *pBase2 = new Derived3(); pBase->fun2();

把Base2類型的指針指向Derived3實例,那麼調用將是對應Base2虛表裡的那些函數.


多重繼承(有虛函數覆蓋)

Derived4類繼承自Base1,Base2,Base3並對3個基類的fun1函數進行了覆蓋。其虛函數表如下:

Base1 *pBase1 = new Derived4(); pBase1->fun1();


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved