`

在类的外面调用类保护类型的虚函数

    博客分类:
  • C++
 
阅读更多

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
class A{ 
protected:
virtual void fun(){
	printf("class:a		function:fun\n");
}
virtual void fun2(){
	printf("class:a		function:fun2\n");
}
};
class B:public A{
protected:
void fun(){
	printf("class:b		function:fun\n");
}
void fun2(){
	printf("class:b		function:fun2\n");
}
};


int main(){
	//输入和输出重定向  
    freopen("in.txt","r", stdin);  
    freopen("out.txt", "w", stdout); 
	void (*fun)(A*); 
	A* pa = new B(); 
	long fp; 
	memcpy(&fp, pa, 4); 
	memcpy(&fun, reinterpret_cast<long*>(fp), 4); 
	fun(pa); 
	memcpy(&fun, reinterpret_cast<long*>(fp)+1, 4); 
	fun(pa); 
	delete pa; 
    return 0; 
}

 输出结果如下:

class:b function:fun

class:b function:fun2

 

百度百科的解释:

void (*fun)(A*); 这段定义了一个函数指针名字叫做fun,而且有一个A*类型的参数,这个函数指针待会儿用来保存从vtbl里取出的函数地址
A* p=new B(); new B是向内存(内存分5个区:全局名字空间,自由存储区,寄存器,代码空间,栈)自由存储区申请一个内存单元的地址然后隐式地保存在一个指针中.然后把这个地址赋值给A类型的指针P.
.
long fp; 这个long类型的变量待会儿用来保存vptr的值
memcpy(&fp,pa,4); 前面说了,他们的实例对象里只有vptr指针,所以我们就放心大胆地把pa所指的4bytes内存里的东西复制到fp中,所以复制出来的4bytes内容就是vptr的值,即vtbl的地址
现在有了vtbl的地址了,那么我们现在就取出vtbl第一个slot里的内容
memcpy(&fun, reinterpret_cast<long*>(fp), 4); 取出vtbl第一个slot里的内容,并存放在函数指针fun里。需要注意的是fp里面是vtbl的地址,但fp不是指针,所以我们要把它先转变成指针类型
fun(pa); 这里就调用了刚才取出的函数地址里的函数,也就是调用了B::fun()这个函数,也许你发现了为什么会有参数p,其实类成员函数调用时,会有个this指针,这个p就是那个this指针,只是在一般的调用中编译器自动帮你处理了而已,而在这里则需要自己处理

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics