C++ 虚拟函数-vtable

C++ 虚拟函数-vtable,c++,C++,假设我有一个从类B和C继承的类A(多重继承)。 A级将有多少vtable成员? 单一继承是什么情况 此外,假设: Class A : Public B {} 以及: test从何处获取其vtable?什么是作业? 我假设它得到了A的vtable中B的一部分,但是A的构造函数是否也改变了它的父类(B)vtable?一般来说,子类将有一个vtable指针指向它从中继承的多个超类中的每一个(显然,假设这些类中的每一个都至少有一个虚函数) 我不太确定我理解了你的第二个问题。在构建一个对象时,一部分的构

假设我有一个从类B和C继承的类A(多重继承)。 A级将有多少vtable成员? 单一继承是什么情况

此外,假设:

Class A : Public B {}
以及:

test
从何处获取其vtable?什么是作业?
我假设它得到了
A
的vtable中
B
的一部分,但是
A
的构造函数是否也改变了它的父类(
B
)vtable?

一般来说,子类将有一个vtable指针指向它从中继承的多个超类中的每一个(显然,假设这些类中的每一个都至少有一个虚函数)


我不太确定我理解了你的第二个问题。在构建一个对象时,一部分的构建过程是设置相关的VTABLE指针,这是C++编译器通过继承层次结构的静态分析所做的事情。没有一个VTHLE改变,它们只是指向。

一般来说-您继承的每个虚拟函数至少需要一个vtable条目。如果没有虚拟函数,则没有vtable。

首先,vtable是特定于实现的。事实上,标准中没有任何地方规定vtable必须存在


无论如何,在大多数情况下,每个基类都会有一个虚拟函数的vtable指针。而且,正如Yuval所解释的,当构造一个对象时,没有人“填充”vtable;每个类都有一个虚拟函数的vtable,而对象只有指向其正确vtable的指针(或者在多重继承的情况下是vtable的指针)。在单个继承示例中,
test
将有一个指向
a
的vtable的指针,假设
a
至少有一个虚拟函数(从
B
继承或在
a
中新声明)

vPtr指向对象的正确vTable

vTable包含指向函数实现的地址列表

这里有一个例子

class Foo: public Bar, public Baz
{
  VTable* bar_vPtr;
  VTable* baz_vPtr;

  // Bar overrides/implementations
  void barOverride();

  // Baz overrides/implementations
  void bazOverride();
};

VTable:  
    &barOverride() // address of implementation

VTable:  
    &bazOverride() // address of implementation

创建对象时,将为数据成员而不是方法创建内存。这些方法将位于一个公共位置,所有对象都可以访问。这[每个类一个]适用于VTable,因为它仅包含类中每个虚拟函数的函数指针

正如Steven所提到的,编译器向基类添加了一个隐藏指针,该指针在创建类实例时设置,从而指向该类的虚拟表,该指针也由派生类继承


当派生类的对象被分配给基类指针时,基类中隐藏的指针将替换为派生类的vtable地址。

B*test,而不是*B test;-)Idan-我试图使您的问题更具可读性,如果我弄错了,请详细说明。您为什么想知道?你想实现什么?我想知道更多的两件事(关于单一继承):1。我想我不懂一些基本的东西。如果类A有它自己的vtable,而类B有它自己的vtable,这意味着当我创建一个新对象时,我必须初始化2个vtabel?2.如果是这样的话,测试的vtable如何变成A的vtable而不是B的vtable?好吧,除了在构建/销毁期间。在执行“新建B”时,如果首先使用A的vtable执行A::A。然后使用B的vtable执行B::B。编译器在发出对构造函数方法的调用之前完成所有vtable指针的修补。我说的是完全构造的对象,但你所说的值得记住。@Banbar:你不能说它是以这种方式发生的,因为它甚至可能不会发生。就像vtables一样,它们的构建方式取决于实现。正如戈皮克在他的回答中所指出的那样…@Martin。我特别回答最后一部分(“在大多数情况下”)。该标准确实指出,在构造期间,虚拟调用被分派到当前构造的类型(12.7.4:调用的函数是在构造函数或析构函数自己的类或其一个基中定义的函数,但不是在派生类中重写它的函数)
class Foo: public Bar, public Baz
{
  VTable* bar_vPtr;
  VTable* baz_vPtr;

  // Bar overrides/implementations
  void barOverride();

  // Baz overrides/implementations
  void bazOverride();
};

VTable:  
    &barOverride() // address of implementation

VTable:  
    &bazOverride() // address of implementation