so true

          心懷未來,開創(chuàng)未來!
          隨筆 - 160, 文章 - 0, 評論 - 40, 引用 - 0
          數(shù)據(jù)加載中……

          c++內(nèi)存對象布局

          收藏陳皓的幾篇博文:
          http://haoel.blog.51cto.com/313033/124567
          http://haoel.blog.51cto.com/313033/124561
          http://haoel.blog.51cto.com/313033/124595

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

          拼接的規(guī)則是:先父類后子類,但特例是虛擬繼承,在虛擬繼承時,會變成“先子類后父類”,因?yàn)樘摂M繼承的目的是:認(rèn)為父類有common的東西,大家共享之。

          因此,vptr不一定只能出現(xiàn)在類內(nèi)存布局的始端,準(zhǔn)確的說: 應(yīng)該是出現(xiàn)在各個類本身的內(nèi)存布局的始端。
          當(dāng)發(fā)生類型轉(zhuǎn)化時,比如要從Derived*轉(zhuǎn)化到Base*,轉(zhuǎn)化后的結(jié)果會是指向“Base這個父類自身的內(nèi)存布局的始端”,一旦這個始端和“Derived類的內(nèi)存布局始端“不一致,那么
          就發(fā)生了指針類型轉(zhuǎn)化后指針值的改變。
          下面是一個例子:
          #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;
          }

          結(jié)果:
          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

          下面還有篇對haoel的介紹,也一并收藏了:
          http://news.csdn.net/n/20070706/106194.html

          posted on 2011-04-24 12:52 so true 閱讀(1962) 評論(0)  編輯  收藏 所屬分類: C&C++

          主站蜘蛛池模板: 信丰县| 壶关县| 冷水江市| 葵青区| 彰化市| 乃东县| 扎鲁特旗| 海原县| 海宁市| 枣阳市| 绥宁县| 南丹县| 手游| 宜州市| 新郑市| 韩城市| 荥经县| 青岛市| 郧西县| 当涂县| 屯留县| 西昌市| 都匀市| 阜南县| 民勤县| 黔江区| 金溪县| 托克逊县| 清远市| 文水县| 济宁市| 介休市| 遂平县| 娱乐| 卢湾区| 常德市| 成都市| 凯里市| 甘洛县| 灵台县| 西贡区|