Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 虚拟函数表指针在对象中的位置_C++_Oop_Virtual Functions_Vptr - Fatal编程技术网

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。但是每个对象的开销不是很好。