CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
IBM Rational 系统开发最佳实践工具包 WebSphere MQ 最佳实践 TOP 15
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  C/C++ >  C++ 语言

问两个有关虚指针和虚表的问题

楼主cattleknife(解牛刀)2006-03-03 20:16:32 在 C/C++ / C++ 语言 提问

1   由带virtual关键字的类实例化出来的对象,是不是每一个virtual关键字对应一个虚指针,还是一个对象有一个虚指针?假设有五个虚函数吧。  
  2   虚表是象static   一样一个类共有的,还是每实例化一个对象都会生成一张虚表呢。也就是虚表在内存中有几份拷贝,是存放在堆中还是栈中的? 问题点数:20、回复次数:4Top

1 楼sjjf(水晶剑锋)回复于 2006-03-04 00:34:03 得分 10

===========================================  
  1   由带virtual关键字的类实例化出来的对象,是不是每一个virtual关键字对应一个虚指针,还是一个对象有一个虚指针?假设有五个虚函数吧。  
  2   虚表是象static   一样一个类共有的,还是每实例化一个对象都会生成一张虚表呢。也就是虚表在内存中有几份拷贝,是存放在堆中还是栈中的?  
  ===========================================  
   
  1.每一个带有virtual关键字的类,包括他的子类,编译器都会为其建立一张虚函数表。  
  每一个类一张虚函数表,该类里的所有的虚函数都会放到这个虚函数表中。  
  这个虚函数表是放在内存中的某处,所有的该类的实例都共用它。至于它存放位置,肯定是在堆里,但在堆里面的具体那个位置,我也不太清楚,等我弄清楚了我在告诉你,  
  类的实例化过程实际上是先分配内存(可能在堆里也可能在栈里分配),  
  如果没有虚函数的类,它的实例的内存大小和他的成员一致,  
  如果有虚函数的话,编译器会编译时给类的内存区域加大  
  一个指针的内存空间(32位下4个字节),类中各个成员一次往后排,  
  如果有构造函数的话,就会调用构造函数进行初始化。  
  对于带虚函数的类,必须有构造函数,如果没有的话,编译器会自动产生一个默认的。  
  构造函数工作时会把该类虚函数表的地址填充入类实例起始地址(也就是那个指针空间)。  
  之后是调用构造函数进行初始化工作。  
   
  验证代码如下:  
   
  #include   "stdafx.h"  
   
  class   parentA  
  {  
  public   :  
  int   iA;  
  virtual   void   fa();  
  };  
   
  class   A:public   parentA  
  {  
  public   :  
   
  int   i1;  
  int   i2;  
   
  void   fa();  
   
  };  
   
  void   parentA::fa()  
  {  
  printf("\n   parentA   iA   =[%d]   \n",this->iA);  
  }  
   
  void   A::fa()  
  {  
  printf("\n   i1   =[%d],i2=[%d]   \n",this->i1,this->i2);  
  }  
   
  void   foo1()  
  {  
      A   a;  
      a.i1   =   1;  
      a.i2   =   2;  
      a.fa();  
  }  
   
  void   foo2()  
  {  
  A   a;  
  parentA   pa;  
   
  printf("A老爸的虚函数表的地址:[%d]   ",*((unsigned   int   *)(&pa)));  
  printf("A虚函数表的地址:[%d]   ",*((unsigned   int   *)(&a)));  
   
  int   t1[4]   ;  
  t1[1]   =   3;  
  t1[2]     =   4;  
  t1[3]     =   5;  
  ((A   *)&t1)->A::A();  
  ((parentA   *)&t1)->fa();  
   
  printf("模拟--   A的虚函数表的地址:[%d]",t1[0]);  
   
   
  ((parentA   *)&t1)->parentA::parentA();  
  ((parentA   *)&t1)->fa();  
   
   
  printf("模拟--   A老爸的虚函数表的地址:[%d]",t1[0]);  
   
  //获取虚函数表的地址还可以实例化一个有虚函数的类,然后将这个类的首地质拷贝出来。  
   
  }  
  int   main(int   argc,   char*   argv[])  
  {  
  foo1();  
  foo2();  
  return   0;  
  }  
   
  具体的分析见  
  http://community.csdn.net/Expert/topic/4532/4532843.xml?temp=.547619  
   
   
   
   
   
   
   
  Top

2 楼cunsh(村少)回复于 2006-03-04 01:00:21 得分 5

1  
  一个对象只要一个虚指针就行了.  
  2  
  一个类只要一个虚表就行了.Top

3 楼wzjall(风)回复于 2006-03-04 01:06:52 得分 5

这个有两种情况:  
  1.虚函数在你设计的类中占的比例比较大,且重写率不是很高时,象vc中的类.  
    vc采用的就是一个虚表.(vc中是通过设计一些巧妙的宏来访问基类的函数的)  
  这种方法节省内存,但效率不是很高,因为它需要通过指针往上一级级的查找  
   
  2.一1.相反,这种情况采用的是内存直接定位,效率高,但占内存(不过没关系,因为虚函数在你设计的类中占的比例比较小),这种编译器的实例给忘了.  
   
  这是我在一本杂志上看到的说法,理解不当之出,请间量Top

4 楼yxg80(林夕昱)回复于 2006-03-04 21:07:48 得分 0

以前不知道Vtable什么的,今天就好好学习了!Top

相关问题

  • 虚表指针
  • 有关链表指针的问题?
  • 有关指针
  • 高手请教,有关类的链表指针
  • 有关指向指针的指针
  • 有关指针的使用:
  • 有关定义指针
  • ……有关数组指针……
  • 有关指针的问题
  • 有关智能指针!

关键词

  • 指针
  • 内存
  • 函数
  • 编译器
  • 拷贝
  • virtual
  • parenta
  • 虚函数表
  • 表
  • 实例

得分解答快速导航

  • 帖主:cattleknife
  • sjjf
  • cunsh
  • wzjall

相关链接

  • C/C++ Blog
  • C/C++类图书
  • C/C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo