C++——继承

什么是继承

继承是两个类之间的关系,可以实现派生类(子类)对基类(父类)的复用,即派生类在基类的基础上进行扩展,实现更多功能。例如学生和人这两个对象就可以是继承关系,学生具有人的所有特征,而且学生有人这个类之外的其他特征。

例子:

class Person
{
public:string _name; // 姓名
};class Student : public Person
{
public:string _stuNum; // 学号void study(){cout << _name << '(' << _stuNum <<") is studying~~" << endl;}
};void test()
{Student stu;stu._name = "Mike";stu._stuNum = "1234";stu.study();
}

继承的使用

继承的定义

继承方式 

简单记忆:派生类中继承过来的成员的访问权限,是基类成员的访问权限和继承方式中权限最小的,例如,基类private成员通过public继承,二者中private的权限最小,继承的成员在派生类中就是private成员

final修饰的类不能作基类

class A final{};//class B :public A {
//
//};

public,protected和private成员的区别

public成员在类内外都可以访问

protected成员可以在类内访问,可以在派生类中(派生类以public/protected继承)访问,不能在类外访问

private成员只能在内内访问

注意:

1.继承后,基类的private成员会继承到派生类,只是派生类没有访问权限

2.class的默认继承方式是private,struct的默认继承方式是public,但是最好显式写出继承方式

派生类和基类的赋值兼容转换

基类可以接收派生类的对象和引用;基类的指针可以接收派生类的指针。

一句话说,就是基类可以接收派生类的值,但是派生类不可以接收基类的值。

可以简单理解一下,派生类赋值给基类时,有一部分成员基类没有,所以派生类只把基类中有的赋值给基类,基类中没有的直接丢掉;但是反过来,基类如果赋值给派生类,派生类中有一部分基类没有的成员无法被赋值,就会出现错误。

