如何确定具有虚函数的类的大小?

问题描述 投票:0回答:4

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

#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 位平台上工作。

c++ sizeof vtable
4个回答
18
投票

这当然取决于实现。 这将是一个糟糕的面试问题。当然,对于日常用途,C++ 程序员可以相信

sizeof
是正确的,让编译器担心那些 vtable 的事情。

但是这里发生的是,典型的基于 vtable 的实现需要类

C
D
的对象中的两个 vtable。每个基类都需要有自己的 vtable。
C
D
添加的新虚拟方法可以通过从一个基类扩展vtable格式来处理,但是
A
B
使用的vtable不能组合。

在伪 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 };

4
投票

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

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

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

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


1
投票

请原谅我含糊其辞,但你提到这本质上是家庭作业。

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

快乐侦查!


-2
投票

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

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

[1]我认为。目前没有时间检查规范来了解

sizeof
是否可以返回 0。

© www.soinside.com 2019 - 2024. All rights reserved.