2

说我们有

Class A
{
   public:
   int _i;
   virtual int getI();
};
class B : public A
{  
   public:
   int _j;
   virtual int getI();
};

因此,假设内存中类的大小是其成员的总和(即忽略填充或实际可能发生的任何事情),B 实例的大小是多少?是 sizeof(A) + sizeof(int) + sizeof(vptr) 吗?还是 B 实例在其个人 A 实例中不包含 A vptr,因此 sizeof(b) 将是 sizeof(int) + sizeof(int) + sizeof(vptr)?

4

4 回答 4

3

这是实现使代码工作所需的任何东西。你只能说它至少是2 * sizeof(int),因为类型的对象B包含两个ints (可能还有其他东西)。在一个典型的实现中,A并且B将共享一个 vptr,并且总大小将仅比两个整数多一个指针(用于对齐的模填充,但在大多数实现中,我认为不会有任何)。但这只是一个典型的实现;你不能指望它。

于 2011-09-23T13:36:06.280 回答
1

任何关于 vtable 的讨论都将特定于某个实现,因为即使 vtable 的存在也不是由 C++ 标准指定的——它是一个实现细节。

通常,一个对象只有一个指向 vtable 的指针,并且该 vtable 将在该类型的所有对象之间共享。派生类将在表中包含基类的每个虚函数以及它未继承的每个新虚函数的指针,但这又是一个静态表,它不是对象的一部分。

要真正回答这个问题,最可能的结果是 sizeof(B) == sizeof(A::_i) + sizeof(B::_j) + sizeof(vptr)。

于 2011-09-23T14:06:09.400 回答
0

除了 James Kanze 所说的之外,也许值得一提的是(在典型的实现中)B 的虚拟表在开始时将包含 A 的虚拟表。

例如:

class A {
    virtual void x();
    virtual void y();
};

class B : A {
    virtual void y();
    virtual void z();
};

A的虚拟表:

  • 斧头()
  • 答:y()

B的虚拟表:

  • 斧头()
  • :y()
  • B:z()

这就是为什么 B 的实例只需一个虚拟表指针就可以逃脱的原因。

顺便说一句,多重继承会使事情变得相当复杂,并为每个对象引入多个虚拟表指针。

永远记住,所有这些都是一个实现细节,你永远不应该编写依赖它的代码。

于 2011-09-23T13:47:45.073 回答
0

你为什么想知道?如果你打算在你的程序中使用它,我会尝试寻找一种比计算它更便携的方法,或者添加一个返回大小的虚函数,或者使用运行时类型信息来获取正确的类型,然后返回大小。

(如果您投票或添加评论,我将开始装饰答案)

于 2011-09-23T13:53:57.013 回答