0
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的同样问题?

任何帮助表示赞赏

4

2 回答 2

2

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

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

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

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

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

于 2020-01-04T09:22:36.967 回答
0

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

进一步:MI的C++虚拟表布局(多重继承)

于 2020-01-04T09:35:45.927 回答