社区
C++ 语言
帖子详情
请教大家关于虚表的问题
shadow0577
2008-06-20 04:03:21
如果一个类中有虚函数,那么编译器会在这个类的起始位置放入虚表的指针。 但我有个疑问,虚函数的入口地址是在编译时也放入虚表所指向的位置,还是在运行时放呢?
...全文
236
22
打赏
收藏
请教大家关于虚表的问题
如果一个类中有虚函数,那么编译器会在这个类的起始位置放入虚表的指针。 但我有个疑问,虚函数的入口地址是在编译时也放入虚表所指向的位置,还是在运行时放呢?
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
22 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
shadow0577
2008-06-24
打赏
举报
回复
非常感谢大家的解答,受益匪浅!
晨星
2008-06-23
打赏
举报
回复
[Quote=引用 12 楼 WuBill 的回复:]
运行时动态绑定是骗人的,好多人在这里迷迷糊糊,都是因为中国那些所谓的专家忽悠的!
说什么对于一系列的虚函数,在编译时还不确定调用哪个函数,运行时就知道了,这都是骗人
试想一下,编译器都不能确定将会调用那个函数,那么程序运行之后又如何能确定呢?
其实在函数重载或虚函数当中,编译器早就用按规则改名,或创建虚函数表等方式,清清楚楚地确定将要调用的函数.
[/Quote]
假如我根据用户输入来决定使用哪个子类,编译时如何能确切知道将被调用哪个函数?
编译器确实是不知道的,它只是生成了相关的代码和数据结构,这些代码和数据结构用来保证运行时可以知道。
机智的呆呆
2008-06-23
打赏
举报
回复
对象创建时,调用构造函数时编译器偷偷顺便初始化了 续表
WuBill
2008-06-23
打赏
举报
回复
9楼的讲得很清楚,我又啰嗦了一下
WuBill
2008-06-23
打赏
举报
回复
如果一个类中有被声明为virtual的函数,编译器就会为这个类生成一个虚函数表,也就是VTABLE。
VTABLE实际上是一个函数指针的数组,每个虚函数占用这个数组的一个slot。
一个类只有一个VTABLE,不管它有多少个实例,派生类有自己的VTABLE。
但派生类的VTABLE与基类的VTABLE有相同的函数排列顺序,同名的虚函数被放在两个数组的相同位置上。
在创建类实例的时候,编译器还会在每个实例的内存布局中增加一个vptr字段,该字段指向本类的VTABLE。
通过这些手段,编译器在看到一个虚函数调用的时候,就会将这个调用改写:
比如:
void bar(A * a)
{
a->foo();
}
会被改写为:
void bar(A * a)
{
(a->vptr[1])(); //方括号中值与你整个类A中虚数的排列顺序有关
}
因为派生类和基类的foo()函数具有相同的VTABLE索引,而他们的vptr又指向不同的VTABLE,因此通过这样的方法可以在运行时刻决定调用哪个foo()函数;
但所有的工作都是在编译时完成的,运行时只是根据所给对象所属的类确定到那个虚表里去。
可能大家对编译时和运行时的理解不同吧!呵呵
K行天下
2008-06-22
打赏
举报
回复
当一个类中有虚函数时,编译器会为该类产生一个虚函数表
你可以做一个例子程序, sizeof(class A) (不需要实例化)
A中含有虚函数, 和含有其它一般函数的结果,会发现:存在一个虚函数,size增大4
con_con
2008-06-22
打赏
举报
回复
编译时放进去的吧
fish6344
2008-06-22
打赏
举报
回复
事物本来就没有真假之分,只在于你对它的感受而已!
jieao111
2008-06-22
打赏
举报
回复
http://hi.baidu.com/_586/blog/item/c345aa000fd3c584e950cdc4.html
WuBill
2008-06-21
打赏
举报
回复
运行时动态绑定是骗人的,好多人在这里迷迷糊糊,都是因为中国那些所谓的专家忽悠的!
说什么对于一系列的虚函数,在编译时还不确定调用哪个函数,运行时就知道了,这都是骗人
试想一下,编译器都不能确定将会调用那个函数,那么程序运行之后又如何能确定呢?
其实在函数重载或虚函数当中,编译器早就用按规则改名,或创建虚函数表等方式,清清楚楚地确定将要调用的函数.
fish6344
2008-06-21
打赏
举报
回复
在上述虚函数表slot1中的索引值,对地某些编译器而言,索引值不是0或者是1,这也是有可能的,原因是slot1有可能包含指向类型信息(type_info,用于RTTI)的指针.
shadow0577
2008-06-21
打赏
举报
回复
太感谢了,一直被骗到今天,豁然开朗了。
pengfeiluck
2008-06-20
打赏
举报
回复
整个东东,inside c++ mode。讲的蛮清楚地。建议看下,书也不厚
fish6344
2008-06-20
打赏
举报
回复
虚函数的入口地址是在编译时也放入虚表所指向的位置,还是在运行时放呢?
答:C++类之内存布局,包括数据成员及成员函数之内存布局(具体的内存占位),都可以在编译期硧定,例如:
class A
{
long _a;
public:
virtual void f(){(){//A类f的行为....;}};
};
class B : public A
{
long _b;
public:
void f(){//B类f的行为....;}
};
上述类体糸中的_a、_b、A::f()及B::f()的内存布局都在编译期与以确定(当然是相对地址,实际物理地址要在加载器加载了.exe才能与以确定),这正是C++是静态语言的原因。
而且,虚函数表-这个对程序设计层面隐晦的数据结构及其内存布局(相对地址)也因此能在编译期与以确定.
综上所述,虚函数的地址,虚函数表及其指针vptr都在编译期就与以确定。
运行时,只是根据指针指向的对象类型,寻址到正确的虚函数表,例如:
A a;
B b;
void Test(A* _pa){ _pa->f();}
对于:
Test(&a);
其中的依据_pa将寻址到A的虚函数表vtable_A,编译器将对_pa->f()产生如下伪码:
(*_pa->vtable_a_vptr[0])(_pa);//_pa充当隐晦的this!
对于:
Test(&b);
其中的依据_pa将寻址到B的虚函数表vtable_B,编译器将对_pa->f()产生如下伪码:
(*_pa->vtable_b_vptr[0])(_pa);//_pa充当隐晦的this!
其中怪异的名字也非常可能,当然是mangling的结果(不同的编译器mangling出独特的名字)!注意,其间的差别仅在于_pa指向了不同的虚函数表,而这二个虚函表中的slot1中分别是A::f()和B::f()的地址!
瞧,这就是C++的运行时多态的细部.(请参考《深度探索C++对象模型》候捷译page152-page159)
晨星
2008-06-20
打赏
举报
回复
编译时生成了组织虚函数表的代码。
shadow0577
2008-06-20
打赏
举报
回复
非常感谢大家的热情解答
ysuliu
2008-06-20
打赏
举报
回复
编译的时候放入的。。
运行时的多态是通过查表选择不同的指针来实现的,而不是到时候再往表里放。
www_adintr_com
2008-06-20
打赏
举报
回复
多态是对象的多态不是类的,类的东西(包括虚函数表)都是在编译时候确定的。
动态语言另当别论。
xkyx_cn
2008-06-20
打赏
举报
回复
每个类的虚表在编译时就确定了,标准上说的是:final overrider
就是最终覆盖的虚函数
多态是通过基类指针指向不同的子类地址,获取其vptr(虚表指针)来得到vtbl(虚函数表)
通过虚表获得实际的虚函数地址,再通过此地址调用相应的函数
所以virtual只是一个编译时的概念,到运行时的时候都是通过指针的不同指向来操作的
[Quote=引用 3 楼 coverallwangp 的回复:]
引用 2 楼 xkyx_cn 的回复:
编译时就放好了…………
编译时放的函数地址还没有具体绑定到哪一个函数吧?
[/Quote]
coverallwangp
2008-06-20
打赏
举报
回复
[Quote=引用 2 楼 xkyx_cn 的回复:]
编译时就放好了…………
[/Quote]
编译时放的函数地址还没有具体绑定到哪一个函数吧?
加载更多回复(2)
Python训练营103期开班典礼直播回放
#《5天Python闯关训练营》学习计划#挑战周期:12月16日—12月20日直播安排:开班典礼:12...完成相应的软件安装及环境搭建学习服务:12.16-12.20日为本课正式服务周期期间遇到学习
问题
可社群
请教
,群内安排助教老师答疑
C++ 虚函数表解析
C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有...关于虚函数的使用方法,我在这
C++多态机制详解(多态实现原理,单继承和多继承时虚函数表,菱形继承时的虚函数表原理)
动态多态:用一个基类对象的引用或者指针去调用重写完成的虚函数,更具引用或指向的对象不同,出现不同的行为静态:是指在编译阶段实现动态:是指在程序运行阶段实现被virtual修饰的函数就是虚函数public:这里的func...
转载:陈皓:C++ 虚函数表解析
转载:陈皓:C++ 虚函数表解析
C++ 语言
64,685
社区成员
250,491
社区内容
发帖
与我相关
我的任务
C++ 语言
C++ 语言相关问题讨论,技术干货分享,前沿动态等
复制链接
扫一扫
分享
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++
技术论坛(原bbs)
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
请不要发布与C++技术无关的贴子
请不要发布与技术无关的招聘、广告的帖子
请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下
试试用AI创作助手写篇文章吧
+ 用AI写文章