在Java中,继承类可以使用super访问基类中的数据变量
但是在C++中,貌似没有此类访问符。。。
能否在C++中访问基类中的数据呢?当然能够,最简单的方式莫过于在基类中定义Get/Set等属性函数,在继承类中使用即可。
问题是,变量太多,定义n多的Get/Set看着有些烦人。
呵呵,其实可以采用一种不是很正规的方式来直接访问基类中的数据(注意:在真实的项目中不建议使用此类方法,这个方法仅仅用于对C++二进制布局的了解+测试而已。我目前已经用vc8、gcc测试通过)
我们知道,在C++中,基类和继承类对象其实享用的同一块内存空间。即this指针所指位置。我们的所有数据都在this指针所指位置上,所有数据按照内存正向规则向上占用各自的位置。
例子代码:
问题:一旦在基类中出现了虚拟函数,此时的this指针不再指向数据的第一个变量,而是指向vptr。
在此种情况下需要给this指针加上一个vptr的指针变量位置即可。
补充:
既然知道了vptr的位置,那我们可以直接手工打造函数地址来调用它(我只使用vc8调用通过,gcc调用报错。。。)
vc的c++虚拟指针手工调用
class A
{
int i = -1;
}
class B extends A
{
void printSuperI()
{
System.out.println(super.i);
}
}
{
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);
}
};
{
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);
}
};
{
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");
}
};
{
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");
}
};