标签: vptr

替代虚拟机制实现?

C++支持通过虚拟机制进行动态绑定.但据我所知,虚拟机制是编译器的实现细节,标准只是指定了在特定场景下应该发生的行为.大多数编译器通过虚拟表和虚拟指针实现虚拟机制.是的,我知道这是如何工作的,所以我的问题不是关于虚拟指针和表的实现细节.我的问题是:

  1. 是否有任何编译器以虚拟指针和虚拟表机制以外的任何其他方式实现虚拟机制?据我所见,最多(阅读g ++,Microsoft visual studio)通过虚拟表,指针机制实现它.那么实际上还有其他任何编译器实现吗?
  2. sizeof只有一个虚函数的任何类的将是一个指针(vptr的内部尺寸this)上编译,所以考虑到虚拟PTR和TBL机制本身是编译器实现,将这个说法我在上面做永远是真的吗?

c++ virtual-functions vtable vptr

48
推荐指数
4
解决办法
4837
查看次数

虚拟调度实施细节

首先,我想清楚地表明我确实理解在C++标准中没有vtable和vptrs的概念.但是我认为几乎所有实现都以几乎相同的方式实现虚拟调度机制(如果我错了,请纠正我,但这不是主要问题).另外,我相信我知道虚函数如何工作的,也就是说,我总能告诉我将调用哪个函数,我只需要实现细节.

假设有人问我以下内容:
"您的基类B具有虚函数v1,v2,v3和派生类D:B,它会覆盖函数v1和v3并添加虚函数v4.解释虚拟调度的工作原理".

我会这样回答:
对于每个具有虚函数的类(在本例中为B和D),我们有一个单独的指向函数的数组,称为vtable.
B的vtable将包含

&B::v1
&B::v2
&B::v3
Run Code Online (Sandbox Code Playgroud)

D的vtable将包含

&D::v1
&B::v2
&D::v3
&D::v4 
Run Code Online (Sandbox Code Playgroud)

现在B类包含一个成员指针vptr.D自然地继承它,因此也包含它.在BB的构造函数和析构函数中设置vptr指向B的vtable.在DD的构​​造函数和析构函数中,它指向D的vtable.
对多态类X的对象x上的虚函数f的任何调用都被解释为对x.vptr的调用[f在vtables中的位置]

问题是:
1.我在上述描述中有任何错误吗?
2.编译器如何知道f在vtable中的位置(请详细说明)
3.这是否意味着如果一个类有两个基数那么它有两个vpt?在这种情况下发生了什么?(尝试以与我相似的方式描述,尽可能详细地描述)
4.钻石层次结构中发生了什么,其中A位于顶部B,C位于中间,D位于底部?(A是B和C的虚拟基类)

提前致谢.

c++ vtable vptr

31
推荐指数
2
解决办法
7495
查看次数

在多重继承中理解vptr?

我试图理解书中有效的c ++语句.以下是多继承的继承图.

在此输入图像描述

在此输入图像描述

现在这本书说vptr需要每个类中的单独内存.它也做了以下声明

上图中的一个奇怪之处在于,即使涉及四个类,也只有三个vptrs.如果愿意,实现可以自由地生成四个vpt,但是三个就足够了(事实证明B和D可以共享一个vptr),并且大多数实现利用这个机会来减少编译器生成的开销.

我看不出有什么理由为什么每个类都要求为vptr提供单独的内存.我理解vptr是从基类继承的,可能是继承类型.如果我们假设它显示了带有继承的vptr的结果内存结构,那么它们如何才能生成该语句

B和D可以共享vptr

有人可以在多重继承中澄清一下vptr吗?

  • 我们每个班级都需要单独的vptr吗?
  • 如果以上是真的,为什么B和D可以共享vptr?

c++ multiple-inheritance virtual-inheritance vtable vptr

17
推荐指数
2
解决办法
5631
查看次数

C++/compilation:是否可以设置vptr的大小(全局vtable + 2字节索引)

我最近发布了一个关于由于C++中的虚拟性导致的内存开销的问题.答案让我了解vtable和vptr的工作原理.我的问题如下:我在超级计算机上工作,我有数十亿个对象,因此我不得不关心由于虚拟性造成的内存开销.经过一些测量,当我使用具有虚函数的类时,每个派生对象都有其8字节的vptr.这根本不可忽视.

我想知道intel icpc或g ++是否有一些配置/选项/参数,使用"全局"vtable和可调精度的索引而不是vptr.因为这样的事情将允许我使用2字节索引(unsigned short int)而不是8字节vptr用于数十亿个对象(并且很好地减少了内存开销).有没有办法用编译选项做到这一点(或类似的东西)?

非常感谢你.

