CSDN-CSDN社区-C/C++-C++ 语言

收藏 请问虚函数表放在哪里?[问题点数:20,结帖人:foreverfresh]

楼主发表于:2007-01-18 13:19:14
test1:    
base.h:    
 
class     base_c    
...{    
public:    
              virtual     ~base_c()     ...{}    
              virtual     int     getkind()     ...{return     0;}    
};    
 
class     derive:     public     base_c    
...{    
public:    
              virtual     int     getkind()     ...{return     1;}    
};    
 
  derived1.cpp:    
 
#include     "base.h "    
 
int     f1()    
...{    
              derive*     pD1=new     derive();    
              base_c*     pB=new     base_c();    
              int     nRet=pD1-> getkind()+pB-> getkind();    
              delete     pD1;    
              delete     pB;    
 
              return     nRet;    
}    
 
derived2.cpp:    
 
#include     "base.h "    
 
int     f2()    
...{    
derive*     pD2=new     derive();    
base_c*     pB=new     base_c();    
int     nRet=pD2-> getkind()+pB-> getkind();    
delete     pD2;    
delete     pB;    
 
return     nRet;    
}    
 
>     nm     derive1.o    
 
00000000     W     _._6base_c    
00000000     W     _._6derive    
00000000     W     __6base_c    
00000000     W     __6derive    
00000000     ?     __EXCEPTION_TABLE__    
00000000     ?     __FRAME_BEGIN__    
                                  U     __builtin_delete    
                                  U     __builtin_new    
                                  U     __rethrow    
                                  U     __rtti_si    
                                  U     __rtti_user    
00000000     W     __tf6base_c    
00000000     W     __tf6derive    
00000008     C     __ti6base_c    
0000000c     C     __ti6derive    
00000000     V     __vt_6base_c    
00000000     V     __vt_6derive    
00000000     T     f1__Fv    
00000000     t     gcc2_compiled.    
00000000     W     getkind__6base_c    
00000000     W     getkind__6derive    
 
 
>     nm     derive2.o    
 
00000000     W     _._6base_c    
00000000     W     _._6derive    
00000000     W     __6base_c    
00000000     W     __6derive    
00000000     ?     __EXCEPTION_TABLE__    
00000000     ?     __FRAME_BEGIN__    
                                  U     __builtin_delete    
                                  U     __builtin_new    
                                  U     __rethrow    
                                  U     __rtti_si    
                                  U     __rtti_user    
00000000     W     __tf6base_c    
00000000     W     __tf6derive    
00000008     C     __ti6base_c    
0000000c     C     __ti6derive    
00000000     V     __vt_6base_c    
00000000     V     __vt_6derive    
00000000     T     f2__Fv    
00000000     t     gcc2_compiled.    
00000000     W     getkind__6base_c    
00000000     W     getkind__6derive    
 
test2    
base.h:    
 
class     base_c    
...{    
public:    
              virtual     ~base_c()     ...{}    
              virtual     int     getkind();    
};    
 
class     derive:     public     base_c    
...{    
public:    
              virtual     int     getkind();    
};    
 
base.cpp:    
 
#include     "base.h "    
 
int     base_c::getkind()    
...{    
              return     0;    
}    
 
int     derive::getkind()    
...{    
              return     1;    
}    
 
>     nm     base.o    
00000000     W     _._6base_c    
00000000     W     _._6derive    
00000000     ?     __FRAME_BEGIN__    
                                  U     __builtin_delete    
                                  U     __rtti_si    
                                  U     __rtti_user    
00000000     W     __tf6base_c    
00000000     W     __tf6derive    
00000008     C     __ti6base_c    
0000000c     C     __ti6derive    
00000000     V     __vt_6base_c    
00000000     V     __vt_6derive    
00000000     t     gcc2_compiled.    
00000000     T     getkind__6base_c    
00000010     T     getkind__6derive    
 
 
>     nm     derive1.o    
 
00000000     W     __6base_c    
00000000     W     __6derive    
00000000     ?     __EXCEPTION_TABLE__    
00000000     ?     __FRAME_BEGIN__    
                                  U     __builtin_delete    
                                  U     __builtin_new    
                                  U     __rethrow    
                                  U     __vt_6base_c    
                                  U     __vt_6derive    
00000000     T     f1__Fv    
00000000     t     gcc2_compiled.    
 
 
  >     nm     derive2.o    
 
00000000     W     __6base_c    
00000000     W     __6derive    
00000000     ?     __EXCEPTION_TABLE__    
00000000     ?     __FRAME_BEGIN__    
                                  U     __builtin_delete    
                                  U     __builtin_new    
                                  U     __rethrow    
                                  U     __vt_6base_c    
                                  U     __vt_6derive    
00000000     T     f2__Fv    
00000000     t     gcc2_compiled.    
--------------------------------------------------------------------------------------------------------------------------------    
 
