现在的位置: 首页 > 综合 > 正文

多态类中的虚函数表是Compile-Time,还是Run-Time时建立的

2013年12月04日 ⁄ 综合 ⁄ 共 1858字 ⁄ 字号 评论关闭

这可是一道很经典的笔试面试考试问题,回答起来也是五花八门,各有各的说法。比如,看到过类似下面这段话的回答:

虚函数它虚就虚在所谓推迟联编或者动态联编上,一个类函数的调用并不是在编译时刻被确定的,而是在运行时刻被确定的。由于编写代码的时候并不能确定被调用的是基类的函数还是哪个派生类的函数,所以被成为函数。  

 

看起来有道理的一段话,问题很明显。

稍微说明:

虚函数,和虚函数表是两个东西,就算虚函数到底怎么调用时在Run-Time时确定,和虚函数表可没有什么关系。

 

再来看另外一个解释:

vtable的内容是在编译时确定好的,每个Class都有一个vtable相对应。  
         
在运行时,首先创建vtable的内存映象,然后,在创建对象时,将相应的vtable的地址写入对象的vptr。所以,这个问题本身就不是十分明确。比较严谨的应该这样说:vtable的内容是在编译时确定的,而内存中的vtable是在运行时创建的。
 
   
         
不过,这里有一个问题需要说明,编译时的vtable中并不一定是虚函数在运行时的真正地址,而很可能是一个offset,因为,代码和数据在运行时都会有一个重定向的过程,这个过程大部分情况是由操作系统进行的,这时运行期vtable的内容就是编译时的映象;而有些时候,程序会对自身进行重定向调整,这时内存中vtable的内容就是编译结果经过运算获得的值

 

     这个就不得了了,这里说明的不但是操作系统有可能让vtable变成在运行时建立,而且有可能因为不同的编译器,而让这个vtalbe出现Compile time确定,和Run-time确定两种状况。

 

 

 

(不知为什么,突然我就开始思考 这个问题到底是为什么被提出来呢?为了检验什么而存在呢?)

 

在<<Inside the C++ Object Model>>这本书中,我看到了标准

 

How might the table containing the virtual function addresses be constructed? In C++, the set of virtual functions capable of being invoked through an object of its class is known at compile time. Moreover, this set is invariant. It cannot be added to nor can a virtual instance be replaced at runtime. The table, therefore, serves only as a passive repository. Since neither its size nor its contents change during program execution, its construction and access can be completely handled by the compiler. No runtime intervention is necessary.

Having the address available at runtime, however, is only half the solution. The other half is finding the address.

 

就是这本经典书籍的经典内容决定了答案。

 

回答Compile-Time建立虚拟函数表,就对了!!!(看起来好像是一个二选一的猜测题目一样)。

 

重要的是,如果不能说明虚拟函数表指针是在运行期被初始化(实现多态的关键所在),那这道题目其实回答得没有任何意义。对我们理解C++多态的本质和必要性也没有帮助。

 

    其实我想说明是:现在的测试和招聘工作中,对于一些知识点的考验,是否真的让应聘人员知道了其与该工作岗位的差距,是否在工作岗位上会用到相关知识,是否对于完成其本职工作有帮助,还是需要出题者更好的进行考虑!

    对于以上言论,欢迎大家拍砖!

附注:

 

因为语言的多样性,不确定性,如果虚拟函数表指针在运行期才被初始化,虽然虚拟函数表是在编译期后其大小和内容就被确定,但是也不能说就被建立了啊!!所以这道题目就变成了捣糨糊。最好改成 虚拟函数表的大小和内容是什么时候确定的?(Compile-Time 或者Run- Time)

 

最后,顺带给出原题标准的答案:虚拟函数表是在编译期就建立了,各个虚拟函数这时被组织成了一个虚拟函数的入口地址的数组.而对象的隐藏成员--虚拟函数表指针是在运行期--也就是构造函数被调用时进行初始化的,这是实现多态的关键。

 

      

抱歉!评论已关闭.