C++在多重继承下的指针类型强制类型转换的一些问题

原文地址:http://www.cnblogs.com/fangyukuan/archive/2010/05/30/1747516.html

在C/c++中,类型之间的转换是经常被遇到的,在C++中,经常会遇到指针的类型转换,比如将派生类指针转换为基类指针,将基类指针转换为派生类指针。指针的本质其实就是一个数字,用以记录进程虚拟内存空间中的地址编号,而指针的类型决定了编译器对其指向的内存空间的解释方式。

基于上面的理解,我们似乎可以得出一个结论,C++中对指针进行类型转换,不会改变指针的值,只会改变指针的类型(即改变编译器对该指针指向内存的解释方式),但是这个结论在C++多重继承下是 不成立的。

以下程序例子:

#include <iostream>   
using namespace std;   
  
class ca{   
        char m_a[32];   
};   
class cb{   
        char m_b[64];   
};   
class cd : public ca,public cb{   
        char m_d[128];   
};   
int main(int argc,char **argv)   
{   
        cd *pD = new cd;   
        ca *pA = (ca *)pD;   
        cb *pB = (cb *)pD;   
  
        cout << pA << endl;   
        cout << pB << endl;   
        cout << pD << endl;   
  
        cout << (pD == pB) << endl;   
  
        return 0;   
}  

这段代码的输出结果是:

可以看出,指向同一个堆上new出来的内存指针,在经过类型转换之后,其值会发生改变。究其原因,要从C++中多重继承的内存布局说起。


同时我们注意到,pB与pD的指针差值正好是ca占用的内存大小32字节,而pA与pD都指向了同一段地址。这是因为,将一个派生类的指针转换成某一个基类指针,编译器会将指针的值偏移到该基类在对象内存中的起始位置。

此时,pA 与 pD都指向ca对象的起始地址,pB 指向其起始地址刚好与ca对象的起始地址差32,所以可以看到pB打印出的地址比pA和pD的地址差32,而pA与pD均指向首地址。

接下来输出1表示pB和pD地址是相同的,其实这也是编译器屏蔽了这种指针的差异,当编译器发现一个指向派生类的指针和指向其某个基类的指针进行==运算时,会自动将指针做隐式类型提升已屏蔽多重继承带来的指针差异。因为两个指针做比较,目的通常是判断两个指针是否指向了同一个内存对象实例,在上面的场景中,pD和pB虽然指针值不等,但是他们确确实实都指向了同一个内存对象(即new cd;产生的内存对象 ),所以编译器又在此处插了一脚,让我们可以安享==运算的上层语义。



©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页