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