q1:     vitual     function     会被拒绝     inline化,那么它的定义在哪里?    
 
q2:     complier一般将vtbl放在第一个没有inline的vitual     function的定义得编译单元内,如所有的virtual     function都inline了,vtbl放在哪里?    
 
q3:     哪位高手能帮我解读nm的symbol信息阿?__6base_c,     __vt_6base_c,     __tf6base_c,     __ti6base_c,     _._6base_c     都各代表什么呀?    

第一个问题我想答案应该是虚函数和一般函数一样被拒绝inline后会在每个编译单元内插入一份实现?    
回复次数:30
  • 060用户头像
  • 060
  • (060)
  • 等 级:
#1楼 得分:0回复于:2007-01-18 13:21:59
虚函数表一般是类的第一个成员。
  • fxc123用户头像
  • fxc123
  • (大葱)
  • 等 级:
#2楼 得分:0回复于:2007-01-18 13:24:02
作为类的静态成员的第一个变量
#3楼 得分:0回复于:2007-01-18 13:26:11
虚表由编译器确定放在那里。
  • taodm用户头像
  • taodm
  • (taodm(不能处理站内信))
  • 等 级:
  • 5

    3

#4楼 得分:0回复于:2007-01-18 13:35:30
看《深度探索C++对象模型》
  • v2002750用户头像
  • v2002750
  • (长安古道马迟迟)
  • 等 级:
#5楼 得分:0回复于:2007-01-18 13:59:47
Base*   pb   =   new   Base();

int*   addr   =   reinterpret_cast <int*> (pb);

int*   vptr   =   reinterpret_cast <int*> (*pb);//debug下看看,这就是须表指针
#6楼 得分:0回复于:2007-01-18 18:15:47
根据不同的编译器位置不同,c++标准没有制定。
  • houdy用户头像
  • houdy
  • (致力于图像/图形领域,成为有思)
  • 等 级:
#7楼 得分:0回复于:2007-01-18 21:05:33
据我在Windows平台下对汇编代码的分析,虚表应该位于 "常量段 ".
我在我的BLOG中写了几篇关于虚函数调用的文章:
1.   http://blog.csdn.net/houdy/archive/2006/10/15/1335209.aspx
2.   http://blog.csdn.net/houdy/archive/2006/11/04/1366007.aspx
#8楼 得分:0回复于:2007-01-18 21:19:52
C中加入汇编不懂,
  • femalelover用户头像
  • femalelover
  • (睡自己的觉, 让编译器去想办法)
  • 等 级:
#9楼 得分:0回复于:2007-01-18 21:32:50
等答案了.
  • OOPhaisky用户头像
  • OOPhaisky
  • (异化$渴望成功~~)
  • 等 级:
#10楼 得分:0回复于:2007-01-18 22:10:54
虚函数表放的位置由具体的实现决定,只有一点是确定的,那就是vtable只能有一份,而不能有多份。
#11楼 得分:0回复于:2007-01-18 22:23:29
由编译器的实现决定的
推荐楼住看看《深度探索C++对象模型》
  • EvilLin用户头像
  • EvilLin
  • (神仙哥哥)
  • 等 级:
#12楼 得分:0回复于:2007-01-18 23:25:17
《深度探索C++对象模型》楼上很多人推荐了.我就路过下.
  • DragonBill用户头像
  • DragonBill
  • (正旦辟恶酒,新年长命杯。柏叶随)
  • 等 级:
#13楼 得分:0回复于:2007-01-19 08:13:39
c++布局时由编译器决定
#14楼 得分:0回复于:2007-01-19 11:02:09
060(060)   (   )   信誉:100         Blog     2007-1-18   13:22:00     得分:   0    
     
虚函数表一般是类的第一个成员。
-------------------------------
第一个成员是指向它的指针,就这个case而言它实现方式由编译器决定没错,我的问题是通过上门的符号表信息如何看出符号表最终插在哪个目标文件下?我的complier:gcc,   g++   -   GNU   project   C   and   C++   Compiler   (gcc-2.96)


   
 
#15楼 得分:0回复于:2007-01-19 11:15:15
OOPhaisky(异化$渴望成功~~)   (   )   信誉:100         Blog     2007-01-18   22:10:54     得分:   0    
 
      虚函数表放的位置由具体的实现决定,只有一点是确定的,那就是vtable只能有一份,而不能有多份。
--------------------------------------------
我猜符号表里__vt_6base_c这个应该是虚函数表,所以test2的结果很明显
00000000     V     __vt_6base_c     in   base.o
U     __vt_6base_c     in   derived1.o
U     __vt_6base_c     in   derived2.o
说明在derived*.o中虚函数表无定义,但为什么在base.o中是weak   symbol?   按我的原来的理解难道它不是在base.o中吗?
为什么在test1种两个derived*.o中都是V?


