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

c++內存對象布局

編輯:C++入門知識

html">http://www.BkJia.com/kf/201104/88627.html

http://www.BkJia.com/kf/201104/88628.html

http://www.BkJia.com/kf/201104/88629.html

看完上面的文章,應該可以回答一個問題:指針被強制類型轉化之後,指針的值會改變嗎?
答案:有時候是會的。haoel把繼承分為5類,我再把它們作個標記:
沒有虛繼承:單一繼承(1), 非重復多重繼承(2), 重復多重繼承(3);
有虛繼承:單一繼承(4),重復多重繼承(5)。
我先區別兩個概念“類的內存布局(由此可以計算出類的大小)”和“類本身的內存布局(由此可以計算出類本身的大小)”:
sizeof(類)= sizeof(類本身) + sizeof(所有父類)。
而類本身的內存布局由兩部分構成:vptr + 成員變量, 整個類的內存布局是把類本身和所有父類的內存布局拼接在一起的,注意:對於類型(1),整個類只有一個vptr,因此父類的內存布局只有成員變量了。

拼接的規則是:先父類後子類,但特例是虛擬繼承,在虛擬繼承時,會變成“先子類後父類”,因為虛擬繼承的目的是:認為父類有common的東西,大家共享之。

因此,vptr不一定只能出現在類內存布局的始端,准確的說: 應該是出現在各個類本身的內存布局的始端。
當發生類型轉化時,比如要從Derived*轉化到Base*,轉化後的結果會是指向“Base這個父類自身的內存布局的始端”,一旦這個始端和“Derived類的內存布局始端“不一致,那麼
就發生了指針類型轉化後指針值的改變。
下面是一個例子:
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>

using namespace std;

class A {
public:
    virtual ~A() {};
    int iA;
};

class A1 {
public:
    virtual ~A1() {};
    int iA1;
};

class B: public A {
public:
    virtual ~B() {};
    int iB;
};

class C: virtual public A {
public:
    virtual ~C() {};
    int iC;
};

class D: public A, public A1 {
public:
    virtual ~D() {};
    int iD;
};

int main(int argc, char* argv[]) {
    A* pa = new B();
    cout << "B size:" << sizeof(B) << endl;
    cout << "A addr:" << pa << endl;
    cout << "B addr ():" << (B*)pa << endl;
    cout << "B addr dynamic_cast:" << dynamic_cast<B*>(pa) << endl;

    cout << "-------------------------------" << endl;

    A* pa2 = new C();
    cout << "C size:" << sizeof(C) << endl;
    cout << "A addr:" << pa2 << endl;
    //cout << "C addr ():" << (C*)pa2 << endl; //compile error
    cout << "C addr dynamic_cast:" << dynamic_cast<C*>(pa2) << endl;

    cout << "-------------------------------" << endl;

    C* pc = dynamic_cast<C*>(pa2);
    cout << "C addr dynamic_cast:" << pc << endl;
    cout << "A addr ():" << (A*)pc << endl;
    cout << "A addr dynamic_cast:" << dynamic_cast<A*>(pc) << endl;

    cout << "-------------------------------" << endl;

    D* pd = new D();
    cout << "D size:" << sizeof(D) << endl;
    cout << "D addr:" << pd << endl;
    cout << "A addr ():" << (A*)pd << endl;
    cout << "A addr dynamic_cast:" << dynamic_cast<A*>(pd) << endl;
    cout << "A1 addr dynamic_cast:" << dynamic_cast<A1*>(pd) << endl;
    return 0;
}

結果:
B size:16
A addr:0x8a96010
B addr ():0x8a96010
B addr dynamic_cast:0x8a96010
-------------------------------
C size:32
A addr:0x8a96040
C addr dynamic_cast:0x8a96030
-------------------------------
C addr dynamic_cast:0x8a96030
A addr ():0x8a96040
A addr dynamic_cast:0x8a96040
-------------------------------
D size:32
D addr:0x8a96060
A addr ():0x8a96060
A addr dynamic_cast:0x8a96060
A1 addr dynamic_cast:0x8a96070

最後再來一篇

http://www.BkJia.com/kf/201104/88630.html

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