C++使用繼承時子對象的內存佈局

 

C++使用繼承時子對象的內存佈局html

 

C++使用繼承時子對象的內存佈局

1 示例程序

class A
{
protected:
    int a;
public:
    A() : a(1) {}

    virtual void a1() {}
    virtual void a2() {}
};

class B
{
protected:
    int b;
public:
    B() : b(2) {}

    virtual void b1() {}
    virtual void b2() {}
};

class C : public A, public B
{
protected:
    int c;
public:
    C() : c(3) {}

    virtual void a1() {}
    virtual void b1() {}
};

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

    return 0;
}

類 A/B/C 之間的關係以下:less

2 對象的內存佈局

C *c = new C();

在上面這段代碼中,對象 c 的內存佈局以下:ide

低地址        
       
1. 虛表指針 –> &C::a1 &A::a2 .
2. A::a        
3. 虛表指針 –> &C::b1 &B::b2 .
4. B::b        
5. c::c        
       
高地址        

c 對象從低地址到高地址依次存儲了:A 的虛表指針、A 的成員變量、B 的虛表指針、B 的成員變量、C 的成員變量。咱們發現,虛函數表 A 中的 A::a1 函數被 C::a1 函數覆蓋了,虛函數表 B 中 B::b1 函數被 C::b1 覆蓋了,這是由於 C 重寫了 a1 和 b1方法。這意味着經過 c 對象中的虛表指針調用 a1 或 b1 函數,只可以調用到 C 類中重寫的方法。函數

C *c = new C;
c->b1();

B *b = c;
b->b1();

上面的兩句調用都會調用 C 的 b1 方法。另外,在對 b 賦值時,b 獲得的結果並非 c 的值,而是 c+8,這正好是 c 對象中用於存儲 B 虛表指針的地址。佈局

Date: 2016-01-12T22:44+0800post

Author: rulelessspa

Org version 7.9.3f with Emacs version 24指針

Validate XHTML 1.0
相關文章
相關標籤/搜索