当前位置: 首页 > news >正文

13.C++:继承

        

目录

一、继承的概念及定义

1.1、继承的概念

1.2、继承的定义

1.2.1、语法形式

1.2.2、继承基类成员访问方式的变化

1.3、继承类模版

二、基类和派生类之间的转换

三、继承中的作用域

3.1、隐藏规则

3.2、练习题

四、派生类的默认成员函数

五、友元与继承

六、静态成员与 继承

七、多继承和菱形继承的问题

7.1、多继承

7.2、菱形继承

7.3、虚继承

八、继承和组合

Note:如何让一个类不能被继承?


        在现实中,我们想拥有财富,无非是靠自己奋斗,或从父辈那里继承。后者显然是一条更轻松的捷径。在C++的世界里,面向对象编程为我们提供了类似的“捷径”——继承。它让一个类能够直接从另一个类获取已有的属性和方法,无需一切从零开始,这避免了“重复发明轮子”,真正实现了“站在巨人的肩膀上”进行开发。本篇博客将为你详细解读C++的继承机制。

一、继承的概念及定义

1.1、继承的概念

        继承机制是面向对象程序设计使代码可以重复使用的一种手段。继承是类设计层次的复用。

比如:学校管理系统。学校里面有学生,老师,职工,这三类有个共同特点:都是人。所以记录它们信息的时候有一部分是必然重叠的(姓名,年龄,性别等)那么我们可以专门创建一个 person 类,然后再创建student ,teacher,worker 三个类,让这三个类去继承 person 这个类就好了。

        对于被继承的类,我们称之为 基类(也叫父类),继承别的类的类,称为 派生类(也叫子类)

1.2、继承的定义

1.2.1、语法形式

        在派生类名后加个 : ,然后接着继承方式,基类就可以了。

        继承方式有三种:

1.2.2、继承基类成员访问方式的变化

public继承protected继承private继承
基类的public成员派生类的public成员派生类的protected成员派生类的private成员
基类的protected成员派生类的protected成员派生类的protected成员派生类的private成员
基类的private成员派生类不可见派生类不可见派生类不可见

Note:基类的私有成员,在派生类中不可见,语法上限制不让用。对于如此庞杂的局面,我们只需要记住 public > protected > private 就可以了。基本上,我们使用的都是公有继承。

Note:使用关键字 class,默认继承方式为 private,使用 struct 默认继承方式为 public,不过最好还是显式写出继承方式

1.3、继承类模版

        模版是按需实例化,调用到哪个成员函数,就实例化哪个成员函数,所以必须要指定!

        说人话就是,在派生类中调用基类成员时,需要在前面用 :: 指定是哪个类型的

二、基类和派生类之间的转换

        大家都知道,在普通对象之间的类型转换时,会产生一个临时的中间变量,而该临时变量具有常性。但是,基类和派生类不是这样的,派生类给基类的引用或指针赋值,不会产生临时变量

        如图,派生类给基类的引用或指针赋值,该引用或指针会直接截取本来自己有的那部分,不会产生临时变量。但是,只能是派生类赋值给基类的引用和指针,基类不能给派生类。(子可以给父,父不能给子)

三、继承中的作用域

3.1、隐藏规则

(1)基类和派生类都有独立的作用域

(2)如果基类和派生类中有同名成员,派生类会直接屏蔽掉对基类的成员访问

(3)如果是同名函数,只要函数名字相同,就隐藏(不管参数和返回类型),也就是说,没有重载这个说法了

(4)最好不要定义同名成员

3.2、练习题

(1)下面 A 和 B 类中的两个 func 构成什么关系?   B

        A.重载        B.隐藏        C.没关系

(2)下面程序的编译运行结果是什么? A

        A.b编译报错        B.运行报错        C.正常运行

        首先,A 是基类,B是派生类,由于两个成员函数的函数名是相同的,所以构成了隐藏关系,在派生类对象中调用 func 会直接隐藏基类的 func ,所以 版本 b.func() 不传任何参数就会报错。

四、派生类的默认成员函数

        派生类的成员变量 = 自己的成员变量 + 基类的成员变量

       自己的成员变量就跟普通类的成员变量一样,该咋滴就咋地。对于基类的成员变量,在调用派生类构造时,它会自动调用基类的默认构造(或者你手动调用)

1.派生类的构造函数,必须调用基类的构造函数,初始化基类的那部分成员。如果基类没有默认构造,那就必须在派生类构造函数的初始化时显式调用

2.派生类的拷贝构造函数必须调用基类的拷贝构造

3.派生类的赋值符重载(operator=)必须要调用基类的赋值符重载(operator=)

