#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指针,只是在一般的调用中
编译器自动帮你处理了而已,而在这里则需要自己处理
分享到:
相关推荐
c++里,指针和引用是很重要的概念,这个程序不仅对指针和引用做了说明、使用,而且对子类不能继承父类虚函数也做了说明。
在虚函数的基类与子类构造函数中调用虚函数。当生成子类对象时,函数的调用顺序是怎样的
在C++中,成员函数的指针是个...但对成员函数来说,常规类型转换是通不过编译的,调用的时候也必须采用特殊的语法。C++专门为成员指针准备了三个运算符: "::*"用于指针的声明,而"->*"和".*"用来调用指针指向的函数。
C++虚函数调用机制初探.pdf
本文给大家分享了避免析构函数调用虚函数。
为了验证C++类间函数的相互调用,利用VC6.0的对话框和任意一个逻辑类,实现了点击对话框按钮-〉调用逻辑类函数-〉在对话框显示运行结果的功能
C++中的类中函数调用,只是基于简单的函数调用的例子
Delphi子类调用祖父类的虚函数.mht
2. 从使用角度,虚函数主要用于在信息不全的情况下,能使重载的函数得到对应的调用。构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀。所以构造函数没有必要是虚函数。虚函数的作用在于通过父类的指针...
题目:设计基类点类(Point)、直接派生类圆类(Circle)、间接派生类圆柱体类(Cylinder),将求面积的函数(area)声明成虚函数,并在主函数实现虚函数调用,输出点类、圆类和圆柱体类面积。提示:其他数据成员和...
remote-function支持调用普通函数,也支持调用类的成员函数。 remote-function底层使用命令管道进行通讯,内置的流程完成了函数参数和返回值的序列化过程。且大部分的参数和返回值都可以使用内置的(反)序列化方法...
C#,不同类之间相互调用实例,包括子类调用父类函数,父类调用子类函数,子类调用子类函数。程序基于VS2010开发,可直接移植到其他版本应用
C#与JAVASCRIPT函数的相互调用 C#调用JAVASCRIPT函数的调用 JAVASCRIPT调用C#函数的调用
构造函数:不可以虚化(重写),在子类的构造函数前自动被调用一次父类的构造函数. 析构函数:当[DELETE]类指针时 非虚会从[此类]一直释放到基类,为虚时会从被赋于的[NEW类]的析构函数一直释放到基类. 总得来说释放[方向...
spring与java反射结合动态定义类及调用函数,实现类的动态定义和函数的动态调用。 为有动态调用的web应用提供一点点借鉴,相互学习。
C++虚函数调用的反汇编解析
这样,在有虚函数的类的实例中这个表被分配在了这个实例的内存中,所以,当我们用父类的指针来操作一个子类的时候,VFTable就显得尤为重要了,它就像一个地图一样,指明了实际所应该调用的函数。在C++的标准中提到,...
对象引用指针调用虚函数源程序实例,帮助初学者理解虚函数的用法
这样,在有虚函数的类的实例中这个表被分配在了 这个实例的内存中,所以,当我们用父类的指针来操作一个子类的时候,这张虚函数表就显得由为重要了,它就像一个地图一样,指明了实际所应该调用的函数。
大学基础c++代码,自习c++可用,虚函数的创建和调用