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

c++继承详解

从这篇文章开始,我们正式进入c++进阶篇章

继承的概念及定义

概念

继承(inheritance)机制是⾯向对象程序设计使代码可以复⽤的最重要的⼿段,它允许我们在保持原有 类特性的基础上进⾏扩展

通俗来讲就是:父亲的遗产传给自己的子女,由子女去使用

增加⽅法(成员函数)和属性(成员变量),这样产⽣新的类,称派⽣类。

这个所谓的派生类就是上面提到过的子女

继承定义

定义格式

class 派生类(子类):public  基类(父类)

                            这里的public是继承方式

{
语句;

}

继承基类(父类)成员访问方式的变化

1.基类的私有成员在派生类中无法访问。

2.基类private的成员不能在派生类中不能被直接访问,需要在派生类中定义为protected才能被访问。

3.使⽤关键字class时默认的继承⽅式是private,使⽤struct时默认的继承⽅式是public,不过最好显 ⽰的写出继承⽅式。

4.在实际运⽤中⼀般使⽤都是public继承,⼏乎很少使⽤protetced/private继承,也不提倡使⽤ protetced/private继承,因为protetced/private继承下来的成员都只能在派⽣类的类⾥⾯使⽤,实 际中扩展维护性不强。

继承中的作用域

隐藏规则

1. 在继承体系中基类和派⽣类都有独⽴的作⽤域。

2. 派⽣类和基类中有同名成员,派⽣类成员将屏蔽基类对同名成员的直接访问,这种情况叫隐藏。

3. 需要注意的是如果是成员函数的隐藏,只需要函数名相同就构成隐藏。

当然啦,在实际中在继承体系⾥⾯最好不要定义同名的成员。

派生类的默认成员

4个常⻅默认成员函数

默认的成员函数就是指不需要我们去编写的函数,编译器会自动生成的成员函数

1. 派⽣类的构造函数必须调⽤基类的构造函数初始化基类的那⼀部分成员。如果基类没有默认的构造 函数,则必须在派⽣类构造函数的初始化列表阶段显⽰调⽤。

2. 派⽣类的拷⻉构造函数必须调⽤基类的拷⻉构造完成基类的拷⻉初始化。

3.派⽣类的operator=必须要调⽤基类的operator=完成基类的复制。但需要注意的是派生类的operator= 隐藏了基类的operator=,因此要显式调用基类的operator= 时,需要指定基类作用域

4. 派⽣类的析构函数会在被调⽤完成后⾃动调⽤基类的析构函数清理基类成员。

实现一个不能被继承的类

⽅法1:基类的构造函数私有,派⽣类的构成必须调⽤基类的构造函数,但是基类的构成函数私有化以 后,派⽣类看不⻅就不能调⽤了,那么派⽣类就⽆法实例化出对象。

方法2: :C++11新增了⼀个final关键字,final修改基类,派⽣类就不能继承了。

继承与友元

友元关系不能继承,也就是说基类友元不能访问派⽣类私有和保护成员 。

由此可见有缘关系不能继承

继承与静态成员

基类定义了static静态成员,则整个继承体系⾥⾯只有⼀个这样的成员。⽆论派⽣出多少个派⽣类,都 只有⼀个static成员实例。

class Person

{

public:

string _name;

static int _count;

};

int Person::_count = 0;

class Student : public Person

{

protected:

int _stuNum;

};

int main()

{

Person p;

Student s;

// 这⾥的运⾏结果可以看到⾮静态成员 _name 的地址是不⼀样的

// 说明派⽣类继承下来了,⽗派⽣类对象各有⼀份

cout << &p._name << endl;

cout << &s._name << endl;

// 这⾥的运⾏结果可以看到静态成员 _count 的地址是⼀样的

// 说明派⽣类和基类共⽤同⼀份静态成员

cout << &p._count << endl;

cout << &s._count << endl;

// 这⾥的运⾏结果可以看到⾮静态成员 _name 的地址是不⼀样的

// 说明派⽣类继承下来了,⽗派⽣类对象各有⼀份

cout << &p._name << endl;

cout << &s._name << endl;

// 这⾥的运⾏结果可以看到静态成员 _count 的地址是⼀样的

// 说明派⽣类和基类共⽤同⼀份静态成员

cout << &p._count << endl;

cout << &s._count << endl;

return 0;

}

多继承及其菱形继承问题

继承模型

单继承

单继承:⼀个派⽣类只有⼀个直接基类时称这个继承关系为单继承

举个例子

这个就是单继承

多继承

