继承体系下派生类的对象模型

博客链接:https://blog.csdn.net/qq_39412582/article/details/81273137 看到标题我们首先应该想到的是什么是对象模型? 那好,什么是对象模型呢?**对象模型就是对象中非静态成员变量在内存中的布局形式。**但是,我们要看这个布局只能在内存中查看,在监视窗口可能不会看到我们想要看到的结果(C++中经常会遇到这种事情,你看到的并不一定就是真的)。

那么什么又是继承呢? 继承:就是在一个已存在的类的基础上建立一个新的类,而这个新的类又从已有的类获得其原有的特性,这个现象叫做类的继承。 **派生:**从父类继承出来的子类叫做类的派生。 根据继承方式可分为: 单继承 多继承 菱形继承 虚拟继承 菱形虚拟继承 五种

单继承

一个派生类只能从一个基类派生叫做单继承。 类似于树形结构。 继承方式:

class B
{
public:
	int _b;
};
class D : public B  
{
public:
	int _d;
};
int main()
{
	cout << sizeof(D) << endl;
	D d;
	d._b = 10;
	d._d = 20;
	return 0;
}

多继承

继承方式:

class A
{
public:
	int _a;
};
class B
{
public:
	int _b;
};
class D :public A,public B
{
public:
	int _d;
};
int main()
{
	cout << sizeof(D) << endl;
	D d;
	d._b = 10;
	d._d = 20;
	return 0;
}

前两种继承方式很简单,这里就不多介绍了。

菱形继承

看个例子:

class B
{
public:
	int _b;
};
class C1:public B
{
public:
	int _c1;
};
class C2:public B
{
public:
	int _c2;
};
class D :public C1,public C2
{
public:
	int _d;
};
int main()
{
	cout << sizeof(D) << endl;
	D d;
	d._b = 10;
	d._d = 20;
	return 0;
}  //思考有没有问题?

继承方式: 为什么会编译错误?那是因为存在二义性。 要怎么解决呢? 本文提供两种解决方案: ⑴d.C1::_b=10 //来自那一个类里面的_b要写清楚,这样就不会报错 ⑵ 就要用到菱形虚拟继承

看一段代码:

//单继承方式
class B
{
public:
	int _b;
};
class D : public B
{
public:
	int _d;
};
int main()
{
	cout << sizeof(D) << endl;
	D d;
	d._b = 10;
	d._d = 20;

	return 0;
}

思考一下这里的**sizeof(D)**应该是多少? 可以看到结果就是我们所想的那样。 但是当我们在20 行下断点进行调试的时候发现它并没有停下来,我们给的情景是:

想要让编译器为我们合成构造函数,先来看看虚拟继承。

虚拟继承

class B
{
public:
	int _b;
};
class D :virtual public B  //virtual   虚拟继承的关键字
{
public:
	int _d;
};
int main()
{
	cout << sizeof(D) << endl;
	B b;
	D d;
	d._b = 10;
	d._d = 20;

	return 0;
}

这里的**sizeof(D)**又是多少呢?

可以看到这次编译器在18行给我们停了下来,但是却多了4个字节,说明它为我们创建了构造函数。 然后我们在内存中看看它到底什什么情况:

怎么来理解呢?我以画图的形式给大家做出详细的解释:

如果这个例子不够满意的话,你还可以去看看反汇编,看看代码在底层是怎么实现的。

我们可以把这个eax+4 这个寄存器强转成 int* 类型在解引用就可以发现它也是 8

菱形虚拟继承

在上面我们说普通的菱形继承存在二义性问题,除了加上作用域限定符之外还可以用菱形虚拟继承来解决。下面就跟着我看看本篇文章最后的一个问题把:

那什么是菱形虚拟继承?聪明的人一下就会想到,就是在菱形继承里加上virtual这个虚拟关键字不就OK了,没错就是这样。

class B
{
public:
	int _b;
};
class C1:virtual public B
{
public:
	int _c1;
};
class C2:virtual public B
{
public:
	int _c2;
};
class D :public C1,public C2
{
public:
	int _d;
};
int main()
{
	cout << sizeof(D) << endl;
	D d;
	d._b = 1;
	d._c1 = 2;
	d._c2 = 3;
	d._d = 4;
	return 0;
}

那这里的sizeof应该是多少呢?24?还是28?

怎么理解呢:我通过画图的方式给大家解答

再说两个面试题: ⑴设计一个类,该类不能被继承? 答:可以用private 访问限定符来做到不能被继承问题,还有一种方法就是C++11里面给出的final关键字,添加在类的后面。 ⑵为什么菱形虚拟继承能够解决菱形继承中二义性的问题? 上面的文章已经给出了答案,相信你已经OK了。