继承与派生

继承与派生的概念

区分继承和组合

​ 从模块累积的角度来说,大模块是由无数个小模块构成的。构建一个模块的方式有两种,一是小模块架构组合成为大模块,二是小模块继承生成大模块。

​ 模块可以通过调用模块成员使用模块成员的性质,这就是组合。

​ 组合的代码理解如下:

#include<bits/stdc++.h>
using namespace std;
class point{private:int x,y;public:point(int xx,int yy):x(xx),y(yy){}void showpoint(){cout<<"("<<x<<","<<y<<")"<<endl;}~point(){}
};
///小模块组合为大模块
class circle{public:point p;double r;public:circle(int xx,int yy,double rr);double getarea(){return 3.14*r*r;}void shouarea(){cout<<"S="<<getarea()<<endl;}
};
///构造函数
circle::circle(int xx,int yy,double rr):p(xx,yy),r(rr){}
int main(){circle c(3,4,5.1);c.shouarea();(c.p).showpoint();return 0;
}

​ 模块除了组合关系,还有继承关系,简要地说就是把父模块的功能性质直接作为自己的功能性质。

继承的概念

​ 简单的理解就是在原有类的功能性质上添加新的功能从而产生一个新的类,这就是继承。

​ 一个新类继承了原有类,原有类称为基类或父类,新类称为派生类或子类。子类获得父类的特性是继承,父类产生子类是派生。

​ 如果一个类只有一个基类,称为单继承,如果有多个基类,称为多继承。

(如果一个派生模块只继承了一个基类模块,称为单继承;如果一个派生模块继承了多个基类模块作为自己的子成员,这种继承关系成为多继承。)

​ 派生类模块的构造是在已有模块的基础上发展起来的,即派生类模块继承了基类模块的接口功能。

​ 派生模块继承了基类模块,也就是说基类模块是派生模块的一部分,在构造派生模块时当然要构造一个基类模块作为他的子成员

派生类的声明

语法

(以公有继承关系为例)

(具体的继承方式在下一段介绍)

class 派生类名 : public 基类名{成员说明列表
}

说明:

1.派生类名指的是新构造的模块,基类名是基础模块,派生类是以基类为基础发展形成的;

2. public表示的是基类的接口被继承到派生模块后将被提升为派生类的对外接口
3. 成员说明列表指的是派生模块里除了继承模块外新加的成员。
4. 基类声明的公有成员和保护成员在派生类中**保持原有访问属性**;基类声明的私有成员在派生类中不可访问,仍然为基类私有。

代码:

单继承!

#include<bits/stdc++.h>using namespace std;class base{private:int b_num;public:///无参构造函数base(){}///有参构造函数base(int i):b_num(i){}int getbnum(){return b_num;}int setnum(int x){b_num=x;}void showbnum(){cout<<b_num<<endl;}~base(){}
};
///定义的继承派生关系,没有添加新成员
///公有继承,基类的对外接口继承下来成为派生类的对外接口
class derived:public base{
};int main(){cout<<"测试基类性质"<<endl;base b;cout<<b.getbnum()<<endl;b.setnum(500);cout<<b.getbnum()<<endl;cout<<"基类base的对象大小为"<<sizeof(b)<<endl;cout<<"测试派生类性质"<<endl;derived d;cout<<d.getbnum()<<endl;d.setnum(555);cout<<d.getbnum()<<endl;cout<<"派生类derived的对象大小为"<<sizeof(d)<<endl;///cout<<d.b_num; 没有访问权限return 0;
}

多继承!

#include<bits/stdc++.h>using namespace std;class A{private: int a;public: int puba;public:void showa(){cout<<a<<endl;}int geta(){return a;}
};class B{private: int b;public: int pubb;public:void showb(){cout<<b<<endl;}int getb(){return b;}
};///公有继承下类C有6个接口成员
class C: public A, public B{};int main(){C e;cout<<e.geta()<<endl;cout<<e.puba<<endl;cout<<e.pubb<<endl;cout<<e.getb()<<endl;///e.A::getb();e.showa();e.showb();return 0;
}

说明:

​ 1.公有继承下类C有6个接口成员:类A的puba showa() geta() ,类B的pubb showb() getb()

​ 2.可以理解为类C中含有类A的一个无名对象和类B的一个无名对象,所以

e.getb();
e.B::getb();

其实是等价的,但是为了方便一般写第一种。

(如果有二义性的话就要格外讨论了,后续会介绍)

派生模块的构造和析构

派生模块的成员构成和构造规则

以下面的代码为例

class C:public A,public B{private:int c;Clock time;public:int get_c(){return c;}
}

借助之前生成无名对象的思想,我们可以分析得到派生类C中含有四个数据成员,分别的类A的无名对象,类B的无名对象,c和Clock类的对象time

派生模块的构造

类的构造函数的作用是创建对象时初始化对象。若类的设计者没有定义构造函数,创建
对象时,系统自动生成一个默认构造函数,但该默认构造函数不能将对象初始化。如果设计
者定义了构造函数,系统就不会自动生成默认构造函数,而是调用设计者定义的构造函数。
派生类继承了基类所有的数据成员,自己又添加了新成员,所以派生类对象的构造函数由二
部分构成。一部分用来初始化继承的基类成员,一部分用来初始化新添加的成员。初始化继
承的基类成员是通过调用基类的构造函数实现的。如果用户没有定义派生类的构造函数,在
创建派生类对象时,系统自动生成一个默认构造函数,该构造函数调用基类的无参构造函数。

构造函数就是将其成员全部构造出来并且按照规则和结构进行组装。

简明扼要的语法定义就是:

/**
模块名(参数列表):初始化列表中构造出模块的要素{将构造出的模块进行组装
}
**/

代码如下:

C(int aa,int bb,int cc,int hh,int mm,int ss):A(aa),B(bb),c(cc),time(hh,mm,ss){cout<<"类C的构造函数"<<endl;
}
//A(aa),B(bb)可以借助上述提到的无名对象进行理解

派生模块的析构

析构函数是对象消亡时,为进行一些必要的清理工作,系统自动执行的函数。用户一般
不必定义类的析构函数,系统会自动生成一个析构函数。但在某些情况下,用户需要定义析
构函数,完成一些特殊的清理工作。
派生类析构函数的定义与没有继承关系的普通类的析构函数的定义相同。在执行派生类
的析构函数时,系统自动调用基类的析构函数。派生类析构函数的调用顺序与构造函数的调
用顺序正好相反,即:先调用派生类的析构函数,再调用对象成员的析构函数,最后调用基
类的析构函数。

代码如下:

~C(){cout<<"类C的析构函数"<<endl;
}

完整代码将不再做赘述。

继承方式和派生模块成员的对外可见性

前言:

需要先明确一点:继承和权限是两回事,先继承,再重新定义对外权限。

访问权限都是定义的可见成员的访问权限,比如基类中的public成员,在派生模块中可以定义为public,也可以定义为private。但是基类中的private成员,是无法定义权限的,因为其本身就不可见,对其进行权限的定义是不符合语法的。

派生模块的新定义成员与同名覆盖:

我们假设类C是由public A,public B派生而来。

如果此时类A和类B里有同名函数,直接用类C的对象e调用该函数是不可行的,这就是二义性,值得注意的是,二义性与函数重载并不相同。

但是,如果我们在函数前加预作用符来说明这是属于类C的哪一个基类,就是可行的。

e.show();///不合法
e.A::show();///合法

还要知道的一点是,如果我们设类A的show函数是public成员,而类B的show函数是private成员,理论上来说这是没有歧义的,因为类B的show成员根本就不可见。但是!编译器并不会区分是public还是private成员,只要是函数名相同的就是二义性。

如果我们在类C里定义一个新的同名show函数,这个新的函数就会覆盖旧的,但是仍然可以通过预作用符来调用旧的同名函数。

比如这样:

class C: public A, public B{public:///只要是同名 新的就覆盖旧的void show(){cout<<"CCCCCCC"<<endl;}
};

继承方式和派生模块成员的对外可见性

访问属性:

(这是偷的图,侵删致歉)

继承方式

类成员有 public(公有)、protected(保护)和 private(私有)三种访问属性。在类的内
部对各种属性的成员均可直接访问。在类的外部通过类的对象,只能直接访问类的公有成员,
类的保护成员与私有成员不可访问。
在类的派生过程中,派生类对基类的继承相应地也有 public(公有)、protected(保护)
和 private(私有)三种继承方式。派生类接收基类成员成为派生类成员时,可以改变基类成
员在派生类中的访问属性。派生类中基类成员的访问属性由基类成员声明的属性和派生方式
共同决定。具体访问规则是:
(1)公有继承方式
基类声明的公有成员和保护成员在派生类中保持原有访问属性;基类声明的私有成员在
派生类中不可访问,仍然为基类私有。
(2)保护继承方式
基类声明的公有成员和保护成员在派生类中都变成保护成员;基类声明的私有成员在派
生类中不可访问,仍然为基类私有。
(3)私有继承方式
基类声明的公有成员和保护成员在派生类中变成私有成员;基类声明的私有成员在派生
类中不可访问,仍然为基类私有。
类的保护成员和私有成员在不涉及继承关系时可认为是等价的,但有继承关系存在时,
二者是有区别的。通过上面的访问规则可以看出私有成员和保护成员的区别。无论哪种继承
方式,基类的私有成员在派生类中仍为基类私有,成为派生类不可访问的成员。基类的保护
成员可成为派生类的保护成员或私有成员,在派生类的内部可以访问。

保护继承

希望某成员能够被继承到子类里,并且还不作为对外访问的接口,这种访问权限就是protected.