class A
{};class B : public A
{};int main()
{A a;B b;B& bb = b;A* pa;//基类赋值派生类a = b;a = bb;pa = &b;}

派生类的指针或者引用赋值给基类时,并不会重开一段空间,而且修改指针指向的数据或者引用的数据也会改变派生类的数据。

成员函数的隐藏/重定义

基类和派生类都有自己独立的作用域,如果基类和派生类中有同名的成员函数,注意只需要同名,那么当我们用派生类的对象调用这个函数时,只会调用派生类的函数,基类的函数就被隐藏/重定义了。

class A
{
public:void fun(){cout << "A_fun()" << endl;}
};class B : public A
{
public:void fun(){cout << "B_fun()" << endl;}
};void _test()
{B b;b.fun();//强制访问基类中被隐藏的函数b.A::fun();
}

派生类的默认成员函数

  1. 派生类的构造函数必须调用基类的构造函数来初始化基类中的那一部分成员。如果基类没有默认构造函数,需要在派生类的初始化列表中显式调用基类的构造函数。
  2. 派生类的析构函数会在自身被调用后,调用基类的析构。因为如果派生类的析构函数使用了基类成员,而基类先析构了,就会出现错误。
  3. 由1,2可知,派生类对象定义和销毁会有以下顺序,先构造基类->构造派生类->析构派生类->析构基类
  4. 派生类的拷贝构造函数必须调用基类的拷贝构造函数
  5. 派生类的operator=函数必须调用基类的operator=函数
class Person
{
protected:string _name;
public:Person(const string& s = "xxxxx"):_name(s){cout << "Person()" << endl;}Person(const Person& p):_name(p._name){}Person& operator=(const Person& p){if(this != &p){_name = p._name;}return *this;}~Person(){cout << "~Person" << endl;}
};class Student : public Person
{
protected:string _num;
public:Student(const string& name = "Stuxxx", const string& num = "22335"):Person(name)//参数列表调用基类构造函数,_num(num){cout << "Student()" << endl;}Student(const Student& s):_num(s._num),Person(s)//参数列表调用基类拷贝构造函数{}Student& operator=(const Student& s){if (this != &s){_num = s._num;Person::operator=(s);//调用基类的赋值运算符重载函数}return *this;}~Student(){cout << "~Student()" << endl;}
};

友元的关系不能继承

基类的友元函数不能访问派生类的成员

class Person
{
public:friend void Display(const Person& p, const Student& s);
protected:string _name; // 姓名
};
class Student : public Person
{//friend void Display(const Person& p, const Student& s);
protected:int _stuNum; // 学号
};
void Display(const Person& p, const Student& s)
{cout << p._name << endl;//cout << s._stuNum << endl; 无法访问
}
void main()
{Person p;Student s;Display(p, s);
}

如果友元函数想要访问派生类成员,需要在派生类中声明友元函数 

继承与静态成员

基类中的静态成员,在整个继承体系中只有一个。无论有多少个派生类,都只有一个实例

//统计A构造的次数
class A
{
public:static int count;A() { count++; }
};class B : public A
{};int B::count = 0;void test()
{A a;B b;cout << B::count;//2
}

菱形继承

菱形继承发生在多继承中,如果一个类继承了多个类,而且这些类中有2个或2个以上都继承了同一个基类,这种情况就是菱形继承。

菱形继承会产生两个问题:数据冗余和二义性

D这个类中有两个A的成员a,造成了数据冗余,同时访问a这个基类成员时,编译器不知道要使用哪一个,调用不明确,有二义性问题。

那么如何解决这些问题呢?——虚拟继承

使用方法很简单,在继承最开始的基类的继承方式的前面加上virtual关键字,对应这个例子中就是在B,C两个类继承A时,加上virtual。

class A{};class B : virtual public A{};class C : virtual public A{};class D : public B, public C{};

虚拟继承原理

虚拟继承后,派生类不会直接存储基类成员,而是储存了一个虚基表(用来存储偏移量)的地址,当我们要访问a这个基类成员时,会通过偏移量找到a的地址访问。 

继承和组合

继承是一种is-a的关系,派生类is-a基类

组合是一种has-a的关系,比如汽车有一个轮胎

// Car和BMW Car和Benz构成is-a的关系class Car{protected:string _colour = "白色"; // 颜色string _num = "陕ABIT00"; // 车牌号};class BMW : public Car{public:void Drive() {cout << "好开-操控" << endl;}};class Benz : public Car{public:void Drive() {cout << "好坐-舒适" << endl;}};// Tire和Car构成has-a的关系class Tire{protected:string _brand = "Michelin";  // 品牌size_t _size = 17;     // 尺寸};class Car{protected:string _colour = "白色"; // 颜色string _num = "陕ABIT00"; // 车牌号Tire _t; // 轮胎};

继承和组合是不同的代码复用方式:

继承是一种白箱复用,基类的实现细节对于派生类是可见的,一定程度上破坏了封装性,对基类的改变会对派生类造成不小的影响,代码维护难

组合是一种黑箱复用,被组合的类的实现对于外部类是不可见的,这种复用未破坏封装性,代码耦合度低,组合类之间没有很强的依赖关系,代码维护相对简单

在实际应用中能用组合就用组合

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/151277.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Dockerfile搭建LNMP

目录 一、基础环境准备 1、环境前期准备 二、部署nginx&#xff08;容器IP 为 172.18.0.10&#xff09; 1、配置Dockerfile文件 2、配置nginx.conf文件 3、构建镜像、启动镜像 三、部署mysql 1、配置Dockerfile文件 2、配置my.conf文件 3、构建镜像、启动镜像 5、验…

【Linux】Vim使用总结

【Linux】Vim使用总结 Vim 的三种模式命令行模式1. 移动2.复制&#xff0c;粘贴&#xff0c;剪切3.撤销4.大小写切换&#xff0c;替换&#xff0c;删除 插入模式底行模式 Vim 的三种模式 一进入VIM就是处于一般模式&#xff08;命令模式&#xff09;&#xff0c;该模式下只能输…

flink双流join结果数据重复问题排查

1.背景 Kafka的两个topic&#xff0c;topic1 为用户下单明细记录&#xff08;包含订单基本信息&#xff09;&#xff0c;topic2为下单渠道记录&#xff08;包含下单来源和渠道内容设备相关的信息&#xff09; &#xff0c;要求实时统计每分钟内所有订单下的渠道来源分布详情。具…

使用Windows系统自带的安全加密解密文件操作步骤详解

原以为安全加密的方法是加密压缩包&#xff0c;有的需要用软件加密文件&#xff0c;可每次想往里面修改或存放文件都要先解密&#xff0c;不用时&#xff0c;还得去加密&#xff0c;操作步骤那么多&#xff0c;那多不方便呀&#xff0c;这里讲讲用系统自带的BitLocker加密工具怎…

【SQL】MySQL中的约束

1. 主键约束&#xff08;primary key&#xff09;&#xff1a; 相当于唯一约束非空约束分为单列主键&#xff0c;多列联合主键&#xff0c;一个表只有一个主键多列联合主键的每列都不能为空 2. 自增长约束&#xff08;auto_increment&#xff09;&#xff1a; 用在单列主键后…

Acwing.889 满足条件的01序列

题目 给定n个0和n个1&#xff0c;它们将按照某种顺序排成长度为2n的序列&#xff0c;求它们能排列成的所有序列中&#xff0c;能够满足任意前缀序列中0的个数都不少于1的个数的序列有多少个。 输出的答案对109&#xff0b;7取模。 输入格式 共一行&#xff0c;包含整数n。 …

10_8C++

X-Mind #include <iostream>using namespace std; class Rect { private:int width;int heigjt; public:void init(int w,int h){width w;heigjt h;}void set_w(int w){width w;}void set_h(int h){heigjt h;}void show(){cout << "矩形的周长" <…

day10.8ubentu流水灯

流水灯 .text .global _start _start: 1.设置GPIOE寄存器的时钟使能 RCC_MP_AHB4ENSETR[4]->1 0x50000a28LDR R0,0X50000A28LDR R1,[R0] 从r0为起始地址的4字节数据取出放在R1ORR R1,R1,#(0x1<<4) 第4位设置为1STR R1,[R0] 写回2.设置PE10管脚为输出模式 G…

okhttp4.11源码分析

目录 一&#xff0c;OKHTTP时序图 二&#xff0c;OKHTTP类图 三&#xff0c;OKHTTP流程图 一&#xff0c;OKHTTP时序图 上图是整个okhttp一次完整的请求过程&#xff0c;时序图里面有些部分为了方便采用了简单的描述&#xff0c;描述了主要的流程&#xff0c;细节的话&#…

基于SSM+Vue的物流管理系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;VueHTML 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 …

Day-06 基于 Docker 安装 Nginx 镜像

1.去官方公有仓库查询nginx镜像 docker search nginx 2.拉取该镜像 docker pull nginx 3. 启动镜像&#xff0c;使用nginx服务&#xff0c;代理本机8080端口(测试是不是好使) docker run -d -p 8080:80 --name nginx-8080 nginx docker ps curl 127.0.0.1:8080

Bridge Champ助力我国桥牌阔步亚运, Web3游戏为传统项目注入创新活力

本届杭州亚运会,中国桥牌队表现杰出,共斩获1金1银1铜佳绩,其中女子团体夺得冠军,混合团体获得亚军。这充分展现了我国桥牌的实力,也彰显了桥牌作为亚运会体育竞技项目的影响力。与此同时,Web3游戏Bridge Champ为传统桥牌项目带来创新模式,将有望推动桥牌运动在亚运舞台上焕发新…

【数据结构】选择排序 堆排序(二)

目录 一&#xff0c;选择排序 1&#xff0c;基本思想 2&#xff0c; 基本思路 3&#xff0c;思路实现 二&#xff0c;堆排序 1&#xff0c;直接选择排序的特性总结&#xff1a; 2&#xff0c;思路实现 3&#xff0c;源代码 最后祝大家国庆快乐&#xff01; 一&#xf…

双字单字拆分/合并操作(博途SCL源代码)

博途PLC的位、字节拆分和合并操作还可以参考下面的文章链接: 博途PLC 位/字/字节 Bit/ Word/Byte拆分与合并_博途的bit-CSDN博客有时候我们需要将分散分布的开关量信号组合为一个整体比如一个字节再完成发送,或者一些报警联锁控制,组合为一个字方便触摸屏报警记录等,下面我…

Python3数据科学包系列(二):数据分析实战

Python3中类的高级语法及实战 Python3(基础|高级)语法实战(|多线程|多进程|线程池|进程池技术)|多线程安全问题解决方案 Python3数据科学包系列(一):数据分析实战 Python3数据科学包系列(二):数据分析实战 Python3数据科学包系列(三):数据分析实战 国庆中秋宅家自省: Pyth…

qt开发从入门到实战2

以下是本人学习笔记 原视频&#xff1a;最新QT从入门到实战完整版|传智教育 qt开发从入门到实战1 练习示例 设计一个按钮&#xff0c;点击时弹出新窗口&#xff0c;再次点击时新窗口关闭 // exerciseQWidget* second_window new QWidget();QPushButton* btn3 new QPushBu…

kafka、rabbitmq 、rocketmq的区别

一、语言不同 RabbitMQ是由内在高并发的erlanng语言开发&#xff0c;用在实时的对可靠性要求比较高的消息传递上。 kafka是采用Scala语言开发&#xff0c;它主要用于处理活跃的流式数据,大数据量的数据处理上 二、结构不同 RabbitMQ采用AMQP&#xff08;Advanced Message Q…

计算机竞赛 题目: 基于深度学习的疲劳驾驶检测 深度学习

文章目录 0 前言1 课题背景2 实现目标3 当前市面上疲劳驾驶检测的方法4 相关数据集5 基于头部姿态的驾驶疲劳检测5.1 如何确定疲劳状态5.2 算法步骤5.3 打瞌睡判断 6 基于CNN与SVM的疲劳检测方法6.1 网络结构6.2 疲劳图像分类训练6.3 训练结果 7 最后 0 前言 &#x1f525; 优…

iTunes更新iOS17出现发生未知错误4000的原因和解决方案

有不少人使用iTunes更新iOS 17时出现「无法更新iPhone发生未知的错误4000」的错误提示&#xff0c;不仅不知道iTunes升级失败的原因&#xff0c;也无从解决iPhone无法更新4000的问题。 小编今天就分享iPhone更新iOS系统出现4000错误提示的原因和对应的解决方案。 为什么iPhone…

Flink学习笔记(二):Flink内存模型

文章目录 1、配置总内存2、JobManager 内存模型3、TaskManager 内存模型4、图形化展示5、实际案例计算内存分配 1、配置总内存 Flink JVM 进程的进程总内存&#xff08;Total Process Memory&#xff09;包含了由 Flink 应用使用的内存&#xff08;Flink 总内存&#xff09;以…