C ++ Object Memory layout and Object Memory Layout

Source: Internet
Author: User

C ++ Object Memory layout and Object Memory Layout

Source: http://www.cnblogs.com/coderkian/

When no virtual function is used, the memory layout of the C ++ object is the same as the struct of the C language. This is easy to understand. This article only analyzes the situation of virtual functions, this article describes the following aspects,

1. Single inheritance

2. Multi-Inheritance

3. Virtual inheritance

The following step-by-step analysis environment is ubuntu 12.04.3 LTS + gcc4.8.1

 

Single inheritance

To achieve polymorphism during runtime, the virtual function address cannot be determined during the compilation period. You need to use the virtual function table to find the actually called virtual function address during runtime. There are two main issues for a single inheritance:

1. Where is the virtual function table?

2. How are the virtual functions of the base class and derived class organized according to the rules?

The Class Structure Code is as follows:

class base{public:  base(int bv):bval(bv){};  virtual void base_f(){cout<<"base::f()"<<endl;}  virtual void base_g(){cout<<"base::g()"<<endl;}private:  int bval;};class derived: public base{public:  derived(int bv, int dv):base(bv), dval(dv){};  void base_f(){cout<<"derived::f()"<<endl;}  virtual void derived_h(){cout<<"derived::h()"<<endl;}private:  int dval;};

Use the following test code to view the memory space of the base class and derived class:

base b(10);FUN fun;int **pvtab = (int**)&b;cout<<"[0]:base->vptr"<<endl;for(int i=0; i<2; i++){    fun = (FUN)pvtab[0][i];    cout<<" "<<i<<" ";    fun();}cout<<" 2 "<<pvtab[0][2]<<endl;cout<<"[1]:bval "<<(int)pvtab[1]<<endl;derived d(10, 100);pvtab = (int**)&d;cout<<"[0]:derived->vptr "<<endl;for(int i=0; i<3; i++){    fun = (FUN)pvtab[0][i];    cout<<" "<<i<<" ";    fun();}cout<<" 3 "<<pvtab[0][3]<<endl;cout<<"[1]:bval "<<(int)pvtab[1]<<endl;cout<<"[2]:dval "<<(int)pvtab[2]<<endl;

Running result:

[0]: base-> vptr

0 base: f ()

1 base: g ()

2 1919247415

[1]: bval 10

[0]: derived-> vptr

0 derived: f ()

1 base: g ()

2 derived: h ()

3 0

[1]: bval 10

[2]: dval 100

This is the case with graphs (I use the same color to represent functions and data members of the same class in this article for distinction ).

The results show that:

1. the pointer to the virtual function table is at the first position of the object.

2. member variables are arranged in sequence based on their inheritance and declaration.

3. The virtual functions are sequentially placed in the virtual function table according to the Inheritance and Declaration Order. The virtual functions that are rewritten in the derived classes are updated at the original position without adding new functions.

4. the last position of the virtual function table of the derived class is NULL, but the base class is a non-NULL pointer (displayed in red). I don't understand the role of this position in gcc, if you know something, please tell me. Thank you very much!

 

Multi-Inheritance

If multiple inheritance is added, the situation will be a little complicated. How can the virtual functions of multiple base classes be organized to use any base class to achieve polymorphism?

The Class Structure Code is as follows:

class base1{public:    base1(int bv):bval1(bv){};    virtual void base_f(){cout<<"base1::f()"<<endl;}    virtual void base1_g(){cout<<"base1::g()"<<endl;}private:    int bval1;};class base2{public:    base2(int bv):bval2(bv){};    virtual void base_f(){cout<<"base2::f()"<<endl;}    virtual void base2_g(){cout<<"base2::g()"<<endl;}private:    int bval2;};class derived: public base1, public base2{public:    derived(int bv1, int bv2,  int dv):base1(bv1),base2(bv2), dval(dv){};    virtual void base_f(){cout<<"derived::f()"<<endl;}    virtual void derived_h(){cout<<"derived::h()"<<endl;}private:    int dval;};

 

Test code to view the memory layout:

derived d(10, 100, 1000);FUN fun;int **pvtab = (int**)&d;cout<<"[0]:base1->vptr "<<endl;for(int i=0; i<3; i++){    fun = (FUN)pvtab[0][i];    cout<<"  "<<i<<"  ";    fun();}cout<<"  3  "<<pvtab[0][3]<<endl;cout<<"[1]:bval1  "<<(int)pvtab[1]<<endl;cout<<"[2]:base2->vptr "<<endl;for(int i=0; i<2; i++){    fun = (FUN)pvtab[2][i];    cout<<"  "<<i<<"  ";    fun();}cout<<"  2  "<<pvtab[2][2]<<endl;cout<<"[3]:bval2  "<<(int)pvtab[3]<<endl;cout<<"[4]:dval  "<<(int)pvtab[4]<<endl;

 