4.派生类的析构函数会在被调用完后自动调用基类的析构函数,因为这样才能保证派生类对象清理完再清理基类对象的顺序

5.派生类初始化,先调用的是基类的构造函数

6.派生类对象析构,先清理派生类,再清理基类

7.因为多态中一些场景的析构函数需要构成重写,重写的条件之一是函数名先攻,所以编译器会对析构函数的名字进行特殊处理,为 destructor() ,所以基类和派生类的析构函数会构成隐藏关系

五、友元与继承

        友元关系不能继承

六、静态成员与 继承

        基类定义了 static 静态成员,则整个继承体系里,都只有一个这样的成员。也就是说,不管派生出都少个派生类,都只有这一个 static 成员

七、多继承和菱形继承的问题

7.1、多继承

        单继承:一个派生类只有一个直接基类时,称为单继承

        多继承:有两个或两个以上的直接基类

Note:在多继承中,先继承的基类成员放在前面,后继承的基类成员放在后面,最后才是派生类自己的成员

7.2、菱形继承

        比如学校管理系统的研究生,他即是学生,又是助教,所以他会继承学生和助教两个基类。但是,学生和助教都是人,学生会继承人,助教也会继承人,这样会导致最后研究生里面有两个人的信息,造成数据的冗余

7.3、虚继承

        如何解决菱形继承的问题呢?像 Java 直接不支持多继承,避免了菱形继承,而 C++则是提出了一个办法,虚继承。

        虚继承的关键字为: virtual

class Person {
protected:string name;
public:Person(string n) : name(n) {}void introduce() {cout << "我是" << name << endl;}
};// 虚继承
class Student : virtual public Person {
public:Student(string n) : Person(n) {}void study() {cout << name << "在学习" << endl;}
};// 虚继承
class Teacher : virtual public Person {
public:Teacher(string n) : Person(n) {}void teach() {cout << name << "在授课" << endl;}
};// 研究生既是学生又是老师
class GraduateStudent : public Student, public Teacher {
public:GraduateStudent(string n) : Person(n), Student(n), Teacher(n) {}void doResearch() {cout << name << "在做科研" << endl;  // 直接访问,没有二义性}
};

Note:谁的数据会造成冗余和二义性就给谁用,这里肯定是给人用,而不是给老师和学生用

八、继承和组合

        继承和组合本质上都是对类的复用。

继承是一种  is-a 的关系  ,而组合是  has -a 的关系

Note:建议优先使用组合,而不是继承,组合的代码耦合性低,更好维护

Note:如何让一个类不能被继承?

        (1)将构造函数放到私有。

        (2)使用 final 修饰

class Base final
{//……
};

       

恭喜你已经阅读完本篇博客的全部内容,如果有不足和错误,恳请批评和指正,期待我们的下次相会!

http://www.dtcms.com/a/561404.html

相关文章:

  • 做我的世界壁纸网站VPS wordpress 教程
  • 扒下来的网站怎么做修改php做网站访问记录
  • jxWebUI--日期时间选择框
  • Linux防火墙配置:iptables与firewalld使用指南(附案例)
  • 毕业设计网站开发类题目济南营销型网站建设贵吗
  • 网站服务器维护价格wordpress主页链接失效
  • 销售网站建设考核指标旅游网站开发目的6
  • 路由器端口镜像的配置与实验(eNSP)
  • vagrant+virtualBox使用记录
  • c++:析构与异常——noexcept的隐形爆炸
  • JavaEE多线程进阶
  • 网站建设结课总结如何在亚马逊开店流程及费用
  • 学习网页制作的网站如何修改网站源文件
  • 停车场管理|停车预约管理|基于Springboot的停车场管理系统设计与实现(源码+数据库+文档)
  • 计算机网络---ICMP协议(Internet Control Message Protocol,互联网控制消息协议)
  • 网站如何做淘宝客网站做要钱
  • 做公司网站需要什么资料开源手机网站系统
  • 成都网站优化公司哪家好南京哪家网络公司做网站优化好
  • Java 通配符
  • java-learn(9):常见算法,collection框架
  • 海口网站建设维护网校 039 网站建设多少钱
  • 网站建设的频道是什么济南企业网站制作费用
  • 外卖餐饮小程序带商城系统餐桌预定点餐寄存排队等待在线点单程序
  • 广州市公司网站建设价格wordpress播放音乐
  • Onnxruntime源码解析
  • Typescript - type 类型别名(通俗易懂教程)
  • 专业建站lhznkj挂机宝做网站
  • 单位网站建设 管理制度wordpress中文视频插件下载
  • 【ComfyUI】混元3D 2.0 Turbo 多视图生成模型
  • 【SAM】eval_coco.py说明