#16楼 得分:0回复于:2007-01-19 11:16:51
houdy(致力于图像/图形领域,成为有思想的程序员)   (   )   信誉:96         Blog     2007-01-18   21:05:33     得分:   0    

      据我在Windows平台下对汇编代码的分析,虚表应该位于 "常量段 ".
我在我的BLOG中写了几篇关于虚函数调用的文章:
1.   http://blog.csdn.net/houdy/archive/2006/10/15/1335209.aspx
2.   http://blog.csdn.net/houdy/archive/2006/11/04/1366007.aspx
------------------------------------------------------------------
常量段和weak   symbol有什么关系吗?

   
 
#18楼 得分:0回复于:2007-01-22 14:57:05
《深度探索C++对象模型》里好像没讲没有这个问题的答案阿
#19楼 得分:0回复于:2007-01-24 10:47:42
mark   。。。。
#20楼 得分:0回复于:2007-01-24 21:36:54
mark
#21楼 得分:0回复于:2007-01-25 09:56:43
OOPhaisky(异化$渴望成功~~)   (   )   信誉:100         Blog     2007-1-18   22:10:55     得分:   0    
 
虚函数表放的位置由具体的实现决定,只有一点是确定的,那就是vtable只能有一份,而不能有多份。
---------------------------------------------------------------

按照《大规模c++程序设计》9.3.3的说法,cfront和很多编译器的做法是未能inline
的virtual   function和虚函数表可以有多份,在每个编译单元里有一份。
这样的话,类中的虚函表指针指向哪个呢?

   
 
  • taodm用户头像
  • taodm
  • (taodm(不能处理站内信))
  • 等 级:
  • 5

    3

#22楼 得分:10回复于:2007-01-25 10:15:51
指向代码所在的编译单元的那个。
#23楼 得分:10回复于:2007-01-25 10:18:25
周意楼上。
但连接器最终应该有能力消除重复。
  • femalelover用户头像
  • femalelover
  • (睡自己的觉, 让编译器去想办法)
  • 等 级:
#24楼 得分:0回复于:2007-01-25 16:52:00
感觉只要steedhorse和taodm出马,   几乎没有解决不了的C++问题
#25楼 得分:0回复于:2007-01-26 09:45:56
我想早期的编译器是先生成虚函数表,连接的时候消除重复或不消除都可以。
看到那些符号都是weak   symbol,我猜是不是为了避免连接时消除重复,现在编译器在编译的时候先不生成虚函数表和其他要消除重复的符号,在连接的时候再生成。但最终连接好的可执行文件中仍然是   weak   symbol,不知道怎么解释这个。
我用的是gcc,   g++   -   GNU   project   C   and   C++   Compiler   (gcc-2.96)
#26楼 得分:0回复于:2007-02-08 19:07:12
有谁能解释一下符号表中的符号吗   ?
  • htqx用户头像
  • htqx
  • (航天奇侠)
  • 等 级:
#27楼 得分:0回复于:2007-02-09 01:12:55
知道又如何,   我看了那个什么《深度探索C++对象模型》,   不感觉有啥用.
俺觉得这些应该给实现编译器的人忙,   和我们这些老百姓没关系.
  • houdy用户头像
  • houdy
  • (致力于图像/图形领域,成为有思)
  • 等 级:
#28楼 得分:0回复于:2007-02-09 08:30:34
我在我的博客中写了一篇关于这个问题的文章:
http://blog.csdn.net/houdy/archive/2007/01/28/1496161.aspx
#29楼 得分:0回复于:2007-02-16 16:14:18
我在我的博客中写了一篇关于这个问题的文章:
http://blog.csdn.net/houdy/archive/2007/01/28/1496161.aspx
------------------------------------

我看过你的blog了,你讨论的问题是一般情况,我的case是虚函数都是inline的,即没有类定义模块。
  • lin_style用户头像
  • lin_style
  • (JAVA卧底、二分流掌门人)
  • 等 级:
#30楼 得分:0回复于:2007-02-16 21:11:20
现在看汇编来了解C++底层不赞成~
#31楼 得分:0回复于:2008-02-16 12:30:38
我记得C++标准规定了虚函数表应该放在类的存储单元的头里啊,似乎是为了保证正确计算偏移量?
相关问题
关于虚函数表C/C++ / C++ 语言- CSDN社区community.csdn.net
一个类中虚函数表与继承的问题
虚函数表C/C++ / C++ 语言- CSDN社区community.csdn.net
请问类能在共享内存中实例化吗?(如果类中有函数!)请大家探讨一下C ...
虚函数到底有什么特别之处呢? C/C++ / C++ 语言- CSDN社区community ...
一个含有虚函数的类其定义的对象所拥有的vptr的地址是不是都是一个地址 ...