继承【C/C++】

news2024/10/3 10:32:51

目录

一、继承

1、概念 

2、定义

3、继承方式和访问限定符

4、继承中的作用域 

5、基类和派生类对象赋值转换

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

构造

​编辑

析构

友元

静态成员

二、多继承和菱形继承

菱形继承的问题

三、虚拟继承

原理

练习题: 

四、组合与继承

面试题:

一、继承

1、概念 

继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保 持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象 程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,继承是类设计层次的复用

继承是面向对象编程中的一个概念,它允许一个类(子类)继承另一个类(父类)的属性和方法。通过继承,子类可以获得父类的所有公共成员,并且可以根据需要添加自己的成员。

2、定义

class 子类名 : 访问修饰符 父类名 {
    // 子类的成员和方法
};

3、继承方式和访问限定符

基类成员在子类的访问方式 = min(成员在基类的访问限定符,继承方式)(public > protected > private)

也就是说,基类中的private成员在派生类中无论以什么方式继承都是不可见的,不可见是指:基类的私有成员还是被继承到派生类对象中,但语法上限制派生类对象不管是在类里面还是类外面都无法访问。 

基类成员不想在类外直接被访问,但需要在
派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的

使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过
最好显示的写出继承方式。

4、继承中的作用域 

如果基类和派生类有同名成员,则遵循就近原则,也可以加类域来指定。

隐藏/重定义:子类和父类有同名成员,子类成员隐藏了父类成员(只要父子类域中成员函数名相同就构成隐藏)

注意区分重载,重写/覆盖、继承体系里最好不要定义同名成员。  

5、基类和派生类对象赋值转换

切割/切片:

派生类对象可赋值给基类对象,或对象的引用,指针。

int i = 0;
const double& d = i;//从int 到double 会创建一个临时变量。

Person p;
Student s;
Person& rp = s;//与上面不同,这里是切片

 rp 引用了子类中父类的那一部分。

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

构造

派生类的构造函数必须调用基类构造函数初始化基类的那一部分。如果基类没有构造函数,则需在初始化列表阶段显示调用。

Person先初始化,_id后初始化。

拷贝构造:

注意:子类和父类的=构成隐藏,如果不加类域,会优先调自己,就会出现自己调用自己的情况。 

析构

派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员。

子类可能用到父类的成员,如果父类出问题析构了,子类还没析构,去访问父类成员就会出问题。且先构造的后初始化,所以先析构子类,再析构父类。

友元

友元关系不能继承。

静态成员

继承的是使用权。

基类定义了static静态成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子
类,都只有一个static成员实例 。

如何计算Person和它的派生类对象一共创建了多少个?

只需要在父类创建一个静态成员变量,再在父类的构造函数里++即ok。 

二、多继承和菱形继承

多继承:一个子类有两个或以上直接父类时称这个继承关系为多继承

(多继承可以认为是C++的缺陷之一)
菱形继承:菱形继承是多继承的一种特殊情况

菱形继承的问题

数据冗余和二义性

class Person
{
public :
    string _name ; // 姓名
};
class Student : public Person
{
protected :
    int _num ; //学号
};
class Teacher : public Person
{
    protected :
int _id ; // 职工编号
};
class Assistant : public Student, public Teacher
{
protected :
    string _majorCourse ; // 主修课程
};
void Test ()
{
// 这样会有二义性无法明确知道访问的是哪一个
    Assistant a ;
    a._name = "peter";
// 需要显示指定访问哪个父类的成员可以解决二义性问题,但是数据冗余问题无法解决
    a.Student::_name = "xxx";
    a.Teacher::_name = "yyy";
}

三、虚拟继承

虚拟继承可以解决菱形继承的二义性和数据冗余的问题。如上面的继承关系,在Student和
Teacher的继承Person时使用虚拟继承,即可解决问题
 

class Person
{
public :
    string _name ; // 姓名
};
class Student : virtual public Person
{
protected :
    int _num ; //学号
};
class Teacher : virtual public Person
{
protected :
    int _id ; // 职工编号
};
class Assistant : public Student, public Teacher
{
protected :
    string _majorCourse ; // 主修课程
};
void Test ()
{
    Assistant a ;
    a._name = "peter";
}

