C++多态和对象的内存布局(一)

 

首先VS2015配置:

在当前工程右键 --> 属性:

先选择左侧的C/C++->命令行,然后在其他选项这里写上/d1 reportAllClassLayout,它可以看到所有相关类的内存布局,如果写上/d1 reportSingleClassLayoutXXX(XXX为类名),则只会打出指定类XXX的内存布局。

 

开始进入主题测试类对象内存布局:


1. 只有数据成员的对象 

成员变量是按照定义的顺序来保存的, 最先声明的在最上边, 然后依次保存.
类对象的大小就是所有成员变量大小之和.


程序输出:
sizeof(Base_1) = 16
   
内存布局:
1>  class Base_1    size(16):
1>      +---
1>   0    | base_1_1
1>   4    | base_1_2
1>   8    | base_1_3

测试代码:

#include<iostream>
#include<string>

using namespace std;

class Base_1
{
public:
    int base_1_1;/* 4 */
    int base_1_2;/* 4 */
	long long base_1_3; /* 8 */
};

int main()
{
	cout << endl << "1. 只有数据成员的对象" << endl;
	
	cout << "sizeof(Base_1) = " << sizeof(Base_1) << endl << endl;		
	
	return 0;
}

2. 有数据成员的对象,并且包含一个普通函数的对象,没有虚函数的对象

   可以看到对象的的大小等于成员属性大小之和,普通的成员函数并不产生内存空间,也就不会对对象的布局造成任何影响,
   那么他就不可能会发生动态绑定,当调用一个非虚函数时, 那么调用的一定就是当前指针类型拥有的那个成员函数. 
   这种调用机制在编译时期就确定下来了. 

程序输出:
sizeof(Base_1) = 8

内存布局:
1>  class Base_1    size(8):
1>      +---
1>   0    | base_1_1
1>   4    | base_1_2
1>      +---

测试代码:

#include<iostream>
#include<string>

using namespace std;

class Base_1
{
public:
    int base_1_1;
    int base_1_2;
	
    void Base_1_fun()
	{
		cout << "void Base_1_fun()" << endl;
	}
};


int main()
{
	cout << endl << "2. 有数据成员的对象,并且包含一个普通函数的对象,没有虚函数的对象" << endl;
	
	cout << "sizeof(Base_1) = " << sizeof(Base_1) << endl << endl;		
	
	return 0;
}

3. 有数据成员的对象,并且包含一个虚函数的对象

    base1_1前面多了一个变量 __vfptr(常说的虚函数表vtable指针), 
    其类型为void**, 这说明它是一个void*指针(注意:不是数组),是一个指向数组的指针. 
    虚函数指针__vfptr位于所有的成员变量之前定义.

程序输出:
sizeof(Base_1) = 12 (成员属性 + 指向虚函数表的指针)

伪代码:
void*   __fun[] = { &Base_1::Base_1_fun_1 };
const void**  __vfptr = &__fun[0];
   
内存布局:
1>  class Base_1    size(12):
1>      +---
1>   0    | {vfptr}
1>   4    | base_1_1
1>   8    | base_1_2
1>      +---
  
虚函数表:
1>  Base_1::$vftable@:
1>      | &Base_1_meta
1>      |  0
1>   0    | &Base_1::Base_1_fun_1 

测试代码:

#include<iostream>
#include<string>

using namespace std;

class Base_1
{
public:
    int base_1_1;
    int base_1_2;
	
    virtual void Base_1_fun_1()
	{
		cout << "virtual void Base_1_fun_1()" << endl;
	}
};


int main()
{
	cout << endl << "3. 有数据成员的对象,并且包含一个虚函数的对象" << endl;
	
	cout << "sizeof(Base_1) = " << sizeof(Base_1) << endl << endl;		
	
	return 0;
}

4. 有数据成员的对象,并且包含两个虚函数的对象

   通过这次可以看出__vfptr 只是一个指向虚函数表的指针而已。
   真正保存对象中虚函数的是虚函数表,而这里的虚函数指针只是提供一个虚函数表的入口。

程序输出:
sizeof(Base_1) = 12 (成员属性 + 指向虚函数表的指针)

伪代码:
void* __fun[] = { &Base_1::Base_1_fun_1, &Base1::Base_1_fun_2 };
const void** __vfptr = &__fun[0];

虚函数表:
1. 同一个类的不同实例共用同一份虚函数表, 它们都通过一个所谓的虚函数表指针__vfptr(定义为void**类型)指向该虚函数表.
2. 它是编译器在编译时期为我们创建好的, 只存在一份
3. 定义类对象时, 编译器自动将类对象的__vfptr指向这个虚函数表


内存布局:   
1>  class Base_1    size(12):
1>      +---
1>   0    | {vfptr}
1>   4    | base_1_1
1>   8    | base_1_2
1>      +---


虚函数表:
1>  Base_1::$vftable@:
1>      | &Base_1_meta
1>      |  0
1>   0    | &Base_1::Base_1_fun_1
1>   1    | &Base_1::Base_1_fun_2 

测试代码:

#include<iostream>
#include<string>

using namespace std;

class Base_1
{
public:
    int base_1_1;
    int base_1_2;
	
    virtual void Base_1_fun_1()
	{
		cout << "virtual void Base_1_fun_1()" << endl;
	}
	virtual void Base_1_fun_2()
	{
		cout << "virtual void Base_1_fun_2()" << endl;
	}
};

int main()
{
	cout << endl << "4. 有数据成员的对象,并且包含两个虚函数的对象" << endl;
	
	cout << "sizeof(Base_1) = " << sizeof(Base_1) << endl << endl;		
	
	return 0;
}

 

 

未完待续...

C++多态和对象的内存布局(二)

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值