带有虚拟方法的C ++对象大小 [英] C++ object size with virtual methods

查看:104
本文介绍了带有虚拟方法的C ++对象大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对虚拟对象的大小有些疑问.

I have some questions about the object size with virtual.

1)虚拟功能

class A {
    public:
       int a;
       virtual void v();
    }

A类的大小为8个字节....一个整数(4个字节)加一个虚拟指针(4个字节) 很明显!

The size of class A is 8bytes....one integer(4 bytes) plus one virtual pointer(4 bytes) It's clear!

class B: public A{
    public:
       int b;
       virtual void w();
}

B类的大小是多少?我使用sizeof B测试,它可以打印 12

What's the size of class B? I tested using sizeof B, it prints 12

这是否意味着即使B类和A类都具有虚拟功能,也只有一个vptr?为什么只有一个vptr?

Does it mean that only one vptr is there even both of class B and class A have virtual function? Why there is only one vptr?

class A {
public:
    int a;
    virtual void v();
};

class B {
public:
    int b;
    virtual void w();
};

class C :  public A, public B {
public:
    int c;
    virtual void x();
};

C的大小是20 ........

The sizeof C is 20........

在这种情况下,似乎有两个vptr在布局中.....这是怎么发生的?我认为这两个vptr一个是针对A类的,另一个是针对B类的.....所以没有C类的虚函数的vptr吗?

It seems that in this case, two vptrs are in the layout.....How does this happen? I think the two vptrs one is for class A and another is for class B....so there is no vptr for the virtual function of class C?

我的问题是,继承中的vptrs数量规则是什么?

My question is, what's the rule about the number of vptrs in inheritance?

2)虚拟继承

    class A {
    public:
        int a;
        virtual void v();
    };

    class B: virtual public A{                  //virtual inheritance 
    public:
        int b;
        virtual void w();
    };

    class C :  public A {                      //non-virtual inheritance
    public:
        int c;
        virtual void x();
    };

class D: public B, public C {
public:
    int d;
    virtual void y();
};

A的大小为8个字节-------------- 4(int a)+ 4(vptr)= 8

The sizeof A is 8 bytes -------------- 4(int a) + 4 (vptr) = 8

B的大小是16个字节--------------如果没有虚拟字节,它应该是4 + 4 + 4 =12.为什么这里还有另外4个字节? B类的布局是什么?

The sizeof B is 16 bytes -------------- Without virtual it should be 4 + 4 + 4 = 12. why there is another 4 bytes here? What's the layout of class B ?

C的大小为12个字节. -------------- 4 + 4 + 4 =12.很明显!

The sizeof C is 12 bytes. -------------- 4 + 4 + 4 = 12. It's clear!

D的大小为32个字节--------------它应该为16(B类)+ 12(C类)+ 4(int d)=32.对吗?

The sizeof D is 32 bytes -------------- it should be 16(class B) + 12(class C) + 4(int d) = 32. Is that right?

    class A {
    public:
        int a;
        virtual void v();
    };

    class B: virtual public A{                       //virtual inheritance here
    public:
        int b;
        virtual void w();
    };

    class C :  virtual public A {                    //virtual inheritance here
    public:
        int c;
        virtual void x();
    };

  class D: public B, public C {
   public:
        int d;
        virtual void y();
    };

sizeof A是8

sizeof A is 8

B的大小为16

sizeof C是16

sizeof C is 16

sizeof D是28,是否意味着28 = 16(B类)+ 16(C类)-8(A类)+ 4(这是什么?)

