如何从中确定虚基类和派生类的大小?

时间:2011-06-27 18:17:12

标签: c++

#include <iostream>
using namespace std;

class base1{};
class base2{virtual void show(){}};

class test1{    };
class test2{virtual void show(){}};

class derv1:public virtual base1{};
class derv12:public virtual base2{};

class derv2:public virtual base2, public test1{};
class derv22:public virtual base2, public virtual test1{};
class derv222:public virtual base2, public virtual test2{};

int main()
{
    cout<<"sizeof base1 = "<<sizeof(base1)<<endl;
    cout<<"sizeof base2 = "<<sizeof(base2)<<endl;
    cout<<"sizeof derv1 = "<<sizeof(derv1)<<endl;
    cout<<"sizeof derv12 = "<<sizeof(derv12)<<endl;

    cout<<"sizeof derv2 = "<<sizeof(derv2)<<endl;
    cout<<"sizeof derv22 = "<<sizeof(derv22)<<endl;
    cout<<"sizeof derv222 = "<<sizeof(derv222)<<endl;

}

输出:

sizeof base1 = 1
sizeof base2 = 4
sizeof derv1 = 4
sizeof derv12 = 8
sizeof derv2 = 8
sizeof derv22 = 8
sizeof derv222 = 12

我理解以下输出:

sizeof base1 : 1 => empty class , size is 1. result is OK.

sizeof base2 : 4 => since class has a virtual function, it adds 
                    a vitual pointer in each object of the class
                    ( 32 bit machine) , so added 4 bytes. Result is OK.

sizeof derv1 : 4 => base1 doesn't have  virtual function but since 
                    derv1 is virtually derived from base1 ,added 4 bytes. 
                    I think that each virtual base class
                    added a  pointer in object so i think Result is OK.     

sizeof derv12: 8 => 4 bytes( from virtual pointer) + 4 bytes
                     (virtual base class ) = 8 bytes. Result is OK.

在上述输出

之后我的困惑开始了
sizeof derv2  : 8 => 8 bytes( virtual pointer + virtually base class)
                    from base2 + 1 byte from test1 => 9 bytes and adds 3 padding 
                    bytes gives 12 bytes (should print). 
                     why "sizeof (test1)" is not adding in the output ??

sizeof derv22 : 8 => 8 bytes( virtual pointer + virtually base class)
                    from base2 + 4 byte (virtually base class) 
                    from test1  => 12 bytes (should print)

                    why 4 bytes from  test1 (virtual base class)  is not added 
                    in the output?? In the  size of(derv1 ) also has
                    a virtual base class( base1) and out put is 4 bytes means
                    they added 4 bytes in the output. 

sizeof derv222: 12 => 12 bytes( virtual pointer + virtually derived)
                      from base2 + 8 byte( virtual pointer + virtually derived)
                      from test2  => 16 bytes (should print)

我是否遗漏了某些东西,或者这些尺寸是系统依赖还是其他任何东西?

4 个答案:

答案 0 :(得分:8)

sizeof(base1)sizeof(test1)为1的原因是以防止大多数派生对象的大小为0.这就是所有标准的禁止。允许基类子对象的大小为0(也就是说,允许不占用任何字节),因此添加base1作为基础不会必须必须添加任何内容班级的大小。

编译器所做的优化,而不是为类型为空类的基类子对象分配任何字节,称为“空基类优化”。标准不要求实现应用它,但实现不适合认真工作。

我认为derv22有点类似 - 如果编译器能够使用一个额外的指针处理两个虚拟基类,那么它有权这样做。因此,您可能只需要“支付”一次,而不是每个虚拟基数“支付”。这可能取决于编译器以及类之间的确切关系,但是,我从未调查过不同的实现,以查看它们是否以及何时被迫添加多个指针值得开销。

显然derv222已经完成了,至少对你的编译器来说。我想这是因为base2test2基类子对象需要单独的vtable指针。如果您考虑当static_cast derv222*作为指向一个基础或另一个基础的指针时发生的情况可能并不令人惊讶 - 两个结果都需要能够show()调用它们,并且调用不同的函数(尽管show函数当前什么都不做)。我不确定其他编译器是否有可能以8个字节实现此继承 - 一方面,继承不会使用vtable实现

答案 1 :(得分:5)

  

如何确定虚拟的大小   基类和派生类   它??

使用sizeof()

答案 2 :(得分:3)

我的旧论文“C ++:Under the Hood”解释了虚拟基类的Microsoft C ++实现。 http://www.openrce.org/articles/files/jangrayhood.pdf

您可以使用cl / d1reportAllClassLayout进行编译,以获取类内存布局的文本报告。

快乐的黑客攻击!

答案 3 :(得分:0)

以虚拟(访问说明符)模式(例如,虚拟公共)继承基类的Empty类的大小为8,如果非空,则为16。