c++ compilation g++ intel vptr

17
推荐指数
1
解决办法
562
查看次数

在构造函数中调用虚方法:Java和C++之间的区别

在Java中:

class Base {
    public Base() { System.out.println("Base::Base()"); virt(); }
    void virt()   { System.out.println("Base::virt()"); }
}

class Derived extends Base {
    public Derived() { System.out.println("Derived::Derived()"); virt(); }
    void virt()      { System.out.println("Derived::virt()"); }
}

public class Main {
    public static void main(String[] args) {
        new Derived();
    }
}
Run Code Online (Sandbox Code Playgroud)

这将输出

Base::Base()
Derived::virt()
Derived::Derived()
Derived::virt()
Run Code Online (Sandbox Code Playgroud)

但是,在C++中,结果是不同的:

Base::Base()
Base::virt() // ? Not Derived::virt()
Derived::Derived()
Derived::virt()
Run Code Online (Sandbox Code Playgroud)

(有关C++代码,请参阅http://www.parashift.com/c++-faq-lite/calling-virtuals-from-ctors.html)

什么导致Java和C++之间的这种差异?这是vtable初始化的时间吗?

编辑:我确实理解Java和C++机制.我想知道的是这个设计决定背后的见解.

c++ java virtual-functions object-lifetime vptr

15
推荐指数
3
解决办法
4787
查看次数

为什么vptr不是静态的?

包含一个或多个虚函数的每个类都有一个与之关联的Vtable.一个名为vptr的void指针指向该vtable.该类的每个对象都包含指向同一Vtable的vptr.那为什么vptr不是静态的呢?而不是将vptr与对象相关联,为什么不将它与类关联?

在此输入图像描述

c++ virtual function vtable vptr

13
推荐指数
2
解决办法
2682
查看次数

用于多个虚拟继承和类型转换的虚拟表和虚拟指针

我对vptr和内存中对象的表示感到困惑,希望你能帮助我更好地理解这个问题.

  1. 考虑B从中继承A并定义虚函数f().从我了解到的记忆B类对象的表示是这样的:[ vptr | A | B ]vtblvptr指向包含B::f().我也明白,从铸造对象BA什么都不做,除了忽略B在对象的端部.这是真的吗?这种行为不对吗?我们希望类型的对象A执行A::f()方法而不是B::f().

  2. 是否有一些vtables在系统中的类的数量?

  3. 一个将如何vtable类,由两个或多个类继承的是什么样子?如何将C的对象表示在内存中?

  4. 与问题3相同,但具有虚拟继承.

c++ multiple-inheritance virtual-inheritance vtable vptr

10
推荐指数
1
解决办法
1万
查看次数

vptr在销毁期间是否会发生变化?

我正在看这篇文章,它说"在进入基类析构函数后,该对象成为基类对象,而C++的所有部分 - 虚函数,dynamic_casts等 - 以这种方式对待它." 这是否意味着vptr在破坏期间发生了变化?这是怎么发生的?

c++ destruction vptr

9
推荐指数
2
解决办法
1750
查看次数

C++程序中的虚拟表和虚拟指针的数量

假设我们有以下程序:

class A
{     public:
      virtual fun(){};
};
class B:public A
{     public:
     virtual fun(){};
};
int main()
{
     A a1;
     B b1;
 }
Run Code Online (Sandbox Code Playgroud)

我的问题是,当我们运行这个程序时,会创建多少vtables和多少vptrs

c++ virtual vtable vptr

9
推荐指数
4
解决办法
9964
查看次数

vtable:底层算法

我对vtable的理解是,如果我有一个带有虚函数的Cat,带有子类Lion和HouseCat的函数,那么有一个vtable,它将speak()映射到每个子类的正确实现.所以一个电话

cat.speak()
Run Code Online (Sandbox Code Playgroud)

编译成

cat.vtable[0]()
Run Code Online (Sandbox Code Playgroud)

也就是说,在vtable位置0中查找并在该位置调用函数指针.

我的问题是:多重继承会发生什么?

让我们添加一个Pet类.Pet有虚函数speak()和eat().HouseCat扩展了Pet,而Lion则没有.现在,我需要确保这一点

pet.eat()
Run Code Online (Sandbox Code Playgroud)

编译为

pet.vtable[1]()
Run Code Online (Sandbox Code Playgroud)

那就是vtable [0]需要说话().Pet.eat需要是插槽1.这是因为cat.speak()需要访问vtable中的插槽0,如果对于HouseCat,插槽0恰好吃了,这将是非常错误的.

编译器如何确保vtable索引适合在一起?

c++ compiler-construction multiple-inheritance vtable vptr

8
推荐指数
1
解决办法
213
查看次数