C++三大特性----“继承”
来源:互联网 发布:中兴软件开发怎么样 编辑:程序博客网 时间:2024/06/10 23:10
C++作为一门面向对象的语言,其核心便是它的三大特性:封装,继承和多态。
而其中,继承这一特性的存在最主要的目的是为了实现代码的复用,即当你在构建多个类的时候,你发现它们之间有相当一部分的功能和属性是相同,这时你就可以通过继承这一特性来进行代码的复用,将重复的部分作为公共部分来使用,从而不必在构建每一个类的时候都将相同的部分在写一遍。
继承的定义格式:
继承方式与访问限定符之间的关系:
1.公有继承public:对于公有继承而言,基类中该成员是被哪种访问限定符所修饰的,那么在派生类中依旧是被这种访问限定符所修饰的,对于成员的访问权限并未做任何修改
2.保护继承protected:对于保护继承而言,除了将基类当中被public访问限定符所修饰的成员变成以protected所修饰的以外,对于其他访问限定符所修饰的成员,并不改变他们的访问权限。
3.私有继承private:对于私有继承而言,要将基类当中被public以及protected修饰的成员均变成以private所修饰的,原本以private修饰的不做改动。
综上,根据上述继承方式有以下几个注意点:
1.对于三种继承方式来说,基类中public,protected对应的成员,在派生类中均可进行访问,而对于private成员,虽说一样是被继承下来了,但由于private访问权限,不能在类外被访问,由此,我们可以清楚的看到protected与private这两个访问限定符之间的区别在于能否在派生类中被访问。
2.对于三种继承方式下来的派生类的对象,除了public继承能访问基类中public修饰的成员以外,派生类的对象是无法访问基类中的成员的。
3.使用class关键字时,默认的继承方式为private,而以struct为关键字时,默认的继承方式是public
继承机制下构造函数与析构函数的调用:
构造函数:
构造派生类对象:a.调用派生类的构造函数;b.在派生类构造函数初始化列表处调用基类的构造函数;c.完成基类构造函数;d.返回并完成派生类构造函数剩下部分
析构函数:
析构派生类对象:a.调用派生类的析构函数;b.执行派生类析构函数的函数体; c.调用基类的析构函数;d.执行基类析构函数函数体后返回
由此,我们可以总结出以下几点:
1.当基类的构造函数是由系统合成,或者是全缺省的构造函数,那么在构造函数不需要做其他事情的时候,派生类的构造函数系统可以自动合成。
2.当基类的构造函数是缺省的构造函数(即需要进行传参时),那么派生类的构造函数必须给出,系统无法合成。
继承的几项规则与特点:
1.派生类与基类是两个不同的作用域;
2.当派生类中存在与基类同名的成员的时候(成员函数是否同名与参数无关),通过派生类的对象进行访问的时候,只能访问派生类中的成员,若要访问基类中的成员,必须加上作用域限定符(同名隐藏);
3.派生类的对象可以对基类对象进行赋值,反之不可;(public继承)
4.基类对象的引用或指针可以指向派生类的对象,反之不可;(public继承)
5.友元函数是不能被继承的(友元函数不是成员函数);
6.基类中的静态成员可以被继承,但无论有多少派生类,该静态成员仅有一份,也就是说基类与派生类共用一份该静态成员;
继承得到的派生类的对象模型:
1.单继承
对象模型:
测试代码:
class A{public:void fun(int a){cout<<"A"<<endl;}public:int _a1;int _a2;};class B:public A{public:void fun(){cout<<"B"<<endl;}public:int _b1;int _b2;};int main(){B b;b._a1=1;b._a2=2;b._b1=3;b._b2=4;return 0;}测试结果:
查看派生类对象b的内存空间:
2.多继承
对象模型:
测试代码:
class A{public:int _a1;int _a2;};class B{public:int _b1;int _b2;};class C:public A,public B{public:int _c1;int _c2;};int main(){C c;c._a1=1;c._a2=2;c._b1=3;c._b2=4;c._c1=5;c._c2=6;return 0;}
测试结果:
查看派生类c的内存空间:
3.菱形继承
测试代码:
class A{public:int _a;};class B1:public A{public:int _b1;int _b2;};class B2:public A{public:int _b3;int _b4;};class C:public B1,public B2{public:int _c1;int _c2;};int main(){C c;c.B1::_a=1;c._b1=3;c._b2=4;c.B2::_a=5;c._b3=6;c._b4=7;c._c1=8;c._c2=9;return 0;}测试结果:
查看派生类对象c的内存空间:
4.虚拟继承与菱形虚拟继承
研究菱形继承后我们发现一个问题,那就是在菱形继承的最终派生类C的对象c当中会将最开始的基类A中的成员继承两份,一份来自对B1的继承,一份来自对B2的继承,而在通过对象访问的时候,会出现访问A中成员的不明确,从而不得不加上作用域限定符来进行访问。
而对于这个问题,通过菱形虚拟继承可以很好的解决。
首先我们来看下虚拟继承的对象模型:
测试代码:
class A{public:int _a1;int _a2;};class B:virtual public A{public:int _b1;int _b2;};int main(){B b;b._a1=1;b._a2=2;b._b1=3;b._b2=4;return 0;}
测试结果:
查看派生类对象b的内存空间:
由此可以推出,虚拟继承的对象模型:
偏移量表内容:
菱形虚拟继承:
测试代码:
class A{public:int _a;};class B1:virtual public A{public:int _b1;int _b2;};class B2:virtual public A{public:int _b3;int _b4;};class C:public B1,public B2{public:int _c1;int _c2;};int main(){C c;c._a=1;c._b1=3;c._b2=4;c._b3=6;c._b4=7;c._c1=8;c._c2=9;return 0;}
查看派生类对象c的内存空间:
由此可以发现,虚拟菱形继承中对于A类的成员只继承了一份,而通过偏移量表中保存的偏移量很好的解决了通过C的对象访问A类成员的不明确的问题。
- 黑马程序员---Objective-C 三大特性---继承
- 三大特性_继承
- JAVA三大特性--继承
- java三大特性--继承
- 七、三大特性~继承
- C++三大特性----“继承”
- Java三大特性--继承
- java三大特性:继承
- C++三大特性--继承
- C++三大特性 -- 继承
- java的三大特性之继承
- 面向对象三大特性之 继承
- java三大特性:封装、继承、多态
- 面向对象三大特性---继承
- java 三大特性 封装 继承 多态
- Java三大特性分析-继承
- OC-5-三大特性:继承
- 学习日记-三大特性之继承
- web旋转动画
- 数据库
- rviz实现gmapping的具体方法,利用官方包
- apt-get installs 报错 Could not open lock file /var/lib/dpkg/lock
- (UVA)272
- C++三大特性----“继承”
- 结构型模式之装饰DECORATOR
- 蓝桥杯 ALGO-101 算法训练 图形显示
- Codeforces Round #308 (Div. 2)C
- 获取项目部署名称的两种方式
- Contact Us
- CDH启动和日志查看
- 蓝桥杯 ALGO-81 算法训练 动态数组使用
- sql 查出一张表中重复的所有记录数据