搜索
当前位置: 秒秒彩平台 > 段表地址 >

C++虚函数表的问题!(看一段代码高分悬赏)

gecimao 发表于 2019-07-16 20:09 | 查看: | 回复:

  如有大侠肯给出合理的解释,小弟感激不尽!!!悬赏80分,回答满意再加20分!

  小弟对虚函数实现机制有基本的了解,知道虚函数表即vptr + vtable这些玩意!

  问题一:第二个注释行,可以这样(int*)*(int*)(&b),小弟感觉是对一个指针取地址再解引用。看下面代码

  (int*)*(int*)(&b)这个代码好像对b取地址再解引用,int*只不过是类型转换而已!!!岂不是和这段代码一样一下代码

  是可以输出一样的地址,而换成 *(void*)(&b)却报错了.大侠能否解释下这里面的规则在哪里!!!

  ((int*)*(int*)(&b))已经是第一个虚函数的地址,赋值给类型匹配的pFun变量很好 啊,可是为什么非要加(Fun)*才能编译通过 啊!!!

  可选中1个或多个下面的关键词,搜索相关资料。也可直接点“搜索资料”搜索整个问题。

  为了得到正确的虚函数偏移量,C++编译器要将虚函数表的指针存在于对象实例中最前面的位置。

  问题一:当然不一样,首先p本身是一指针类型,是一种简单类型,*&p:先得到p在物理内存中的地址,再取出该地址中的数据,这个数据依然是指针类型,例如:p的物理地址是0x10,而0x10所在位置存的是0x20,那么输出就是0x20,而0x20依然是个地址。p:过程是相同的,只是写起来比较简单。

  其次b是一对象类型,是非简单类型,插入符“”无法识别,除非你写一个重载该运算符的函数

  &b是取出对象的地址,(int*)(&b)是将该地址转换为整形指针,就是对象虚表数组的首地址,*(int*)(&b)是将取出虚表数组的第一项,就是第一个虚函数的首地址,(int*)*(int*)(&b)就是将该地址转换为整形指针。

  问题二:void*不是一个指向对象类型的指针(int*,long*都是),所以你向他取东西肯定是不行的,例如:void*p=NULL;

  问题三:你这个之所以可以是因为,你的函数碰巧没有参数,如果有的话,就不行了,编译器会说类似从void()()转换成void()(char*)失败。

  展开全部(int*)*(int*)(&b)应该是把b的地址转换成指针,然后用*或者指针指向的位置的值(即函数地址),最后通过(int*)转换为整数指针打印。

  void*有可能不是32位。vc6.0我很久不用了,我也不能确定在vc6.0里void是否等于int长度,不过看一下错误信息应该就知道是什么问题了。

  一个类创建的实例它的前4个字节(即一个指针的长度)就指向该函数的虚表,前提是该类有虚表。所以:

  (int*)(&b),是先将对象的地址取出,转换成int*,这样就转成了一个int的指针。然后再用*取这个地址上的值,因为指针是int类型,所以就取出了4个字节的值,再把这个值用(int*)转成一个int指针,这个指针就指向vtable了。这个vtable还是个指针,它的值才是第一个函数的地址,所以还要再用*取次值。

  void是个空类型,没有长度。而*是取地址上的值,必须要知道类型的长度,比如a是int*类型,那么*a编译器就知道从这个地址指向的位置上取4个字节。虽然void*变量本身有长度,但编译器无法知道其指向的地址有多长,所以用*取一个void*类型地址的值在编译时就会报错。

  void*指针一般配合强转用作转换成任何指针类型,不会也不能参与表达式运算。

  这么一个函数,函数名代表函数入口地址,加个&还是函数地址,在表达式中返回的是存有该函数入口地址的函数指针,这是编译器规定的。

  这个p就是一个返回值为void,参数列表为void的函数指针,而fun返回一个函数指针,跟p的类型匹配,所以不需要强转。

  因为操作系统调用一个函数除了函数地址外,还需要它的参数列表,所以你光一个地址是无法调用函数的。

  这个时候就要用到函数指针。函数指针除了可以存储函数地址外还能描述出函数的参数列表。

  所以你用int*取到的地址,需要强转成FUN类型的函数指针,这样编译器就知道这个函数的参数和返回值,就能调用函数了。

  然后“*(int *)(&b)”是指用*操作符间接引用这个地址,得到了虚函数表的首地址,也就是得到这么一个指针,这个指针指向了第一个虚函数的地址。

  这个比较简单,根据c++语法规则,指向void的指针比较特殊,是不能间接引用的。

  一个指向任何对象类型的指针都可以赋值给类型为void *的变量,void *可以显式转换到另一个类型,其他操作是不安全的,因为编译器不知道实际被指的的是哪种对象,要想使用void *,必须显式地将它转换成某个指向特定类型的指针。

  因为对一个函数无非就是两种操作,调用和取地址。所以可以省略从函数指针得到函数的间接运算符&,也可以省略取得函数地址的运算符&。

  Fun是一个函数指针类型, (Fun)作用是做类型转换, *是间接引用运算符。

  前面已经知道(int*)*(int*)(&b)是一个指针,这个指针指向了第一个虚函数的地址。

  那么*((int*)*(int*)(&b))就是得到了第一个虚函数的地址,但是还不能直接使用,因为这里编译器会把它当成一个int型的数,必须加上(Fun)类型转换后,才可以赋值给pFun,否则编译器是会提示类型不匹配的。

本文链接:http://latharnaog.com/duanbiaodizhi/651.html
随机为您推荐歌词

联系我们 | 关于我们 | 网友投稿 | 版权声明 | 广告服务 | 站点统计 | 网站地图

版权声明:本站资源均来自互联网,如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

Copyright @ 2012-2013 织梦猫 版权所有  Powered by Dedecms 5.7
渝ICP备10013703号  

回顶部