protected访问权限的本意就是当前成员可以被继承到派生类里,但是不能作为派生类的对外接口,此访问权限介于public和private中间。


未完待续,实在是写不下去了

面向对象——继承与派生相关推荐

  1. Python之面向对象继承和派生

    Python之面向对象继承和派生 什么是继承: 继承是一种创建新的类的方法.在Python中,新建的类可以继承自一个或多个父类.原始类称为基类或超类. 新建的类称为派生类或子类. Python中类的继 ...

  2. C++面向对象 - 继承、派生和多态

    公有继承 -- 学生信息类 任务描述 本关任务:采用公有继承设计学生信息类. 相关知识 继承 继承是使代码可以复用的重要手段,也是面向对象程序设计的核心思想之一.简单的说,继承是指一个对象直接使用另一 ...

  3. 12.面向对象(继承/super/接口/抽象类)

    面向对象 继承与派生 继承 继承顺序 继承原理 子类调用父类的方法(super) 组合 接口 接口的概念: 接口的概念解释和使用: python中的接口: 抽象类 面向对象 继承与派生 继承 什么是继 ...

  4. 程序设计与算法三~C++面向对象程序设计~北大郭炜MOOC学习笔记~第五章:继承与派生(新标准C++程序设计)

    以下内容为笔者手打,望读者珍惜,如有转载还请注明. 第五章 继承与派生 $5.1 继承与派生的概念 $5.1.1 基本概念     在C++中,当定义一个新的类B时,如果发现类B拥有某个已经写好的类A ...

  5. 面向对象 - 继承/组合 - 总结

    面向对象 - 继承:1.继承: 类与类之间的关系 什么是什么的关系 eg:人是动物 狗是动物 功能: 解决代码重用问题, 创建新类的方式, 类: 可继承一个或多个父类: 父类 == 基类/超类 类 = ...

  6. C++(22)--继承和派生

    继承和派生 1.基本概念 2.实现公有继承 3.私有继承的例子 4. 继承和组合 <老九学堂C++课程><C++ primer>学习笔记.<老九学堂C++课程>详情 ...

  7. 模块的封装之C语言类的继承和派生

    [交流][微知识]模块的封装(二):C语言的继承和派生 在模块的封装(一):C语言的封装中,我们介绍了如何使用C语言的结构体来实现一个类的封装,并通过掩码结构体的方式实 现了类成员的保护.这一部分,我 ...

  8. c语言继承与派生作用,C++中继承与派生是如何实现的?

    面向对象编程的主要目的之一就是提供可重用的代码,强调可重用性.当我们在面临一个大的工程的时候,一般都会重用以前的代码,首先我们使用现有的代码可以节省编码时间,我们称重复的编码为重复的造轮子,重复的代码 ...

  9. C++类的继承与派生

    文章目录 一.继承 二.基类和派生类 三.继承方式 六.多继承 七.应用经验 八.课后作业 九.版权声明 一.继承 继承是面向对象程序设计中最重要的一个概念.继承允许我们根据一个类来定义另一个类,达到 ...

最新文章

  1. php判断网页编码,python判断网页编码的方法
  2. 模糊测试(fuzz testing)介绍(一)
  3. 限制会话id服务端不共享_会话控制 - able-woman - 博客园
  4. Navicat连接MySQL8.0出现乱码的解决方案
  5. mybaits四-2:模糊查询
  6. wget命令出现Unable to establish SSL connection.错误
  7. 2021-01-28 粒子群优化算法-Python版本和Matlab函数 particleswarm 调用
  8. 自己发现的数学规律一
  9. OpenCV中6种访问Mat元素的方法
  10. Service Worker的应用
  11. 理想汽车市值逼近蔚来,王兴曾多次在饭否为其站台
  12. linux下mysql5.7创建用户_Linux下mysql5.7 创建、删除用户与授权
  13. 最小公倍数和最大公约数的简洁写法
  14. coin3d碰撞检测的实现
  15. 卡尔加里大学计算机世界排名,2020年卡尔加里大学计算机科学专业本科申请条件-学费-世界排名...
  16. Lua_第28章 资源管理(下)
  17. android ADB 模拟手机点击事件
  18. 高级软件工程第三次作业:数独游戏界面功能
  19. petalinux 1144文档 安装流程
  20. 网页看视频,加速敢看的技巧

热门文章

  1. Minecraft我的世界原版云服务器配置
  2. Sitecore 随笔
  3. 大厂实践|Apache Pulsar 消息队列在拉卡拉的应用
  4. 百度闲聊对话机器人Plato-1、2、XL
  5. 多项目与项目组合管理专家胡立
  6. astmb348标准查询_ASTM B381-2013
  7. 激光slam坐标系和视觉slam坐标系对齐,两个slam系统之间坐标对齐,轨迹对齐,时间戳对齐
  8. python安装opencv模块踩过的坑
  9. 2021,大润发的手牌只剩阿里?
  10. 京东CTO张晨:用技术迎接第四次零售革命