程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 派生類地址比基類地址少

派生類地址比基類地址少

編輯:C++入門知識

大家對虛表並不陌生,都知道每個含有虛函數的類對象都有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,接下來的是基類的成員變量,接下來再是自身的成員變量。

 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved