memory layout of inherited class

后端 未结 5 577
不知归路
不知归路 2021-02-04 05:25

I\'m keen to know exactly how the classes will be arranged in memory esp. with inheritance and virtual functions.

I know that this is not defined by the c++ language st

相关标签:
5条回答
  • 2021-02-04 05:38

    One way is to print out the offsets of all the members:

    class Parent{
    public:
        int a;
        int b;
    
        virtual void foo(){
            cout << "parent" << endl;
        }
    };
    
    class Child : public Parent{
    public:
        int c;
        int d;
    
        virtual void foo(){
            cout << "child" << endl;
        }
    };
    
    int main(){
    
        Parent p;
        Child c;
    
        p.foo();
        c.foo();
    
        cout << "Parent Offset a = " << (size_t)&p.a - (size_t)&p << endl;
        cout << "Parent Offset b = " << (size_t)&p.b - (size_t)&p << endl;
    
        cout << "Child Offset a = " << (size_t)&c.a - (size_t)&c << endl;
        cout << "Child Offset b = " << (size_t)&c.b - (size_t)&c << endl;
        cout << "Child Offset c = " << (size_t)&c.c - (size_t)&c << endl;
        cout << "Child Offset d = " << (size_t)&c.d - (size_t)&c << endl;
    
        system("pause");
    }
    

    Output:

    parent
    child
    Parent Offset a = 8
    Parent Offset b = 12
    Child Offset a = 8
    Child Offset b = 12
    Child Offset c = 16
    Child Offset d = 20
    

    So you can see all the offsets here. You'll notice that there's nothing at offset 0, as that is presumably where the pointer to the vtable goes.

    Also notice that the inherited members have the same offsets in both Child and Parent.

    0 讨论(0)
  • 2021-02-04 05:39

    Create an object of class, cast pointer to it to your machine's word, use sizeof to find the size of the object, and examine the memory at the location. Something like this:

    #include <iostream>
    
    class A
    {
     public:
      unsigned long long int mData;
      A() :
       mData( 1 )
      {
      }      
      virtual ~A()
      {
      }
    };
    class B : public A
    {
     public:
      unsigned long long int mData1;
      B() :
       A(), mData1( 2 )
      {
      }
    };
    
    int main( void )
    {
     B lB;
    
     unsigned long long int * pB = ( unsigned long long int * )( &lB );
    
     for( int i = 0; i < sizeof(B) / 8; i++ )
     {
      std::cout << *( pB + i ) << std::endl;
     }
    
     return ( 0 );
    }
    
    
    Program output (MSVC++ x86-64):
    
    5358814688 // vptr
    1          // A::mData
    2          // B::mData1
    

    On a side note, Stanley B. Lippman has excellent book "Inside the C++ Object Model".

    0 讨论(0)
  • 2021-02-04 05:41

    As long as you stick to single inheritance, the subobjects are typically layed out in the order they are declared. A pointer is prepended to they type information at the front which is e.g. used for dynamic dispatch. Once multiple inheritance is incolved things become more complex, especially when virtual inheritance is involved.

    To find precise information at least for one ABI flavour you can look for the Itanium ABI. This documents all these details. It is used as the C++ ABI at least on some Linux platforms (i.e. there multiple compilers can produce object files linked into one executable).

    To determine the layout just print the addresses of subobjects of a give object. That said, unless you happen to implement a compiler it typically doesn't matter. The only real use of the object layout I doubd is arranging members to minimize padding.

    0 讨论(0)
  • 2021-02-04 05:46

    The best way is probably writing a few simple test cases and then compile and debug them in assembler (all optimization off): running one instruction at a time you'll see where everything fits.

    At least that's the way I learned it.

    And if you find any case particularly challenging, post in in SO!

    0 讨论(0)
  • 2021-02-04 05:47

    Visual Studio atleast has a hidden compiler option /d1reportSingleClassLayout (starting at ~32:00).

    Usage: /d1reportSingleClassLayoutCLASSNAME where there shall be no whitespace between the compiler switch and CLASSNAME (obviously replace this with the name of the class you'e interested in).

    0 讨论(0)
提交回复
热议问题