据我所知,virtual
函数指针表在对象中的位置取决于编译器
是否有任何利弊将这个指针放在对象的开头和结尾处,反之亦然?
答案 0 :(得分:8)
虚拟函数表的存在依赖于编译器(但所有编译器都有),并且该位置也没有强制要求......在我知道细节的所有编译器中,vptr存储在宾语。原因是它提供了统一的位置。考虑一个类层次结构:
struct base {
T data;
virtual void f();
};
struct derived : base {
T1 data;
virtual void g();
};
如果vptr存储在对象的末尾,那么对于完整类型sizeof(T)
的对象,它将在base
个字节之后。现在,当您拥有完整类型derived
的对象时,base
子对象的布局必须与完整base
对象的布局兼容,因此vptr
会在对象内部仍然必须是sizeof(T)
个字节,它位于derived
对象中间的某个位置(sizeof(T)
从开头,sizeof(T1)
结束之前)。所以它不再是对象的 end 。
此外,给定this
指针,虚拟调用需要通过vtable的间接,这基本上是解除引用vptr
,添加偏移量并跳转到存储在那里的内存位置。如果vptr
存储在对象的末尾,则对于每个虚拟调用,在解除引用this
之前,会额外添加vptr
。
答案 1 :(得分:4)
是的,它完全取决于实施。
对于简单的继承层次结构,它位于对象的开头,但对于复杂的层次结构,它不是
无论如何,你编写的任何源代码都不应该依赖于它所在的位置,事实上你编写的任何代码都不应该依赖于虚拟表或虚拟表指针的存在。
C ++标准并未要求通过虚拟表和指针实现虚拟调度,实现可以使用其他实现方法自由实现它。但是所有主流编译器都通过表指针机制实现这一点,需要注意的重点是它们可能不同确切实现指针所在的位置等。