原理

这里是通过了B和C的两个指针,指向的一张表。这两个指针叫虚基表指针,这两个表叫虚基表。虚基表中存的偏移量。通过偏移量可以找到下面的A

练习题: 

1.c

2.按声明的顺序进行初始化,A对象之会初始化一次(但每个地方的A(sa)都不能省)。

四、组合与继承

继承: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.coloradmin.cn/o/1128430.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

1-07 React配置postcss-px-to-viewport

React配置postcss-px-to-viewport 移动端适配 安装依赖&#xff1a;在项目根目录下运行以下命令安装所需的依赖包&#xff1a; npm install postcss-px-to-viewport --save-dev配置代码 const path require(path);module.exports {webpack: {alias: {: path.resolve(__di…

【lesson14】进程控制之进程终止

文章目录 进程创建结尾写时拷贝 进程终止进程终止时操作系统做了什么&#xff1f;进程终止常见的方式用代码如何终止一个进程&#xff1f; 进程创建结尾 写时拷贝 上个博客在进程创建的时候我们提到了写时拷贝技术&#xff0c;那么到底什么是写时拷贝技术。 通常&#xff0c…

(汇总)系统设计 - 我们如何通俗的理解那些技术的运行原理 - 汇总篇

本心、输入输出、结果 文章目录 &#xff08;汇总&#xff09;系统设计 - 我们如何通俗的理解那些技术的运行原理 - 汇总篇前言分目录相关技术清单相关资料弘扬爱国精神 &#xff08;汇总&#xff09;系统设计 - 我们如何通俗的理解那些技术的运行原理 - 汇总篇 编辑&#xff1…

mount: /dev/sr0 is write-protected, mounting read-only

报错 原因 只有只读权限&#xff0c;没有写权限 解决 在终端中执行以下命令。 id user_name将 user_name 替换为您的用户名以获取您的 uid 然后执行此命令 sudo mount -o rw,uidyour_uid_here /dev/cdrom /mnt将 your_uid 替换为上面找到的用户的 uid。

Python 中的方法重载

本篇文章将通过示例介绍Python中的方法重载及其优点。 Python 中的方法重载 方法重载在 Python 中起着至关重要的作用。 方法有时采用零个参数&#xff0c;有时采用一个或多个参数。 当我们以不同的方式调用同一个方法时&#xff0c;称为方法重载。 Python 并不像其他语言一样…

数字电路与逻辑设计 之 组合逻辑电路

文章目录 组合电路的分析过程组合电路的设计过程电路竞争冒险编码器编码器的应用 组合电路的分析过程 在上面的例子中是 奇校验 功能&#xff0c;怎么改可以变成偶 校验呢 如果是增加一个异或门可以实现吗&#xff0c;答案是不可以&#xff0c;四个异或门也是实现奇校验功能&am…

十八、字符串(3)

本章概要 正则表达式 基础创建正则表达式量词CharSequencePattern 和 Matcherfinde()组&#xff08;Groups&#xff09;start() 和 end()Pattern 标记split()替换操作reset()正则表达式与 Java I/0 正则表达式 很久之前&#xff0c;_正则表达式_就已经整合到标准 Unix 工具…

Linux_虚拟内存机制

虚拟内存是如何工作的 我们的程序中使用的所有地址都是虚拟地址&#xff0c;但实际数据是从磁盘空间缓存在物理内存中&#xff0c;读的还是内存中的数据&#xff0c;所以每次CPU的访存操作都会先将虚拟内存交给CPU中的MMU硬件&#xff0c;利用存在主存&#xff08;实际也可能在…

Towards a Rigorous Evaluation of Time-series Anomaly Detection(论文翻译)

1 Introduction 随着工业4.0加速系统自动化&#xff0c;系统故障的后果可能会产生重大的社会影响&#xff08;Baheti和Gill 2011; Lee 2008; Lee&#xff0c;Bagheri和Kao 2015&#xff09;。为了防止这种故障&#xff0c;检测系统的异常状态比以往任何时候都更加重要&#xff…

python+unittest+requests+HTMLRunner编写接口自动化测试集

