C&C++   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了c – 有关Virtual Inheritance层次结构的问题大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
在处理虚拟继承时遇到这个问题.我记得在非虚拟继承层次结构中,子类的对象拥有其直接超类的对象.那么虚拟继承呢?在这种情况下,子类的对象是直接拥有其超类的对象还是仅仅持有指向其超类对象的指针?

顺便说一下,为什么以下代码输出是:

sizeof(A): 8
sizeof(B): 20
sizeof(C): 20
sizeof(D): 36

码:

#include <iostream>

using namespace std;

class A{
    char k[ 3 ];
    public:
        virtual void a(){};
};

class B : public virtual A{
    char j[ 3 ];
    public:
        virtual  void b(){};
};

class C : public virtual A{
    char i[ 3 ];
    public:
        virtual void c(){};
};

class D : public B,public C{
    char h[ 3 ];
    public:
        virtual void d(){};
};

int main( int argc,char *argv[] ){
    cout << "sizeof(A): " << sizeof( A ) << endl;
    cout << "sizeof(B): " << sizeof( B ) << endl;
    cout << "sizeof(C): " << sizeof( C ) << endl;
    cout << "sizeof(D): " << sizeof( D ) << endl;

    return 0;
}

提前致谢.
亲切的问候.

解决方法

虚拟基础对象位于内存块中属于对象的某个位置(具有size = sizeof(object)的内存).因为不同类型的若干子对象可以以各种方式组合但必须共享相同的基础对象,所以每个子对象需要偏移指针来找出虚拟基础对象.如果没有虚拟继承,则在编译时为每个类类型修复找出相应基础对象的偏移量.

sizeof值取决于您的编译器和机器,但以下假设非常常见:

假设:指针大小为4个字节

假设:类大小向上舍入为4个字节的倍数

sizeof(A): 8  ->   1 pointer to vtable (virtual method) 
                 + 3 chars -> 4+3=7 
              -> round up to 8

sizeof(B): 20 ->   8 + 1 pointer to vtable (virtual method) 
                 + 1 offset pointer to virtual base 
                 + 3 chars -> 8 + 4 + 4 + 3 = 19 
              -> round up to 20

sizeof(C): 32 ->  20 + 1 pointer to vtable (virtual method) 
                 + 1 offset pointer to virtual base 
                 + 3 chars 
              -> 20 + 4 + 4 + 3 = 31 // this calculation refers to an older 
              -> round up to 32      // version of the question's example 
                                     // where C had B as base class

猜测计算是因为实际计算必须完全知道编译器的工作原理.

问候,
奥利弗

更多细节为什么需要额外的偏移指针:

例:

class B  : virtual public A {...};
class C  : virtual public A {...};
class D1 : public B {...};
class D2 : public B,C {...};

D1的可能内存布局:

A
B
D1

D2的可能内存布局:

A
C
B
D2

在第二种情况下,子对象B需要另一个偏移量来找到它的基数A.

D2类型的对象由一个内存块组成,其中包含所有父对象部分,即D2类型对象的内存块有一个A成员变量,C成员变量,B成员变量和D2成员变量.这些部分的顺序取决于编译器,但是示例显示,对于多个虚拟继承,需要一个偏移指针,该指针指向对象的总内存块中的虚拟基础对象.这是必需的,因为B类的方法只知道一个指向B的指针,并且必须以某种方式计算A存储器部分相对于t​​his指针的位置.

计算尺寸(D):

sizeof(D): 36 ->   A:3 chars + A:vtable 
                 + B:3 chars + B:vtable + B:virtual base pointer
                 + C:3 chars + C:vtable + C:virtual base pointer
                 + D:3 chars + D:vtable
               =   3 + 4 
                 + 3 + 4 + 4 
                 + 3 + 4 + 4 
                 + 3 + 4 
                 = 36

上面的计算可能是错的;-) ……

我不确定D部分是否有自己的vtable指针(这都是高度依赖编译器的).

我现在认为可能是D部分使用其父类的vtable指针条目,并且4个额外字节用于对齐每个部分(8个字节的倍数):

所以这个计算可能更正确:

sizeof(D): 36 ->   A:3 chars + A:vtable + A:alignment
                 + B:3 chars + B:vtable + B:virtual base pointer + B:alignment
                 + C:3 chars + C:vtable + C:virtual base pointer + C:alignment
                 + D:3 chars + D:alignment
               =   3 + 4 + 1
                 + 3 + 4 + 4 + 1 
                 + 3 + 4 + 4 + 1
                 + 3 + 1
                 = 36

大佬总结

以上是大佬教程为你收集整理的c – 有关Virtual Inheritance层次结构的问题全部内容,希望文章能够帮你解决c – 有关Virtual Inheritance层次结构的问题所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: