shootingstars

菩提本无树,明镜亦非台。本来无一物,何处惹尘埃。尘埃乃虚幻,亦何惧之来?

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
在Java中,继承类可以使用super访问基类中的数据变量
class A
{
    
int i = -1;
}


class B extends A
{
    
void printSuperI()
    
{
        System.out.println(
super.i);
    }

}

但是在C++中,貌似没有此类访问符。。。
能否在C++中访问基类中的数据呢?当然能够,最简单的方式莫过于在基类中定义Get/Set等属性函数,在继承类中使用即可。
问题是,变量太多,定义n多的Get/Set看着有些烦人。
呵呵,其实可以采用一种不是很正规的方式来直接访问基类中的数据(注意:在真实的项目中不建议使用此类方法,这个方法仅仅用于对C++二进制布局的了解+测试而已。我目前已经用vc8、gcc测试通过)
我们知道,在C++中,基类和继承类对象其实享用的同一块内存空间。即this指针所指位置。我们的所有数据都在this指针所指位置上,所有数据按照内存正向规则向上占用各自的位置。

例子代码:
class A
{
public:
    
int i,j;
    A()
    
{
        i 
= -1;
        j 
= -2;
    }


}
;

class B : public A
{
public:
    
void printSuperI()
    
{
        
// 此this指针及指向A::i的内存位置
        int superI = *(int *)(this);   
        
// 此this+4指针及指向A::j的内存位置(sizeof(int) == 4)
        
// 注意:此时必须知道C++的内存对齐方案,当然你可以通过命令要求按照自己的规则进行内存对齐。
        int superJ = *(int *)((char*)this+4);  
        printf(
"SuperI=%d, superJ=%d\n",superI,superJ);
    }

}
;


问题:一旦在基类中出现了虚拟函数,此时的this指针不再指向数据的第一个变量,而是指向vptr。
在此种情况下需要给this指针加上一个vptr的指针变量位置即可。
class A
{
public:
    
int i;
    A()
    
{
        i 
= -1;
    }

    
virtual void foo()
    
{
        printf(
"Foo\n");
    }


}
;

class B : public A
{
public:
    
void printSuperI()
    
{
        
int superI = *(int *)((char*)this+4);
        printf(
"SuperI=%d\n",superI);
    }

}
;


补充:
既然知道了vptr的位置,那我们可以直接手工打造函数地址来调用它(我只使用vc8调用通过,gcc调用报错。。。)
vc的c++虚拟指针手工调用
class A
{
public:
    
int i;
    
char *p;
    A()
    
{
        p 
= "5678";
        i 
= -1;
    }

    
virtual void foo(const char *s)
    
{
        printf(
"Foo, %s : %s\n",s, p);
    }

    
virtual void foo1(const char *s)
    
{
        printf(
"Foo1, %s\n",s);
    }


}
;

typedef 
void (A::*foo_fun)(const char *p);

class B : public A
{
public:
    
void printSuperI()
    
{
        unsigned 
int *vptr;
        
int superI = *(int *)((char*)this+4);
        printf(
"SuperI=%d\n",superI);
        vptr 
= (unsigned int *)this;
        foo_fun fun_ptr 
= *(foo_fun*)(*vptr);
        (
this->*fun_ptr)("1234");
        foo_fun fun_ptr1 
= *(foo_fun*)((*vptr)+4);
        (
this->*fun_ptr1)("abcd");
    }

}
;

posted on 2008-06-02 09:23  shootingstars  阅读(2572)  评论(0编辑  收藏  举报