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

发布于 2024-10-14 07:21:26 字数 494 浏览 3 评论 0原文

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

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

this is kind of homework question. For the following code,

#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;
}

The output is: 8

Could anyone please explain how it is 8 bytes? If the vtable implementation is compiler dependent, what should I answer for this kind of question in interviews? What about virtual base classes?

EDIT: i am working on a 32-bit platform.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

少钕鈤記 2024-10-21 07:21:26

这当然取决于实现。 这将是一个糟糕的面试问题。当然,对于日常用途,C++ 程序员可以相信 sizeof 是正确的,并让编译器担心那些 vtable 的事情。

但这里发生的情况是,典型的基于 vtable 的实现需要类 CD 的对象中的两个 vtable。每个基类都需要有自己的 vtable。 CD 添加的新虚拟方法可以通过从一个基类扩展 vtable 格式来处理,但 A 使用的 vtable 和B 无法组合。

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

This is of course implementation-dependent. And it would make a terrible interview question. Of course, for everyday purposes, a C++ programmer can just trust sizeof to be right and let the compiler worry about those vtable things.

But what's going on here is that a typical vtable-based implementation needs two vtables in objects of class C or D. Each base class needs its own vtable. The new virtual methods added by C and D can be handled by extending the vtable format from one base class, but the vtables used by A and B can't be combined.

In pseudo-C-code, here's how a most derived object of type D looks on my implementation (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 };
旧瑾黎汐 2024-10-21 07:21:26

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

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

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

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

In this question if you try to get Sizeof class A, it will give you answer '4' because A have only one virtual function so its __vptr will be of '4' byte.

In the same way, if you try to get Sizeof class B, it will give you answer '4' because B also have only one virtual function so its __vptr will be of '4' byte.

But class C is inheriting both classes A & B and C itself have a virtual function. So C will receive 2 __vptr pointers, and for its own virtual function C will use the inherited __vptr.
So if you try to get Sizeof class C, it will give you answer '8' because C have two virtual pointers.

And lastly class D is inheriting class C so D will use inherited __vptr for its own virtual function and because class C have sizeof '8' byte so sizeof D will give you answer '8' byte.

楠木可依 2024-10-21 07:21:26

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

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

快乐侦查!

Forgive me for being vague, but you are mentioning that it is homework in nature.

See what sizeof() returns for the other classes. Your answer will vary depending on your compiler and whether you are in a 32 or 64 bit environment.

Happy sleuthing!

櫻之舞 2024-10-21 07:21:26

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

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

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

The size of the object has nothing to do with how many methods that it has, nor with whether those methods are virtual or not. The size of an object is determined solely by its member variables.

I can't tell you exactly why you're getting a size of 8 bytes. Since there are no data members in your class, a C++ compiler could in principle generate a class that occupies no space at all [1]! I'm guessing that the 8 bytes is the minimum required to provide a pointer to the vtbl, plus possibly some padding.

[1] I think. No time to check the spec to find out at the moment whether sizeof can ever return 0.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文