sizeof D is 28 Does it mean 28 = 16(class B) + 16(class C) - 8(class A) + 4 ( what's this? )

我的问题是,为什么在应用虚拟继承时会有额外的空间?

My question is , why there is an extra space when virtual inheritance is applied?

在这种情况下,对象大小的基本规则是什么?

What's the underneath rule for the object size in this case?

将virtual应用于所有基类和部分基类有什么区别?

What's the difference when virtual is applied on all the base classes and on part of the base classes?

推荐答案

这是所有定义的实现.我正在使用VC10 Beta2.帮助理解这些内容(虚拟功能的实现)的关键是,您需要了解Visual Studio编译器中的一个秘密开关/d1reportSingleClassLayoutXXX .一会儿,我会讲到这一点.

This is all implementation defined. I'm using VC10 Beta2. The key to help understanding this stuff (the implementation of virtual functions), you need to know about a secret switch in the Visual Studio compiler, /d1reportSingleClassLayoutXXX. I'll get to that in a second.

基本规则是,对于任何指向对象的指针,vtable必须位于偏移量0处.这意味着需要多个vtable进行多重继承.

The basic rule is the vtable needs to be located at offset 0 for any pointer to an object. This implies multiple vtables for multiple inheritance.

在这里耦合问题,我将从顶部开始:

Couple questions here, I'll start at the top:

这是否意味着即使B类和A类都具有虚拟功能,也只有一个vptr?为什么只有一个vptr?

Does it mean that only one vptr is there even both of class B and class A have virtual function? Why there is only one vptr?

这是虚拟函数的工作方式,您希望基类和派生类共享相同的vtable指针(指向派生类中的实现.

This is how virtual functions work, you want the base class and derived class to share the same vtable pointer (pointing to the implementation in the derived class.

在这种情况下,似乎有两个vptr在布局中.....这是怎么发生的?我认为这两个vptr一个用于A类,另一个用于B类....所以没有C类的虚函数的vptr吗?

It seems that in this case, two vptrs are in the layout.....How does this happen? I think the two vptrs one is for class A and another is for class B....so there is no vptr for the virtual function of class C?

这是类C的布局,由/d1reportSingleClassLayoutC报告:

This is the layout of class C, as reported by /d1reportSingleClassLayoutC:

class C size(20):
        +---
        | +--- (base class A)
 0      | | {vfptr}
 4      | | a
        | +---
        | +--- (base class B)
 8      | | {vfptr}
12      | | b
        | +---
16      | c
        +---

您是正确的,有两个vtable,每个基类一个.这就是它在多重继承中的工作方式.如果将C *强制转换为B *,则指针值将调整8个字节.为了使虚拟函数调用正常工作,vtable仍需要位于偏移量0处.

You are correct, there are two vtables, one for each base class. This is how it works in multiple inheritance; if the C* is casted to a B*, the pointer value gets adjusted by 8 bytes. A vtable still needs to be at offset 0 for virtual function calls to work.

以上布局中A类的vtable被视为C类的vtable(通过C *调用时).

The vtable in the above layout for class A is treated as class C's vtable (when called through a C*).

B的大小是16个字节--------------如果没有虚拟字节,它应该是4 + 4 + 4 =12.为什么这里还有另外4个字节? B类的布局是什么?

The sizeof B is 16 bytes -------------- Without virtual it should be 4 + 4 + 4 = 12. why there is another 4 bytes here? What's the layout of class B ?

在此示例中,这是B类的布局:

This is the layout of class B in this example:

class B size(20):
        +---
 0      | {vfptr}
 4      | {vbptr}
 8      | b
        +---
        +--- (virtual base A)
12      | {vfptr}
16      | a
        +---

如您所见,还有一个额外的指针可以处理虚拟继承.虚拟继承很复杂.

As you can see, there is an extra pointer to handle virtual inheritance. Virtual inheritance is complicated.

D的大小为32个字节--------------它应该为16(B类)+ 12(C类)+ 4(int d)=32.对吗?

The sizeof D is 32 bytes -------------- it should be 16(class B) + 12(class C) + 4(int d) = 32. Is that right?

否,36个字节.同样处理虚拟继承.在此示例中D的布局:

No, 36 bytes. Same deal with the virtual inheritance. Layout of D in this example:

class D size(36):
        +---
        | +--- (base class B)
 0      | | {vfptr}
 4      | | {vbptr}
 8      | | b
        | +---
        | +--- (base class C)
        | | +--- (base class A)
12      | | | {vfptr}
16      | | | a
        | | +---
20      | | c
        | +---
24      | d
        +---
        +--- (virtual base A)
28      | {vfptr}
32      | a
        +---

我的问题是,为什么在应用虚拟继承时会有额外的空间?

My question is , why there is an extra space when virtual inheritance is applied?

虚拟基类指针,很复杂.基类在虚拟继承中是组合"的.该类将在布局中具有指向基类对象的指针,而不是将基类嵌入到类中.如果您有两个使用虚拟继承的基类(钻石"类层次结构),则它们都将指向对象中的同一虚拟基类,而不是具有该基类的单独副本.

Virtual base class pointer, it's complicated. Base classes are "combined" in virtual inheritance. Instead of having a base class embedded into a class, the class will have a pointer to the base class object in the layout. If you have two base classes using virtual inheritance (the "diamond" class hierarchy), they will both point to the same virtual base class in the object, instead of having a separate copy of that base class.

在这种情况下,对象大小的基本规则是什么?

What's the underneath rule for the object size in this case?

重要点;没有规则:编译器可以做任何需要做的事情.

Important point; there are no rules: the compiler can do whatever it needs to do.

最后一个细节;制作我正在使用的所有这些类布局图:

And a final detail; to make all these class layout diagrams I am compiling with:

cl test.cpp /d1reportSingleClassLayoutXXX

其中XXX是要查看其布局的结构/类的子字符串匹配.使用此工具,您可以自己探索各种继承方案的影响,以及为什么/在何处添加填充等.

Where XXX is a substring match of the structs/classes you want to see the layout of. Using this you can explore the affects of various inheritance schemes yourself, as well as why/where padding is added, etc.

这篇关于带有虚拟方法的C ++对象大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