灯火互联
管理员
管理员
  • 注册日期2011-07-27
  • 发帖数41778
  • QQ
  • 火币41290枚
  • 粉丝1086
  • 关注100
  • 终身成就奖
  • 最爱沙发
  • 忠实会员
  • 灌水天才奖
  • 贴图大师奖
  • 原创先锋奖
  • 特殊贡献奖
  • 宣传大使奖
  • 优秀斑竹奖
  • 社区明星
阅读:4175回复:0

[C++技术]派生类地址比基类地址少

楼主#
更多 发布于:2013-05-14 10:27

大家对虚表并不陌生,都知道每个含有虚函数的类对象都有1个虚指针,但是在现实使用中,却总是因为这而调试半天,才发现原来是虚指针惹的祸。我这几天在调试代码时候也中招了,我的问题是这样的,如下图,CTree是最底层基类(非虚类), CSamplerTree(虚类)派生自CTree,CMSamplerTree,CASamplerTree派生自CSamplerTree,

                                                                                                   

CTree中包括两个成员变量,QList <CTree *> childList;树中有多少个孩子节点;CTree *parent;当前树节点的父亲节点,程序中我大量使用CTree *pTree指针指向CSamplerTree、CMSamplerTree、CASamplerTree ,从而达到统一处理的目的,从而使代码很简洁,复用性高。但是谁曾想到,程序一运行就会崩溃,通过调试发现,CSamplerTree、CMSamplerTree、CASamplerTree的指针当指向CTree的指针时,地址均加了4,为什么呢?为了加深理解,我做了一个简单的测试代码:

[cpp]

#include <stdio.h>class CBase {  

public:

    CBase() {}

    void func()

    {

        printf("base\n");

    }

};

class CDerived : public CBase {

public:

    CDerived() {}

    virtual void func1()

    {

        printf("derived\n");

    }

};

void main()

{

     CBase *pBase = new CDerived();

     pBase->func();

     CDerived *pDerived = (CDerived *)pBase;

     printf("%d %d\n", pDerived, pBase);

     pDerived->func();    

     CBase *pBase1 = new CBase();

     pBase1->func();

     CDerived *pDerived1 = (CDerived *)pBase1;

     printf("%d %d\n", pDerived1, pBase1);

     pDerived1->func();

}

#include <stdio.h>class CBase {

public:

    CBase() {}

    void func()

    {

        printf("base\n");

    }

};

class CDerived : public CBase {

public:

 CDerived() {}

 virtual void func1()

 {

  printf("derived\n");

 }

};

void main()

{

     CBase *pBase = new CDerived();

     pBase->func();

     CDerived *pDerived = (CDerived *)pBase;

     printf("%d %d\n", pDerived, pBase);

     pDerived->func();

     CBase *pBase1 = new CBase();

     pBase1->func();

     CDerived *pDerived1 = (CDerived *)pBase1;

     printf("%d %d\n", pDerived1, pBase1);

     pDerived1->func();

}下面是输出的结果,从结果可以看出派生类指针指向基类指针,指针地址会加4,基类指针指向派生类时,指针地址会减4。

base

200672 200676

derived

base

200740 200744

Press any key to continue

下面我们看看派生类对象和基类对象的内存是如何组织的,我们在上例的基础上引入2个变量,代码如下:

[cpp]

#include <stdio.h>class CBase {  

public:

    CBase() {}

    void func()

    {

        printf("base\n");

    }

    int a;

};

class CDerived : public CBase {

public:

    CDerived() {}

    virtual void func1()

    {

        printf("derived\n");

    }

       int b;

};

void main()

{

     CBase *pBase = new CDerived();

     CDerived *pDerived = (CDerived *)pBase;      

     printf("%d %d\n", pDerived, pBase);

     printf("%d %d %d\n", &pDerived->a, &pDerived->b, &pBase->a);

}

#include <stdio.h>class CBase {

public:

    CBase() {}

    void func()

    {

        printf("base\n");

    }

    int a;

};

class CDerived : public CBase {

public:

 CDerived() {}

 virtual void func1()

 {

  printf("derived\n");

 }

       int b;

};

void main()

{

     CBase *pBase = new CDerived();

     CDerived *pDerived = (CDerived *)pBase;    

     printf("%d %d\n", pDerived, pBase);

     printf("%d %d %d\n", &pDerived->a, &pDerived->b, &pBase->a);

}

200672 200676

200676 200680 200676

Press any key to continue

从输出结果我们可看出,CDerived对象的起始地址存放的是虚表指针vptr,接下来的是基类的成员变量,接下来再是自身的成员变量。


喜欢0 评分0
游客

返回顶部