这是一种家庭作业问题。对于以下代码,
#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 的事情。
但是这里发生的是,典型的基于 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 };
在这个问题中,如果你尝试获取 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' 字节。
请原谅我含糊其辞,但你提到这本质上是家庭作业。
查看 sizeof() 为其他类返回什么。您的答案将根据您的编译器以及您处于 32 位还是 64 位环境中而有所不同。
快乐侦查!
对象的大小与它有多少方法无关,也与这些方法是否是虚拟的有关。对象的大小仅由其成员变量决定。
我无法确切地告诉你为什么你会得到 8 字节的大小。由于类中没有数据成员,C++ 编译器原则上可以生成一个完全不占用空间的类 [1]!我猜测 8 个字节是提供指向 vtbl 的指针所需的最小值,还可能加上一些填充。
[1]我认为。目前没有时间检查规范来了解
sizeof
是否可以返回 0。