c++多态情况下对象内存布局

原创 2016年08月31日 12:50:06

今天在复习C++多态时有个问题没弄清楚,子类继承含有虚函数的父类时,子类的虚表是否是公用的?
如果是公用的,虚表什么时候创建?为了弄清楚这个问题,写了以下程序来验证


得到了如下结论:
子类的虚表是公用,虚表创建于第一个实例构造之时,所有子类实例虚表指针都指向这块虚表。
同时也验证了C++对象的内存布局
以下是验证代码:

#include "stdafx.h"
#include<iostream>

using namespace std;

class A
{
public:
	virtual void a_function() {}
	int a = 1;
};
class B :public A
{
public:
	void a_function() {}
	int b = 2;
};

class C :public A
{
public:
	void c_function() {}
	int c = 3;
};

int main()
{
	A  a1;
	A  a2;
	B  b1;
	B  b2;
	C  c1;
	C  c2;

	cout << (int*)(&a1) << '\t' << (int *)(&a2) << '\n';//a对象虚表指针的地址,不同,存储在对象内存的起始处

	cout << *(int*)(&a1) << '\t'<< *(int *)(&a2)<<'\n'; //a对象虚表指针指向的值,相同即表示同一类的不同对象虚表指针指向同一块内存
	cout << *(int*)(&b1) <<'\t'<< *(int *)(&b2) << '\n'; //b对象虚表指针指向的值,相同即表示同一类的不同对象虚表指针指向同一块内存
	cout << *(int*)(&c1) << '\t' << *(int *)(&c2) << '\n'; //c对象虚表指针指向的值,相同即表示同一类的不同对象虚表指针指向同一块内存
	//a, b, c 三个类的虚表地址不同, C即使不含虚函数,也没重写a_function也继承了虚表指针。


	cout << (int*)(&b1)+1 << '\t' << (int *)(&b2)+1 << '\n';//不同b实例的b成员地址不同,表示不同实例分配了不同的内存


	cout << *((int*)(&b1) + 1) << '\t' << *((int *)(&b2) + 1) << '\n'; //b对象的第二个成员的值为继承自父类数据成员a的值(第一个成员为虚表指针)
	cout << *((int*)(&b1) + 2) << '\t' << *((int *)(&b2) + 2) << '\n'; //b对象第三个成员的值为子类数据成员b的值

	//综上继承时,如果父类有虚函数,内存布局如下:
	/*
	1、虚表指针,同一类虚表指针指向的值相同,即都指向同一块内存,同一张虚表
	2、父类的数据成员
	2、子类的数据成员
	*/

	//另外
	//当子类重写父类的虚函数时,子类的虚表对应的虚函数指针将被覆盖成子类的虚函数指针。
	//子类非继承自父类的虚函数,将被添加到虚表的末尾。
	//多重继承时,如果有n个含有虚函数的父类,则子类有n张虚表,每个实例起始处有n个虚表指针。
	//任何妄图使用父类指针想调用子类中的未覆盖父类的成员函数的行为都会被编译器视为非法。
    return 0;
}


结果如下图:


相关文章推荐

C++程序运行时内存布局之----------无继承情况下的虚函数

没有继承的情况下,拥有虚函数的类及其实例在运行期的内存布局。
  • smstong
  • smstong
  • 2011年07月04日 17:55
  • 1885

C++对象布局及多态实现

  • 2008年05月12日 20:35
  • 34KB
  • 下载

黑马程序员_10_成员变量_成员方法_静态成员方法_在多态情况下的特点

---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------   *****...

java多态情况下通过类型转换访问子类特有的成员

目前多态情况下不能访问子类特有的成员。 如果需要访问子类特有的成员,那么需要进行类型强制转换. 基本数据类型的转换 小数据类型-------->大的数据类型      自动类型转换 ...
  • oguro
  • oguro
  • 2016年11月08日 19:54
  • 195

C++多态篇2——虚函数表详解之从内存布局看函数重载,函数覆盖,函数隐藏

上一篇C++多态篇1一静态联编,动态联编、虚函数与虚函数表vtable中,我在最后分析了虚函数与虚函数表的内存布局,在下一篇详细剖析虚函数及虚函数表的过程中,我发现有关函数重载,函数覆盖,函数重写和函...

C++对象布局及多态实现的探索(六)

C++对象布局及多态实现的探索(六) 后记   结合前面的讨论,我们可以看到,只要牵涉到了虚继承,在访问父类的成员变量时生成的代码相当的低效,需要通过很多间接的计算来定位成员变量的...
  • ilvu999
  • ilvu999
  • 2012年09月05日 00:14
  • 572

C++对象布局及多态实现的探索

虚函数的类的对象布局(1)     如果类中存在虚函数时,情况会怎样呢?我们知道当一个类中有虚函数时,编译器会为该类产生一个虚函数表,并在它的每一个对象中插入一个指向该虚函数表的指针,通常这个指...
  • kannju
  • kannju
  • 2011年09月01日 15:40
  • 364

C++中的类的成员变量在各种情况下所占用的内存大小

内存对齐的讲解请参考:点击打开链接#include using namespace std; int main() { /* *空类,类中没有变量也没有函数 *占用内存:1个字节 *原因:C...

C++ 类继承与对象赋值 情况下 成员变量的覆盖 浅析

类的继承以及对象的赋值会带来成员变量的相互传递。这里详细讨论了,类间继承带来的成员变量的传递采用覆盖原则,采用函数级的成员变量的取值;对象赋值带来的成员变量的传递采用,实函数采用数据类型的实函数,虚函...

C++对象模型——"无继承"情况下的对象构造(第五章)

5.1 "无继承"情况下的对象构造 考虑下面这个程序片段: 1 Point global; 2 3 Point foobar() 4 { 5 Point local; 6 Point *heap ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:c++多态情况下对象内存布局
举报原因:
原因补充:

(最多只允许输入30个字)