多继承:⼀个派⽣类有两个或以上直接基类时称这个继承关系为多继承

值得一提的是多继承对象在内存中的模型, 它的模型是先继承的基类在前⾯,后⾯继承的基类在后⾯,派⽣类成员在放到最后⾯

那么接下来讲一下一种特殊的继承模型

菱形继承

菱形继承是多继承的⼀种特殊情况。

菱形继承的问题,从下⾯的对象成员模型构造,可以 看出菱形继承有数据冗余和⼆义性的问题,在Assistant的对象中Person成员会有两份。⽀持多继承就 ⼀定会有菱形继承,像Java就直接不⽀持多继承,规避掉了这⾥的问题,所以实践中我们也是不建议 设计出菱形继承这样的模型的。

虚继承

class Person

{

public:

string _name; // 姓名

/*int _tel;

int _age;

string _gender;

string _address;

*/

// ...

}; // 使⽤虚继承 Person 类

class Student : virtual public Person

{

protected:

int _num; // 学号

}; // 使⽤虚继承 Person 类

class Teacher : virtual public Person

{

protected:

int _id; // 职⼯编号

};

// 教授助理

class Assistant : public Student, public Teacher

{

protected:

string _majorCourse; // 主修课程

};

int main()

{

// 使⽤虚继承,可以解决数据冗余和⼆义性

Assistant a;

a._name = "peter";

return 0;

}

继承和组合

public继承是一种is-a的关系,即每个派生类对象都素一个基类对象

组合是一种has-a的关系,假设b组合了a,每个b对象中都有一个a对象

都看到这里了,各位观众老爷给个三联呗,谢谢啦!!!

相关文章:

  • 【数据结构】栈和队列(Stack Queue)
  • 使用Python免费将pdf转为docx
  • TypeScript 设计模式之【建造者模式】
  • C语言指针系列1——初识指针
  • 《算法岗面试宝典》正式发布
  • 生成式语言模型底层技术面试
  • 计算机网络发展
  • 极狐GitLab 17.4 重点功能解读【四】
  • Xcode16 iOS18 编译问题适配
  • Vue3+Element-UI Plus登录静态页
  • Vue极简入门
  • 【达梦数据库】存储过程统计模式下表信息-SQL改写
  • 微服务架构拆分策略与实践
  • 前后端分离集成CAS单点登录
  • Redis配置文件详解(上)
  • 自己简单写的 事件订阅机制
  • [译]CSS 居中(Center)方法大合集
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  •  D - 粉碎叛乱F - 其他起义
  • echarts的各种常用效果展示
  • JavaScript函数式编程(一)
  • JavaScript设计模式与开发实践系列之策略模式
  • javascript数组去重/查找/插入/删除
  • java多线程
  • JSDuck 与 AngularJS 融合技巧
  • Netty 框架总结「ChannelHandler 及 EventLoop」
  • Web Storage相关
  • webgl (原生)基础入门指南【一】
  • 前端_面试
  • hi-nginx-1.3.4编译安装
  • RDS-Mysql 物理备份恢复到本地数据库上
  • 国内唯一,阿里云入选全球区块链云服务报告,领先AWS、Google ...
  • 通过调用文摘列表API获取文摘
  • ​LeetCode解法汇总1276. 不浪费原料的汉堡制作方案
  • ​什么是bug?bug的源头在哪里?
  • #14vue3生成表单并跳转到外部地址的方式
  • (13)Latex:基于ΤΕΧ的自动排版系统——写论文必备
  • (2)nginx 安装、启停
  • (C语言)球球大作战
  • (java)关于Thread的挂起和恢复
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (附源码)springboot太原学院贫困生申请管理系统 毕业设计 101517
  • (附源码)计算机毕业设计ssm基于B_S的汽车售后服务管理系统
  • (图文详解)小程序AppID申请以及在Hbuilderx中运行
  • (五)activiti-modeler 编辑器初步优化
  • (五)c52学习之旅-静态数码管
  • (已解决)vue+element-ui实现个人中心,仿照原神
  • (转)可以带来幸福的一本书
  • (转)我也是一只IT小小鸟
  • .360、.halo勒索病毒的最新威胁:如何恢复您的数据?
  • .htaccess配置常用技巧
  • .net core MVC 通过 Filters 过滤器拦截请求及响应内容
  • .NET Standard / dotnet-core / net472 —— .NET 究竟应该如何大小写?
  • .Net 转战 Android 4.4 日常笔记(4)--按钮事件和国际化
  • .NET下的多线程编程—1-线程机制概述