1. 程式人生 > >陳皓-C++ 物件的記憶體佈局(上):筆記

陳皓-C++ 物件的記憶體佈局(上):筆記

單一的一般繼承

程式碼如下:

#include <iostream>
using namespace std;

class Parent {
public:
    int iparent;
    Parent ():iparent (10) {}
    virtual void f() { cout << " Parent::f()" << endl; }
    virtual void g() { cout << " Parent::g()" << endl; }
    virtual void h() { cout << " Parent::h()" << endl; }

    virtual ~Parent() {}

};

class Child : public Parent {
public:
    int ichild;
    Child():ichild(100) {}
    virtual void f() { cout << "Child::f()" << endl; }
    virtual void g_child() { cout << "Child::g_child()" << endl; }
    virtual void h_child() { cout << "Child::h_child()" << endl; }

    virtual ~Child() {}
};

class GrandChild : public Child{
public:
    int igrandchild;
    GrandChild():igrandchild(1000) {}
    virtual void f() { cout << "GrandChild::f()" << endl; }
    virtual void g_child() { cout << "GrandChild::g_child()" << endl; }
    virtual void h_grandchild() { cout << "GrandChild::h_grandchild()" << endl; }

    virtual ~GrandChild() {}
};

typedef void(*Fun)(void);

int main()
{

    GrandChild gc;

    int** pVtab = (int**)&gc;
    Fun pFun = NULL;

    cout << "[0] GrandChild::_vptr->" << endl;
    for (int i=0; (Fun)pVtab[0][i]!=NULL && i<3; i++)
    {
		pFun = (Fun)pVtab[0][i];
		cout << "    ["<<i<<"] ";
		pFun();
    }

    //cout << "[1] Parent.iparent = " << (int)*((int*)(&gc)+1) << endl;
    cout << "[1] Child.ichild = " << (int)pVtab[1] << endl;
    cout << "[2] Child.ichild = " << (int)pVtab[2] << endl;
    cout << "[3] GrandChild.igrandchild = " << (int)pVtab[3] << endl;

    return 0;
}

for迴圈中必須有"i<3"的約束條件,否則會報讀記憶體錯誤。

對"(int)pVtab[1]"的理解:與(int)*((int*)(&gc)+1)是等價的。這是C語言中獲取指標指向內容的兩種方式:1)解引用; 2)下標操作。


多重繼承

程式碼如下:
/*
 * multiple_inheritance.h
 *
 *  Created on: 2013-10-1
 *      Author: Administrator
 */

#ifndef MULTIPLE_INHERITANCE_H_
#define MULTIPLE_INHERITANCE_H_

#include <iostream>
using namespace std;

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

	virtual ~Base1() {}
};

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

	virtual ~Base2() {}
};

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

	virtual ~Base3() {}
};


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

	virtual ~Derive() {}
};



#endif /* MULTIPLE_INHERITANCE_H_ */

int main()
{

    GrandChild gc;

    int** pVtab = (int**)&gc;
    Fun pFun = NULL;

    //Base1
    cout << "[0] Base1::_vptr->" << endl;
    for (int i=0; (Fun)pVtab[0][i]!=NULL && i<3; i++)
    {
		pFun = (Fun)pVtab[0][i];
		cout << "    ["<<i<<"] ";
		pFun();
    }
    cout << "[1] Base1.ibase1 = " << (int)pVtab[1] << endl;

    //Base2
    int s = sizeof(Base1)/4; //Derive類繼承在Base1類部分所佔記憶體的大小
    cout << "[" << s << "]" << "Base2::_vptr->" << endl;
    for (int i=0; (Fun)pVtab[s][i]!=NULL && i<3; i++)
    {
		pFun = (Fun)pVtab[s][i];
		cout << "    ["<<i<<"] ";
		pFun();
    }
    cout << "[" << s+1 << "]" << "Base2.ibase2 = " << (int)pVtab[s+1] << endl;

    //Base3
    s += sizeof(Base2)/4;
    cout << "[" << s << "]" << "Base3::_vptr->" << endl;
    for (int i=0; (Fun)pVtab[s][i]!=NULL && i<3; i++)
    {
		pFun = (Fun)pVtab[s][i];
		cout << "    ["<<i<<"] ";
		pFun();
    }
    cout << "[" << s+1 << "]" << "Base3.ibase3 = " << (int)pVtab[s+1] << endl;

    //Derive
    s += sizeof(Base3)/4;
    cout << "[" << s << "]" << "Derive.iderive = " << (int)pVtab[s] << endl;

    return 0;
}

報讀記憶體錯誤,文章內容未得到驗證。通過vs2010檢視Derive類物件gc的記憶體佈局和文章說的不一致,如下: