在这个例子中会创建多少个vtable和vpointer?

8
这里是关于虚函数表的程序。我的理解是关于虚函数表和虚函数指针的。
Class B
{
  public:

  virtual Void Hello()
  {
    cout<<"Hello Base";
  }
};

class D: public B    
{
  public:

  virtual void Hello()
  {
    cout<<"Hello Derived";
  }
};

int main(int argc, char* argv[])
{
  D *d1 = new D();
  D *d2 = new D();
  D *d3 = new D();

  return 0;
}

在我看来,将会有两个vtable和一个vptr。我的看法正确吗?


你是否打算让 D 继承自 B? - 2785528
哎呀,谢谢!是继承。 - dexterous
1
这个问题太过局限,没有人会从它的答案中受益。只需阅读与你使用的编译器和ABI相对应的规范,它将定义答案。 - Puppy
2
不使用虚函数表的实现,或在整个程序优化过程中消除虚函数表的实现将不会创建任何虚函数表和虚函数指针。 - n. m.
3个回答

16

这个标准并没有定义虚函数的实际实现方式,只定义了它们应该如何行为。所以你所问的完全取决于你正在使用的编译器。


GCC理论上最可能创建两个vtable(一个用于B,另一个用于D),以及三个vptr(分别用于对象实例d1d2d3)。

请参阅此处:http://en.wikipedia.org/wiki/Virtual_method_table


它在gcc上会如何表现? - dexterous
虽然这是真的,但它也完全没有帮助,无法准确回答他的问题。并不是因为你的错,因为他的问题是无法回答的,但这是另一回事。 - Puppy
@DeadMG:为什么这没什么帮助?我对一般情况做了陈述,并给出了一些特定情况的提示。 - Danvil
使用gcc编译它,亲自验证一下。 - n. m.
关于一般情况的陈述是:“在一般情况下,你的问题无法回答(但这仍然是一般情况下的答案)”,这已经是我们知道的了,而他的问题没有指明具体情况。 - Puppy
1
@DeadMG:它确定了“使用vtables和vptrs实现”的特定情况,这已足以回答问题,除了最苛刻的学究之外。 - Mike Seymour

8
您可以在编译器文档中找到实现细节。这些细节可能会因版本和平台的不同而有所变化。
对于Linux上的gcc,每个D实例都需要其vptr和一个vtable。
您有3个D实例:
- 每个实例都有其vptr -> 3个vptr - 每个实例指向相同的vtable。
所以共需3个vptr和1个vtable(对于B来说,这里是无用的)。
再次强调,这是一个实现细节,在您非常简单的情况下,它受到编译器优化的影响。

为什么要点踩?有什么问题吗? - quantdev
你通过回答一些特定的子问题来回答一个无法回答的问题。这并不能回答这个问题。 - Puppy
5
我不同意,原帖明确指定了gcc,而且gcc的实现已经有文档记录。从文化角度来看,回答这个问题是有帮助的,即使你只限制在特定的子情况下。无论如何,感谢您的回复。 - quantdev

5
在基于虚拟多态性的典型vtable实现中,会有以下内容:
  • 每个类都有一个vtable,包含该类的虚函数指针和其他元数据;
  • 每个对象都有一个vptr,指向该对象动态类类型的vtable。
因此,在这里会有两个vtable(对于B和D)和三个vptr(在*d1、*d2和*d3中)。除非编译器注意到您没有使用对象并完全消除它们。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接