首先我们来看一下下面这段代码,类C多重继承自类A和类B,观察程序运行后打印的结果我们会发现 (A*)c 和 (B*)c 的值不同,为什么做了一次强转之后的值会不一样呢?
#include "stdafx.h"
#include <iostream>
using namespace std;
class A
{
public:
virtual void DrinkSomething(){};
private:
int A1;
int A2;
};
class B
{
public:
virtual void EatSomething(){};
private:
int B1;
int B2;
};
class C : public A, public B
{
private:
int C1;
int C2;
};
int _tmain(int argc, _TCHAR* argv[])
{
A* a = new A();
B* b = new B();
C* c = new C();
cout << "c pointer:" << c << endl;
cout << "c pointer:" << (A*)c << endl;
cout << "c pointer:" << (B*)c << endl;
B* pB = c;
cout << "pB pointer:" << pB << endl;
A* pA = dynamic_cast<A*>(pB);
cout << "pA pointer:" << pA << endl;
cin.get();
return 0;
}
原来编译器在强转的时候会根据自定义类的子类父类关系,对指针的值进行位置偏移。入下图所示。
pointerC 是一个 C 类型的指针变量,它指向一个 C 类变量的内存空间,如图中的长方体,由于 C 多重继承自 A 和 B ,所以他的内存空间由A和B两部分组成。当进行 (A*) pointerC 或者是 B* pointerB = pointerC这样的操作时,编译器就会根据内存的布局,重新定位到C类内存空间中真正指向A类内存空间的部分。
B* pB = c;
cout << "pB pointer:" << pB << endl;
A* pA = dynamic_cast<A*>(pB);
cout << "pA pointer:" << pA << endl;
下面我们来浅谈一下dynamic_cast的用途。dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的,在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。另外,dynamic_cast还支持交叉转换(cross cast)。
#include<iostream>
using namespace std;
class A{
public:
int m_nA;
};
class B{
public:
int m_nB;
};
class C:public A,public B{
public:
int m_nC;
};
int main()
{
C *pC = new C;
cout<<"pC= "<<(int) pC<<endl;
B *pB = dynamic_cast<B*>(pC); //a
B *pB1 = static_cast<B*>(pC); //b
B *pB2 = pC; //c
cout<<"pB= "<<(int) pB<<endl;
cout<<"pB1="<<(int) pB1<<endl;
cout<<"pB2="<<(int) pB2<<endl;
return 0;
}
运行结果:
分析:这是一个派生类指针向基类指针转换的例子,这种转换只是将派生类指针向下挪几个位置(挪多少与具体成员有关),即指向到基类位置的地方。因为在派生类中既包含基类成员又包含派生类成员。