【问题标题】:Number of Virtual tables and Virtual Pointers in a C++ ProgramC++ 程序中的虚拟表和虚拟指针的数量
【发布时间】:2012-02-14 11:09:31
【问题描述】:

假设我们有以下程序:

class A
{     public:
      virtual fun(){};
};
class B:public A
{     public:
     virtual fun(){};
};
int main()
{
     A a1;
     B b1;
 }

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

【问题讨论】:

    标签: c++ virtual vtable vptr


    【解决方案1】:

    它在很大程度上依赖于实现,但通常每个具有任何虚函数的类都会得到一个 vtable 对象(没有虚函数或基的类不需要它们),并且每个具有 vtable 的类的对象都有一个 vptr (指向类的 vtable)。

    如果您有多重继承和虚拟基类,事情会变得更加复杂——这可以通过多种方式实现。一些实现对每个附加基类使用一个附加 vtable(因此最终每个类每个基类都有一个 vtable),而其他实现使用一个包含额外信息的单个 vtable。这可能导致每个对象需要多个 vptr。

    B 中的virtual 关键字无关紧要——如果函数在基类中是虚拟的,那么无论如何它在派生类中都是虚拟的。

    【讨论】:

    • 现在,如果我像下面这样修改我的 pgm:我从派生类中删除了 virtual 关键字。现在将创建多少个 vtable?
    • @Pal - 没有区别,函数仍然是虚拟的。
    • @Bo Persson:函数是虚拟的,但是,是否还会为派生类创建一个 vtable?
    • @Pal - 在这种情况下,是否使用关键字并不重要,如果函数在基类中是虚拟的,那么它在派生类中也是虚拟的。由于它是两个不同的功能,因此也可能会有两个 vtable。当然,所有这些都是特定于实现的,如果编译器认为有用的话,它可以优化一些特殊情况。
    • @PalLoveCoding,每个派生类都会有一个 vtable,即使它没有创建或覆盖任何虚函数。 RTTI 取决于它。
    【解决方案2】:

    这个程序可以优化成和这个完全一样:

    int main(){}
    

    因此,“无”是一种可能性。

    【讨论】:

    • 不一定,您可以有 2 或 1000 个(不强制优化)。但是 +1 的想法:)
    • int main(){} 足以编写 C++ 程序。不需要任何其他代码行。 :)
    • 不那么有趣,更完全准确。谢谢你迂腐。 ;)
    【解决方案3】:

    基本上,2.一个用于class A,一个用于class B(vftables)和2个vfptrs,一个用于a1,一个用于b1

    但是,这不是标准强制要求,因此您也可以没有。 (通常实现使用 vftables,但不是强制的。

    注意@R。 Martinho Fernandes 开启优化后,您将不会创建任何对象,因此不会有 vfptrs

    【讨论】:

      【解决方案4】:

      请注意,这完全取决于实现。
      C++ 标准没有提到vptrvtable,虚拟机制作为编译器的实现细节被忽略了。所以实际上,编译器可以在不使用vptrvtable 的情况下实现它。然而,几乎所有已知的编译器都使用vptrvtable 来实现它。

      鉴于以上情况,回答您的问题:

      每个类都有自己的虚拟表。
      而每个对象都有自己的虚拟指针。

      【讨论】:

      • 感谢 Als 的回答,现在我有点困惑。请解释一下,如果我从 B 类(派生)中删除 virtual 关键字,那么将创建多少个 vtable?
      • @CodeCodeCode 如果您从类 B(派生) 中删除虚拟关键字,那么将创建多少个 vtable?答案仍然是相同的 2 基数和派生数。
      • @aloksave 我在某处读到,由于基类具有虚函数,因此它将具有 vptr,并且继承到派生类但指向派生类 vtable。你能帮忙吗?
      【解决方案5】:

      只有在基类中至少有 1 个虚函数时才会创建虚拟表,这将通过任何方式继承到派生类。即使你从派生类 B 中删除 virtual 关键字也没关系,因为你已经拥有A 中的一个虚拟 fun()。 因此,虚拟表的数量将是 2(作为每个类的基础),虚拟 ptr 的数量也将是 2,作为它的每个对象的基础。 VTABLE for A---v_ptr* ,A::fun()

      & VTABLE for B--- V_ptr*(继承自 A),B::fun()/* B 可以访问 A::fun 和 B 的 fun(),但是因为我们提到了 A:: fun() 作为虚拟 B 的虚拟表中充满了函数的最衍生版本,fun(),它只不过是 B::fun()。希望这能消除你的疑问

      【讨论】:

        【解决方案6】:

        将有 2 个vtables,一个用于A 类,一个用于B 类。并且将有3个vptrs,一个在a1中,两个在b1中(一个指向A类vtable,另一个指向B类vtable )。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-06-22
          • 1970-01-01
          • 2011-03-20
          • 2012-06-08
          • 1970-01-01
          • 2014-07-07
          • 2016-07-09
          • 2013-10-13
          相关资源
          最近更新 更多