The running result is as follows:

[0]: base1-> vptr

0 derived: f ()

1 base1: g ()

2 derived: h ()

3-8

[1]: bval1 10

[2]: base2-> vptr

0 derived: f ()

1 base2: g ()

2 0

[3]: bval2 100

[4]: dval 1000

Summary:

1. Each base class has a separate virtual function table, and the virtual function of the subclass is placed in the virtual function table of the first base class.

2. The base class memory space is ordered by the Declaration Order of the base class

3. If multiple base classes have virtual functions with the same name, the function of all base classes will be overwritten when the derived classes are rewritten. If this clause is not covered, functions of the same name between different base classes will produce ambiguity. You must specify the function of the class for use.

4. The last position of the virtual function table of the first base class is still not blank (in red). Its function is unknown.

 

Virtual inheritance

Virtual inheritance requires that the base class has only one copy in the derived class, so the memory layout is a little more complex than multi-inheritance. We will introduce the most typical diamond inheritance as an example.

The Class Structure Code is as follows:

class base{public:    base(int bv):bval(bv){};    virtual void base_f(){cout<<"base::f()"<<endl;}    virtual void base_t(){cout<<"base::t()"<<endl;}private:    int bval;};class base1:virtual public base{public:    base1(int bv, int bv1):base(bv), bval1(bv1){};    void base_f(){cout<<"base1::f()"<<endl;}    virtual void base1_g(){cout<<"base1::g()"<<endl;}    virtual void base1_k(){cout<<"base1::k()"<<endl;}private:    int bval1;};class base2: virtual public base{public:    base2(int bv, int bv2):base(bv), bval2(bv2){};    void base_f(){cout<<"base2::f()"<<endl;}    virtual void base2_g(){cout<<"base2::g()"<<endl;}    virtual void base2_k(){cout<<"base2::k()"<<endl;}private:    int bval2;};class derived: public base1, public base2{public:    derived(int bv, int bv1, int bv2,  int dv):base(bv), base1(bv, bv1),base2(bv, bv2), dval(dv){};    void base_f(){cout<<"derived::f()"<<endl;}    void base1_g(){cout<<"derived::base1_g()"<<endl;}    void base2_g(){cout<<"derived::base2_g()"<<endl;}    virtual void derived_h(){cout<<"derived::h()"<<endl;}private:    int dval;}

 

Test code to view memory structure

 derived d(10, 100, 1000, 10000);    FUN fun = NULL;    int **pvtab = (int**)&d;    cout<<"[0]:base1->vptr "<<endl;    for(int i=0; i<5; i++){        fun = (FUN)pvtab[0][i];        cout<<"  "<<i<<"  ";        fun();    }    cout<<"  5  "<<pvtab[0][4]<<endl;    cout<<"[1]:bval1  "<<(int)pvtab[1]<<endl;    cout<<"[2]:base2->vptr "<<endl;    for(int i=0; i<3; i++){        fun = (FUN)pvtab[2][i];        cout<<"  "<<i<<"  ";        fun();    }    cout<<"  3  "<<pvtab[2][3]<<endl;    cout<<"[3]:bval2  "<<(int)pvtab[3]<<endl;    cout<<"[4]:dval  "<<(int)pvtab[4]<<endl;    cout<<"[5]:base->vptr "<<endl;    for(int i=0; i<2; i++){        fun = (FUN)pvtab[5][i];        cout<<"  "<<i<<"  ";        fun();    }    cout<<"  2  "<<pvtab[5][2]<<endl;

Running result:

[0]: base1-> vptr

0 derived: f ()

1 derived: base‑g ()

2 base1: k ()

3 derived: base2_g ()

4 derived: h ()

5 134516512

[1]: bval1 100

[2]: base2-> vptr

0 derived: f ()

1 derived: base2_g ()

2 base2: k ()

3 0

[3]: bval2 1000

[4]: dval 10000

[5]: base-> vptr

0 derived: f ()

1 base: t ()

2 134517004

The results show that:

1. Directly non-virtual base classes are arranged in the declared order and then the derived classes. This is the same as multi-inheritance.

2. The virtual function of the derived class is still placed in the first virtual function table of the direct non-virtual base class.

3. Put the virtual base class at the end, with only one copy.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.