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