程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++多重繼承與void*指針轉換問題的分析

C++多重繼承與void*指針轉換問題的分析

編輯:C++入門知識

C++多重繼承與void*指針轉換問題的分析


C++支持多重繼承,然而多重繼承可能會導致一些奇怪的問題,我前段時間遇到一個指針轉換問題,非常典型。

先看一個簡單的測試代碼:

#include 
using namespace std;

class IA 
{
public:
    virtual ~IA(){}
    virtual void a() = 0;
};

class IB
{
public:
    virtual ~IB(){}
    virtual void b() = 0;
};

class CMulti : public IA, public IB
{
public:
    CMulti(){}
    ~CMulti(){}

    void a(){ cout << "C::a()" << endl; }
    void b(){ cout << "C::b()" << endl; }
};

void testCastA(void *p)
{
    cout << "cast from void*(" << p << ")to IA*:  ";
    IA *a = (IA *)p;
    a->a();
}

void testCastB(void *p)
{
    cout << "cast from void*(" << p << ")to IB*:  ";
    IB *b = (IB *)p;
    b->b();
}


int _tmain(int argc, _TCHAR* argv[])
{
    CMulti * c = new CMulti;

    cout << "cast to void*, then to IA or IB:" << endl;
    testCastA((void*)c);
    testCastB((void*)c);
    cout << endl;

    cout << "static_cast to void*, then to IA or IB:" << endl;
    testCastA((void*)static_cast(c));
    testCastB((void*)static_cast(c));
    cout << endl;

    cout << "dynamic_cast to void*, then to IA or IB:" << endl;
    testCastA((void*)dynamic_cast(c));
    testCastB((void*)dynamic_cast(c));

    return 0;
}

我測試了:

強制轉換為void* 先static_cast再強制轉換為void* 先dynamic_cast再強制轉換為void*

(32位程序)運行的結果如下圖所示:

\

差異很明顯了,結論也很明了:多重繼承時,子類指針轉換為非第一繼承的父類指針時,會發生地址偏移(注意圖上標紅的部分)。這是因為每一個父類都會占用 4 個字節維護自己的虛函數表。所以,當 CMulti* 轉換為 IB* 時,指針加 4 ,因為 IA 是 CMulti 的第一父類, IB 是第二父類,依次類推……

如果我們在某些地方不得不使用 void* 來進行代碼適配時,遇到多重繼承就要注意這一點,否則很可能你調用的是 b() 方法,實際執行的是 a() ,達不到預期效果。

   

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