多继承下数据成员布局

继承下数据成员布局

将分类讨论类中的成员布局

无继承子类有虚函数

#include <iostream>
#include <cstdio>
class Son
{
public:
	Son(){}
	~Son(){}
	virtual void MYCALSFun1()
	{
		printf("Son::this=%p\n", this);
		printf("MYCALS::a=%p\n", &Son::a);
		printf("MYCALS::b=%p\n", &Son::b);
	}
public:
	int a;
	int b;
};
int main()
{
	Son s;
	s.MYCALSFun1();
	return 0;
}
输出:
Son::this=00BAFADC
MYCALS::a=00000004
MYCALS::b=00000008
内存布局:
0x00BAFADC  34 9c a9 00 cc cc cc cc cc cc cc cc

分析

该类占12个字节,分别为两个int类型和1个虚函数指针,this与vptr公用地址,a偏移4个地址,b便宜8个地址,内存布局为vptr->a->b

单继承子有虚函数父无虚函数

#include <iostream>
#include <cstdio>

class Base
{
public:
	Base()
	{
		printf("Base::this=%p\n", this);
	}
	~Base(){}
public:
	int c;
};

class Son : public Base
{
public:
	Son()
	{
		printf("Son::this=%p\n", this);
	}
	~Son(){}
	virtual void MYCALSFun1(){}
public:
	int a;
	int b;
};

int main()
{
	Son s;
	s.a = 1, s.b = 2, s.c = 3;
	printf("MYCALS::c=%p\n", &Son::c);
	printf("MYCALS::a=%p\n", &Son::a);
	printf("MYCALS::b=%p\n", &Son::b);

	return 0;
}
输出:
Base::this=012FF6F4
Son::this=012FF6F0
MYCALS::c=00000000
MYCALS::a=00000008
MYCALS::b=0000000C
内存:
0x012FF6F0  40 9c 17 00 03 00 00 00 01 00 00 00 02 00 00 00

分析

son的this指针与对象的地址相同,Base的this指针与变量c的地址相同,所以c偏移值为0,c的参照是Base。布局顺序是vptr->c->a->b

单继承父子都有虚函数

#include <iostream>
#include <cstdio>

class Base
{
public:
	Base()
	{
		printf("Base::this=%p\n", this);
	}
	~Base(){}
	virtual void BaseFun1(){}
public:
	int c;
};

class Son : public Base
{
public:
	Son()
	{
		printf("Son::this=%p\n", this);
	}
	~Son(){}
	virtual void MYCALSFun1(){}
public:
	int a;
	int b;
};

int main()
{
	Son s;
	s.a = 1, s.b = 2, s.c = 3;
	printf("MYCALS::c=%p\n", &Son::c);
	printf("MYCALS::a=%p\n", &Son::a);
	printf("MYCALS::b=%p\n", &Son::b);
	return 0;
}
输出:
Base::this=010FFEB8
Son::this=010FFEB8
MYCALS::c=00000004
MYCALS::a=00000008
MYCALS::b=0000000C
内存:
0x0133F76C  50 9c e1 00 03 00 00 00 01 00 00 00 02 00 00 00

分析

子父类公用一个this指针,要么都有虚函数,要么都没有虚函数,此时父子类才会共用一个this,c的偏移改变,从刚刚的0变成了4,原因就是this指针相同了,布局顺序是vptr->c->a->b

多继承都有虚函数

#include <iostream>
#include <cstdio>

class Base
{
public:
	Base()
	{
		printf("Base::this=%p\n", this);
	}
	~Base(){}
	virtual void BaseFun1(){}
public:
	int c;
};

class Base2
{
public:
	Base2()
	{
		printf("Base2::this=%p\n", this);
	}
	virtual void Base2Fun1(){}
public:
	int d;
};

class Son : public Base, public Base2
{
public:
	Son()
	{
		printf("Son::this=%p\n", this);
	}
	~Son(){}
	virtual void MYCALSFun1(){}
public:
	int a;
	int b;
};

int main()
{
	Son s;
	s.a = 1, s.b = 2, s.c = 3, s.d = 4;
	printf("MYCALS::c=%p\n", &Son::c);
	printf("MYCALS::a=%p\n", &Son::a);
	printf("MYCALS::b=%p\n", &Son::b);
	printf("MYCALS::d=%p\n", &Son::d);
	return 0;
}
输出:
Base::this=00D0FAC0
Base2::this=00D0FAC8
Son::this=00D0FAC0
MYCALS::c=00000004
MYCALS::a=00000010
MYCALS::b=00000014
MYCALS::d=00000004
内存:
0x00D0FAC0  0c 9e bf 00 03 00 00 00 1c 9e bf 00 04 00 00 00 01 00  .??......??.......
0x00D0FAD2  00 00 02 00 00 00

分析

Base和Son共用一个this指针,Base2单独一个Base指针,c相对于Base的this偏移了4,d相对于Base2的this偏移了4,a是偏移了10(H)也就是16,是Base的偏移+Base2的偏移,b偏移了14(H),在a的基础上多了4,布局顺序:Basevptr->c->Base2vptr->d->a->b

多态直接的相互转换

使用上面的代码进行改进

#include <iostream>
#include <cstdio>

class Base
{
public:
	Base()
	{
		c = 3;
		printf("Base::this=%p\n", this);
	}
	~Base(){}
	virtual void BaseFun1(){}
public:
	int c;
};

class Base2
{
public:
	Base2()
	{
		d = 4;
		printf("Base2::this=%p\n", this);
	}
	virtual void Base2Fun1(){}
public:
	int d;
};

class Son : public Base, public Base2
{
public:
	Son()
	{
		a = 1, b = 2;
		printf("Son::this=%p\n", this);
	}
	~Son(){}
	virtual void MYCALSFun1(){}
public:
	int a;
	int b;
};

int main()
{
	Base *b1 = new Son();
	Son *s = (Son*)b1;
	Base2 *b2 = s;
	return 0;
}
地址:
b1=014E9DE8
s=014E9DF0
b2=014E9DE8
内存:
0x014E9DE8  0c 9e 58 00 03 00 00 00 1c 9e 58 00 04 00 00 00 01 00  .?X......?X.......
0x014E9DFA  00 00 02 00 00 00

分析

在指针进行强制类型转换的时候其实只是做了指针的偏移来完成的

多继承释放的不是第一个this指针造成的后果

在多继承中,指针是可以来回转换的,上串代码中base、base1、son的指针都是可以互相转换的,但是释放并不是都可以释放的,b1和s的this是指向头节点的,是可以释放没有问题的,但是b2的指针并不是头节点,他是在中间的,释放的时候就会异常,如下:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值