11

这是一种家庭作业问题。对于以下代码,

#include <iostream>
using namespace std;

class A
{
public:
    virtual void f(){}
};

class B
{
public:
    virtual void f2(){}
};

class C: public A, public B
{
public: 
    virtual void f3(){}
};

class D: public C
{
public:
    virtual void f4(){}
};

int main()
{
    cout<<sizeof(D)<<endl;
}

输出为:8

谁能解释一下它是8个字节吗?如果 vtable 实现依赖于编译器,我应该在面试中回答这种问题?那么虚拟基类呢?

编辑:我正在一个 32 位平台上工作。

4

4 回答 4

16

这当然取决于实现。这会是一个糟糕的面试问题。一个好的 C++ 程序员可以相信sizeof自己是对的,让编译器担心那些 vtable 的事情。

但是这里发生的情况是,典型的基于 vtable 的实现需要在 classCD. 每个基类都需要自己的 vtable。Cand新增的虚方法D可以通过从一个基类扩展 vtable 格式来处理,但是Aand使用的 vtableB不能合并。

在伪 C 代码中,这是 D 类型的最派生对象在我的实现中的外观(g++ 4.4.5 Linux x86):

void* D_vtable_part1[] = { (void*) 0, &D_typeinfo, &A::f1, &C::f3, &D::f4 };
void* D_vtable_part2[] = { (void*) -4, &D_typeinfo, &B::f2 };

struct D {
  void** vtable_A;
  void** vtable_B;
};

D d = { D_vtable_part1 + 1, D_vtable_part2 + 1 };
于 2011-01-22T05:40:51.200 回答
4

在这个问题中,如果您尝试获取 Sizeof 类 A,它会给您答案“4”,因为 A 只有一个虚函数,所以它的 __vptr 将是“4”字节。

同样,如果您尝试获取 Sizeof 类 B,它会给您答案“4”,因为 B 也只有一个虚函数,因此它的 __vptr 将是“4”字节。

但是类 C 继承了类 A 和 B 并且 C 本身具有虚函数。所以 C 将接收 2 个 __vptr 指针,并且对于它自己的虚函数 C 将使用继承的 __vptr。因此,如果您尝试获取 Sizeof 类 C,它会给您答案“8”,因为 C 有两个虚拟指针。

最后,D 类继承了 C 类,因此 D 将使用继承的 __vptr 作为自己的虚函数,并且因为 C 类具有 sizeof '8' 字节,所以 sizeof D 会给你答案 '8' 字节。

于 2012-08-31T08:28:10.477 回答
1

请原谅我含糊不清,但您提到它本质上是家庭作业。

查看 sizeof() 为其他类返回什么。您的答案会因您的编译器以及您是在 32 位还是 64 位环境中而有所不同。

快乐的侦查!

于 2011-01-22T05:26:45.290 回答
-2

对象的大小与它有多少方法无关,也与这些方法是否是虚拟的无关。对象的大小由其成员变量决定。

我不能确切地告诉你为什么你会得到 8 个字节的大小。由于您的类中没有数据成员,因此 C++ 编译器原则上可以生成一个完全不占用空间的类 [1]!我猜测 8 个字节是提供指向 vtbl 的指针所需的最小值,可能还有一些填充。

[1] 我认为。目前没有时间检查规范以确定是否sizeof可以返回 0。

于 2011-01-22T05:28:02.077 回答