继承小结
来源:互联网 发布:店淘精品数据采集神器 编辑:程序博客网 时间:2024/05/18 19:44
继承是复用代码的重要手段也为动态多态提供了平台
定义格式:
一、 继承关系
基类(父类)
派生类(子类)
派生类对象模型如图:
类 缺少继承权限:默认权限为private继承
结构体缺少继承权限:默认权限为public继承
#include <iostream>using namespace std;class Base{public:Base(int a = 1):_b(a){}~Base(){cout << "Base()" << endl;}int _B;private:int _b;};class Derive :public Base{public:Derive(int a):Base(a),_d(a){}~Derive(){cout << "Derive()" << endl;}private:int _d;};class D :protected Base{public:D(int a):Base(a), _D(a){}~D(){cout << "D()" << endl;}private:int _D;};class DD :private Base{public:DD(int a):Base(a), _DD(a){}~DD(){cout << "DD()" << endl;}private:int _DD;};int main(){Derive a(1);D b(1);DD c(1);/*Base b(1);*/a._B = 10;b._B = 1;c._B = 1;system("pause");return 0;}
二、
派生类构造函数的初始化链表先完成基类对象构造(调用基类的构造函数)最后构造派生类自己特有的成员
派生类先调用自己的析构函数最后调用基类析构函数
1、基类没有缺省构造函数,派生类必须要在初始化列表中显式给出基类名和参数列表。
2、基类没有定义构造函数,则派生类也可以不用定义,全部使用缺省构造函数。
3、基类定义了带有形参表构造函数,派生类就一定定义构造函数。
否则:出现如下错误
#include <iostream>using namespace std;class Base{public:Base(int a ):_b(a){}~Base(){cout << "Base()" << endl;}int _B;private:int _b;};class B{private:int _B1;};class Derive :public Base{public:Derive(int a):Base(a),_d(a){}~Derive(){cout << "Derive()" << endl;}private:int _d;};class D :public Base{public:D(int a): _D(a){}~D(){cout << "D()" << endl;}private:int _D;};class DD :public B{public:~DD(){cout << "DD()" << endl;}private:int _DD;};int main(){Derive a(1);D b1;D b(1);DD c;/*Base b(1);*//*a._B = 10;b._B = 1;c._B = 1;*/a.~Derive();system("pause");return 0;}
三、继承体系中的作用域
1. 在继承体系中基类和派生类是两个不同作用域。(不能构成重载)
2. 子类和父类中有同名成员,子类成员将屏蔽父类对成员的直接访问。(在子类成员函数中,可以
使用 基类::基类成员 访问)--隐藏 --重定义
3. 注意在实际中在继承体系里面最好不要定义同名的成员。
#include <iostream>using namespace std;class Base{public:Base(int a = 1):_b(a){}void FunTest(int a){ }~Base(){cout << "Base()" << endl;}int _B;private:int _b;};class Derive :public Base{public:Derive(int a):Base(a),_d(a){}void FunTest(){ }~Derive(){cout << "Derive()" << endl;}int _B;private:int _d;};int main(){Derive a(1);Base B;/*D b1;D b(1);DD c;*//*Base b(1);*//*a._B = 10;b._B = 1;c._B = 1;*//*a.FunTest(a);*/// 不能形成重载a._B = 1; // 不能给基类赋值 a.Base::_B = 1; 对基类赋值a.~Derive();system("pause");return 0;}
四、继承与转换--赋值兼容规则--public继承
1. 子类对象可以赋值给父类对象(切割/切片)
2. 父类对象不能赋值给子类对象
3. 父类的指针/引用可以指向子类对象
4. 子类的指针/引用不能指向父类对象(可以通过强制类型转换完成)
友元关系不可继承
五、多继承
#include <iostream>using namespace std;class B1{public:int _B1;};class B2{public:int _B2;};class D :public B1,public B2 //继承B1和B2 {public:int _D;};int main(){D d;cout << sizeof(d) << endl;d._B1 = 0;d._B2 = 1;d._D = 2;system("pause");return 0;}
调试得到:对象d 的大小为3*4 = 12个字节, 取d地址, 从内存中可以看出 d的对象模型为
六、菱形继承
如图所示继承:
#include <iostream>using namespace std;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 //继承B1和B2 {public:int _D;};int main(){D d;cout << sizeof(d) << endl;//d._B = 0; 产生二义性问题d.C1::_B = 0;d.C2::_B = 1;d._c1 = 2;d._c2 = 3;d._D = 4;system("pause");return 0;}
调试结果如图
得到对象模型
七、虚继承
虚继承关键字 :virtual
虚继承 避免了二义性问题
#include <iostream>using namespace std;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 //继承B1和B2 {public:int _D;};int main(){D d;cout << sizeof(d) << endl;d._B = 0; // 产生二义性问题d._c1 = 1;d._c2 = 2;d._D = 3;system("pause");return 0;}
调试:
d的大小为24, 对象模型为:
取d的地址发现前四个字节不是某个类成员变量的值,它其实是个地址 ,在内存2中输入前四个字节的内容发现 它前四个字节为0x00 00 00 00转化为十进制就是0 接着为0x 14 00 00 00 转化为十进制就是20。
这个地址是偏移量表格的地址。
偏移量表格里面放的是 相对于自己的偏移量以及相对于基类的偏移量。
如内存2中存放的内容:
第一个字节放的为0 相对于C1偏移量为0。
第二个字节放的为20 相对于B偏移量为20 即 &d+20 得到存放基类的地址。
欢迎各位,批评指正。
- 继承小结
- 继承小结
- 继承小结
- 继承小结
- 继承小结
- 继承小结
- 继承小结
- 继承小结
- 继承小结
- C#继承小结
- C# 继承小结
- C++继承例题小结
- 虚继承基础小结
- 多重继承小结
- C++虚继承小结
- 类,对象,继承 小结
- C++虚继承小结
- JAVA继承知识小结
- 【机器学习笔记】判别模型和生成模型(贝叶斯估计)
- C++中的函数重复定义问题
- PRSA的作用域对比
- 安装anaconda + opencv for mac
- 数据结构C++小笔记《2017-10-08》
- 继承小结
- 基于微擎的消息回复
- ad发过火
- 作业:习题3
- 数理逻辑习题集(4)
- volitate与volatile
- Linux 命令行入门
- js-10*10个div-制作整图碎片化效果
- 为什么你那么努力,却一直还得不到提升?