【问题标题】:cpp class size with virutal pointer and inheritance具有虚拟指针和继承的 cpp 类大小
【发布时间】:2020-01-04 09:00:04
【问题描述】:
class A{
    virtual void a();
};  
class B : A{
    virtual void a();
};
class C{
    virtual void a();
};
class E : A, C{
    virtual void a();
};

int main(){
    std::cout << (sizeof(B)) << "\n"; // 4
    std::cout << (sizeof(C)) << "\n"; // 4
    std::cout << (sizeof(E)) << "\n"; // 8
}

在 32 位系统 linux 中

为什么sizeof(B)和sizeof(C)都是4

对于C类,它有一个虚函数,所以在C类中隐藏了一个虚拟指针,它是4字节的

但是为什么B类的大小也是4。我认为B类中存在两个指针,一个是B本身的,因为B类有一个虚函数,一个是A的。

那么 E 也有同样的问题?

感谢任何帮助

【问题讨论】:

  • 您的代码示例中有很多拼写错误,导致无法编译。我们为您解决了这个问题,但是当您在这里发帖时应该更加准确:-)

标签: c++ virtual-table


【解决方案1】:

不,每个使用虚函数的对象中只有一个 vtable 指针,如果虚函数是在类本身中定义的,或者该类派生自另一个使用虚函数的类,则独立。

编译器生成的是一个函数指针表,因此每个类(不是实例/对象)都有自己的。在您的示例中,您有一个 A 类表,一个 B 类表,依此类推。在每个对象/实例中,您都有一个 vtable 指针。该指针仅指向表。如果你通过类指针调用一个虚函数,你就可以间接访问 vtable 指针,而不是 vtable 本身。

因此,每个类的实例只保留一个 vtable 指针,指向该类的 vtable。如您所见,这会导致您编写的每个类的每个实例的大小都相同。

在多重继承的情况下,你会得到多个vtable指针。这里已经给出了更详细的答案: vtable and multiple inheritance

顺便说一句:标准不能保证你有一个 vtable 和一个 vtable 指针,如果结果是我们对语义的期望,每个编译器都可以做它想做的事情。但是通过vtable指针到函数表中的指针的双重间接是典型的实现。

【讨论】:

  • 这是不正确的。例如,E 类的一个实例将有两个 vtable 指针,这就是为什么 sizeof(E) 在上面是 8...
【解决方案2】:

对于单继承,派生类 B 只是在虚拟表中再插入一个条目。 对于多重继承,派生类 E 有 2 个虚表指针。

进一步:C++ virtual table layout of MI(multiple inheritance)

【讨论】:

    猜你喜欢
    • 2020-10-31
    • 2023-03-22
    • 2011-03-20
    • 2013-02-26
    • 2016-03-04
    • 2019-12-20
    • 1970-01-01
    • 2020-02-01
    相关资源
    最近更新 更多