关闭

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

111人阅读 评论(0) 收藏 举报
分类:

今天在复习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;
}


结果如下图:


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:46063次
    • 积分:1152
    • 等级:
    • 排名:千里之外
    • 原创:54篇
    • 转载:102篇
    • 译文:0篇
    • 评论:13条
    文章分类