看《深入浅出MFC》时里面谈到虚函数表遇到的问题扩展

slqvstian 2009-08-26 12:49:57
这本书里谈到虚函数,于是我就想更深入了解一下虚函数,看到一篇文章,转载在我博客,网址http://hi.baidu.com/slqhappy/blog/item/996ee3465f4668006a63e56e.html
因为虚函数表在类的头部,所以可以通过获取一个类的实例的地址得到这张虚函数表的地址,而虚函数表里放的又是本实例对象的虚函数的地址。这里问一个问题,是否一个类的所有实例都有不同的虚函数表,但我看到有关文章说的是所有类的实例共享本类的虚函数表,那请问一个虚函数表如何能得到不同的虚函数地址?
还有就是指针的问题,部分源码如下:

#include <iostream>
using namespace std;

class Base
{
public:
virtual void f()
{
cout<<"Base::f"<<endl;
}
virtual void g()
{
cout<<"Base::g"<<endl;
}
virtual void h()
{
cout<<"Base::h"<<endl;
}
};

typedef void(*Fun)(void);

void main()
{

Base b;
Fun pFun = NULL;
cout<<"虚函数表地址"<<(int*)(&b)<<endl; //这里我明白是实例地址
cout<<""<<(int*)*(int*)(&b)<<endl;//这里的每一步是什么意思?

pFun = (Fun)((int*)*(int*)(&b));//这里的每一步是什么意思?
fFun();
}

另外,该代码可在VC2003中通过,但VC2005中不能将 int 转化为 int*错误
请DX赐教,两个问题:
现重复如下
1 是否一个类的所有实例都有不同的虚函数表,但我看到有关文章说的是所有类的实例共享本类的虚函数表,那请问一个虚函数表如何能得到不同的虚函数地址?
2 上面代码中指针转换的意思.
谢谢了 !
...全文
91 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
secretcf 2009-08-26
  • 打赏
  • 举报
回复
1. 虚函数表中的函数地址肯定是唯一的。
2.
cout < <"" < <(int*)*(int*)(&b) < <endl;//这里的每一步是什么意思?
取得虚函数表中第1个函数地址.
雪影 2009-08-26
  • 打赏
  • 举报
回复
1 是否一个类的所有实例都有不同的虚函数表,但我看到有关文章说的是所有类的实例共享本类的虚函数表,那请问一个虚函数表如何能得到不同的虚函数地址?
类的所有实都有一个不同的虚函数表指针.指向同一个虚函数表.
2 上面代码中指针转换的意思.
cout < <"" < <(int*)*(int*)(&b) < <endl;//这里的每一步是什么意思?
虚函数表的第一个虚函数地址.
pFun = (Fun)((int*)*(int*)(&b));//这里的每一步是什么意思?
将类的第一个虚函数指针赋给pFun
MoXiaoRab 2009-08-26
  • 打赏
  • 举报
回复
又来了
slqvstian 2009-08-26
  • 打赏
  • 举报
回复
还有在继承有虚函数类的情况下,若没有重写虚函数,虽然虚函数表里的函数地址都是指向基类的虚函数,但是两个类里的虚函数表地址应该不一样吧?
不好意思,问题太多了 ,呵呵...
请大家指教啊!
slqvstian 2009-08-26
  • 打赏
  • 举报
回复
既然是指向同一个虚函数表,那为何里面的虚函数地址会不同,难道里面的虚函数地址是动态填充的?
不需要,对于一个类,它的虚函数表是固定的,但是这个类有一个指针变量,指向虚函数表,需要在构造函数中填充.编辑器会生成响应的代码,不需要你去管理的
我考虑错了,应该是每一个类都共享虚函数表,但是基类与派生类的虚函数表地址就不一样了,对吧?
还有关于指针,这里(int*)*(int*)(&b)
第一步(int*)(&b)之后*(int*)(&b)这里如果把 (int*)改成(Base*)这个语句不就是b吗?,这里int*到底是何作用?是编译器遇到(int*)后就直接看成是int*指针,然后再取*(int*)后就得存储在这个指针里的4个字节的数值,而如果是(Base*)虽然指针也是4个字节,但得到的是sizeof(Base)个字节大小的值吗?可能是我理解的不够透彻,所以阐述不清,希望哪位能解释详细一点
雪影 2009-08-26
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 slqvstian 的回复:]
既然是指向同一个虚函数表,那为何里面的虚函数地址会不同,难道里面的虚函数地址是动态填充的?
不需要,对于一个类,它的虚函数表是固定的,但是这个类有一个指针变量,指向虚函数表,需要在构造函数中填充.编辑器会生成响应的代码,不需要你去管理的
还有(int*)*(int*)(&b) 是不是这个意思,
第一步  (int*)(&b)将对象首地址转化为int类指针
(int*)(&b)取得需函数表地址
第二步 *(int*)(&b)取得虚函数表里的第一个函数地址.
这步你说对了
第三步(int*)*(int*)(&b)再将取得的虚函数地址转为int类指针输出 ,是否是这样?



第二个(Fun)((int*)*(int*)(&b)); 是否是将上面的结果转为Fun类指针,再条用第一个虚函数,是否这样?
是,这里第一个虚函数的类型必须是Fun类型的,否则调用会失败
[/Quote]
secretcf 2009-08-26
  • 打赏
  • 举报
回复
对啦
slqvstian 2009-08-26
  • 打赏
  • 举报
回复
既然是指向同一个虚函数表,那为何里面的虚函数地址会不同,难道里面的虚函数地址是动态填充的?
还有(int*)*(int*)(&b) 是不是这个意思,
第一步 (int*)(&b)将对象首地址转化为int类指针 第二步 *(int*)(&b)取得虚函数表里的第一个函数地址.
第三步(int*)*(int*)(&b)再将取得的虚函数地址转为int类指针输出 ,是否是这样?


第二个(Fun)((int*)*(int*)(&b)); 是否是将上面的结果转为Fun类指针,再条用第一个虚函数,是否这样?
slqvstian 2009-08-26
  • 打赏
  • 举报
回复
弄错了,fFun改为pFun都可以执行

16,551

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Creator Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