问题描述&#xff1a; 搭建接口测试框架&#xff0c;执行用例请求多个不同请求方式的接口 实现步骤&#xff1a; ① 创建配置文件config.ini&#xff0c;写入部分公用参数&#xff0c;如接口的基本url、测试报告文件路径、测试数据文件路径等配置项 1 [DATABASE] 2 data_addre…

QT:编译opencv4.5.3

软件版本 QT&#xff1a;5.9.11 OpenCV 4.5.3 mingw 530&#xff08;32位&#xff09; cmake 3.15.3 下载地址&#xff1a; opencv下载&#xff1a;https://sourceforge.net/projects/opencvlibrary/files/opencv-unix/ cmake下载&#xff1a;https://cmake.org/files/ qt下…

多变量GARCH模型R代码实现

大家好&#xff0c;我是带我去滑雪&#xff01; 多变量GARCH&#xff08;Generalized Autoregressive Conditional Heteroskedasticity&#xff09;模型是一种用于建模多个时间序列变量之间的条件异方差性&#xff08;conditional heteroskedasticity&#xff09;的统计模型。它…

Unity开发之观察者模式(事件中心)

观察者模式是一种对象行为模式。它定义对象间的一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都得到通知并被自动更新。在观察者模式中&#xff0c;主体是通知的发布者&#xff0c;它发出通知时并不需要知道谁是它的观察者&#…

随机森林算法(Random Forest)的二分类问题

二分类问题 1. 数据导入2. RF模型构建2.1 调参&#xff1a;mtry和ntree2.2 运行模型 3. 模型测试4.绘制混淆矩阵5.绘制ROC曲线6. 参考 1. 数据导入 library(dplyr) #数据处理使用 library(data.table) #数据读取使用 library(randomForest) #RF模型使用 library(caret) # 调参…

软件测试之 测试用例 如何设计

在软件开发过程中&#xff0c;测试是一个至关重要的环节&#xff0c;它有助于确保软件的质量和稳定性。而测试用例设计则是测试过程中的一个关键步骤&#xff0c;它帮助测试团队确定如何测试软件以发现潜在的问题和缺陷。本文将介绍测试用例设计的基本概念和步骤&#xff0c;以…

产品研发团队协作神器!10款提效工具大盘点!

在如今科技驱动的时代&#xff0c;产品研发团队面临着前所未有的竞争压力和不断变化的市场需求。为了在这个激烈的环境中脱颖而出&#xff0c;团队需要高效协作并充分利用先进的工具来提高生产力和创新能力。 本文将为你盘点产品研发团队协作必备的10个提效工具&#xff0c;这…

TiDB、MySQL与Oracle的char字段

文章目录 MySQLTiDBOracle结论 我们组在团队内维护了一套TiDB&#xff0c;有时候会有其他同事来请教一些问题&#xff0c;当然遇到比较复杂的问题&#xff0c;我也会直接抛给DBA。今天有个同事来问了一下TiDB的char字段查询是否需要补空格。在我的印象中&#xff0c;TiDB是高度…

【Docker】Docker学习之一:离线安装Docker步骤

前言&#xff1a;基于Ubuntu Jammy 22.04 (LTS)版本安装和测试 1、Docker安装 1.1、离线安装 步骤一&#xff1a;官网下载 docker 安装包 wget https://download.docker.com/linux/static/stable/x86_64/docker-24.0.6.tgz步骤二&#xff1a;解压安装包; tar -zxvf docker…

安防监控视频汇聚平台EasyCVR增加AI算法列表接口的实现方法

安防监控视频汇聚平台EasyCVR基于云边端一体化架构&#xff0c;具有强大的数据接入、处理及分发能力&#xff0c;可提供视频监控直播、云端录像、云存储、录像检索与回看、智能告警、平台级联、云台控制、语音对讲、智能分析等功能。平台既具备传统安防监控的能力&#xff0c;也…

C++进阶语法之函数和指针【学习笔记(三)】

文章目录 1、C 函数1.1 函数的定义1.2 函数原型&#xff08;function prototypes&#xff09;1.3 参数&#xff08;parameter&#xff09;——值传递&#xff08;pass by value&#xff09;1.4 重载&#xff08;overloading&#xff09;1.5 函数传参——传递数组&#xff08;ar…