C++ 虚拟函数表指针在对象中的位置
据我所知,C++ 虚拟函数表指针在对象中的位置,c++,oop,virtual-functions,vptr,C++,Oop,Virtual Functions,Vptr,据我所知,虚拟函数指针表在对象中的位置取决于编译器。 将此指针放在对象的开始位置与放在对象的结束位置相比,有什么优点/缺点吗?是的,它完全依赖于实现。 对于简单的继承层次结构,它位于对象的开头,但对于复杂层次结构,它不会位于对象的开头。 无论如何,您编写的任何源代码都不应该依赖于它所在的位置,事实上,您编写的任何代码都不应该依赖于虚拟表或虚拟表指针的存在。 C++标准并没有规定通过虚拟表和指针实现虚拟调度,实现可以使用其他实现方法来实现。然而,所有主流编译器都是通过表指针机制实现这一点的。需要注
虚拟
函数指针表在对象中的位置取决于编译器。将此指针放在对象的开始位置与放在对象的结束位置相比,有什么优点/缺点吗?是的,它完全依赖于实现。
对于简单的继承层次结构,它位于对象的开头,但对于复杂层次结构,它不会位于对象的开头。
无论如何,您编写的任何源代码都不应该依赖于它所在的位置,事实上,您编写的任何代码都不应该依赖于虚拟表或虚拟表指针的存在。
C++标准并没有规定通过虚拟表和指针实现虚拟调度,实现可以使用其他实现方法来实现。然而,所有主流编译器都是通过表指针机制实现这一点的。需要注意的重要一点是,它们可能在指针所在位置的精确实现上有所不同。仅仅存在一个虚拟函数表是依赖于编译器的(但所有编译器都是如此),而且位置也不是强制要求的。。。在我知道详细信息的所有编译器中,vptr都存储在对象的开头。原因是它提供了一个统一的位置。考虑类层次结构:
struct base {
T data;
virtual void f();
};
struct derived : base {
T1 data;
virtual void g();
};
如果vptr存储在对象的末尾,那么对于完整类型的base
对象,它将位于sizeof(T)
字节之后。现在,当您有一个完整类型的派生的对象时,base
子对象的布局必须与完整base
对象的布局兼容,因此vptr
仍然必须是sizeof(T)
对象中的字节,这将是在<代码>派生的对象的中间某处(<代码> siZeof(t)< /代码>从开始,<代码> siZeof(t1)< /代码>结束之前)。因此,它将不再位于对象的末尾
此外,给定一个此
指针,虚拟调用需要通过vtable进行间接寻址,这基本上就是取消对vptr的引用,添加偏移量并跳转到存储在那里的内存位置。如果vptr
存储在对象的末尾,则在解除对vptr
的引用之前,每个虚拟调用都会有一个额外的this
理论上,您可以在基类子对象和完整对象的末尾都有vptr。这会有一定的意义:对于未出现在Base
中的虚拟函数,使用派生的
vptr。但是每个对象的开销不是很好。