当前位置:首页 > 技术知识 > 正文内容

c++ 继承简介(c++继承的概念)

maynowei10个月前 (08-03)技术知识160

24.1 — 继承简介

2024 年 6 月 5 日

在上一章中,我们讨论了对象组合,即从更简单的类和类型构建复杂类。对象组合非常适合构建与其部分具有“has-a”关系的新对象。但是,对象组合只是 C++ 允许您构建复杂类的两种主要方式之一。第二种方式是通过继承,它模拟了两个对象之间的“is-a”关系。

与对象组合(通过组合和连接其他对象来创建新对象)不同,继承是通过直接获取其他对象的属性和行为,然后扩展或专门化它们来创建新对象。与对象组合一样,继承在现实生活中无处不在。当你受孕时,你继承了父母的基因,并从他们两人那里获得了身体属性——但随后你又在上面添加了自己的个性。技术产品(计算机、手机等)继承了其前身的特性(通常用于向后兼容)。例如,英特尔奔腾处理器继承了英特尔 486 处理器定义的许多特性,而英特尔 486 处理器本身又继承了早期处理器的特性。C++ 从其所基于的语言 C 继承了许多特性,而 C 从它之前的编程语言继承了许多特性。

以苹果和香蕉为例。虽然苹果和香蕉是不同的水果,但它们的共同点是它们都是水果。而且由于苹果和香蕉是水果,简单的逻辑告诉我们,任何适用于水果的事情也适用于苹果和香蕉。例如,所有水果都有名称、颜色和大小。因此,苹果和香蕉也有名称、颜色和大小。我们可以说苹果和香蕉继承(获得)了水果的所有属性,因为它们水果。我们还知道水果要经过成熟过程才能食用。因为苹果和香蕉是水果,所以我们还知道苹果和香蕉会继承成熟的行为。

用图表来表示的话,苹果、香蕉和水果之间的关系可能看起来像这样:

该图定义了一个层次结构。

层次结构

层次结构是一种显示各种对象如何关联的图表。大多数层次结构要么显示随时间推移的进展(386 -> 486 -> Pentium),要么以从一般到具体的方式对事物进行分类(水果 -> 苹果 -> 蜜脆)。如果您学过生物学,那么著名的领域、界、门、纲、目、科、属和物种排序定义了一个层次结构(从一般到具体)。

这是层次结构的另一个示例:正方形是矩形,矩形是四边形,四边形是一种形状。直角三角形是三角形,三角形也是一种形状。将其放入层次结构图中,如下所示:

该图从一般(顶部)到具体(底部),层次结构中的每个项目都继承了其上方项目的属性和行为。

展望未来

在本章中,我们将探讨 C++ 中继承工作原理的基础知识。

下一章,我们将探讨继承如何通过虚函数实现多态性(面向对象编程的流行语之一)。

随着我们的进展,我们还将讨论继承的主要好处以及一些缺点。

在上一章中,我们讨论了对象组合,即通过组合和连接其他类和类型来构建复杂的类。对象组合非常适合构建与其部分具有“拥有”关系的新对象。然而,对象组合只是C++允许你构建复杂类的两种主要方式之一。第二种方式是通过继承,它在两个对象之间模拟“是一种”的关系。

与涉及通过组合和连接其他对象来创建新对象的对象组合不同,继承涉及通过直接获取其他对象的属性和行为,然后扩展或专门化它们来创建新对象。与对象组合一样,继承在现实生活中无处不在。当你被孕育时,你从父母那里继承了基因,并从他们那里获得了身体特征——但后来你在上面添加了自己的个性。科技产品(计算机、手机等)从其前身继承特性(通常用于向后兼容)。例如,英特尔奔腾处理器继承了许多由英特尔486处理器定义的特性,而英特尔486处理器本身又从早期处理器继承了许多特性。C++从C语言继承了许多特性,C语言是基于它的编程语言,而C语言又从前面的编程语言继承了许多特性。

考虑苹果和香蕉。尽管苹果和香蕉是不同的水果,但它们都有一个共同点,那就是它们都是水果。因为苹果和香蕉是水果,简单的逻辑告诉我们,所有关于水果的事实也适用于苹果和香蕉。例如,所有的水果都有名称、颜色和大小。因此,苹果和香蕉也有名称、颜色和大小。我们可以说苹果和香蕉继承(获得)了水果的所有属性,因为它们是水果。我们还知道,水果会经历一个成熟过程,从而变得可食用。因为苹果和香蕉是水果,我们也知道苹果和香蕉将继承成熟的特性。

将其放入图表中,苹果、香蕉和水果之间的关系可能如下所示:

水果
|
|--- 苹果
|--- 香蕉

在这个图表中,水果类位于顶部,苹果和香蕉类继承自它。这表示水果与苹果/香蕉之间的“是一种”的关系。就像在例子中一样,水果类中定义的任何属性或方法都将被苹果和香蕉类继承。

现在让我们看看这在C++中是如何应用的:

class Fruit {
public:
    std::string name;
    std::string color;
    int size;

    void ripen() {
        // 成熟逻辑在这里
    }
};

class Apple : public Fruit {
    // 苹果特有的附加属性或方法
};

class Banana : public Fruit {
    // 香蕉特有的附加属性或方法
};

在这个C++示例中,苹果和香蕉类都使用:符号后跟public关键字继承自水果类,这表示公共继承。这意味着水果类中的所有公共和保护成员都可以在派生类(苹果和香蕉)中访问。

现在你可以创建苹果和香蕉类的对象,并访问水果类中定义的属性和方法:

Apple apple;
apple.name = "Apple";
apple.color = "Red";
apple.size = 100;
apple.ripen();

Banana banana;
banana.name = "Banana";
banana.color = "Yellow";
banana.size = 150;
banana.ripen();

通过使用继承,你可以创建更专业的类,同时重用基类中定义的属性和行为,从而促进代码的重用和组织。

Status DB::Open(const Options& options, const std::string& dbname, DB** dbptr) {
  *dbptr = nullptr;

  DBImpl* impl = new DBImpl(options, dbname);
  impl->mutex_.Lock();
  VersionEdit edit;
  // Recover handles create_if_missing, error_if_exists
  bool save_manifest = false;
  Status s = impl->Recover(&edit, &save_manifest);
  if (s.ok() && impl->mem_ == nullptr) {
    // Create new log and a corresponding memtable.
    uint64_t new_log_number = impl->versions_->NewFileNumber();
    WritableFile* lfile;
    s = options.env->NewWritableFile(LogFileName(dbname, new_log_number),
                                     &lfile);
    if (s.ok()) {
      edit.SetLogNumber(new_log_number);
      impl->logfile_ = lfile;
      impl->logfile_number_ = new_log_number;
      impl->log_ = new log::Writer(lfile);
      impl->mem_ = new MemTable(impl->internal_comparator_);
      impl->mem_->Ref();
    }
  }
  if (s.ok() && save_manifest) {
    edit.SetPrevLogNumber(0);  // No older logs needed after recovery.
    edit.SetLogNumber(impl->logfile_number_);
    s = impl->versions_->LogAndApply(&edit, &impl->mutex_);
  }
  if (s.ok()) {
    impl->RemoveObsoleteFiles();
    impl->MaybeScheduleCompaction();
  }
  impl->mutex_.Unlock();
}

相关文章

Flutter 之 ListView(flutter框架)

在 Flutter 中,ListView 可以沿一个方向(垂直或水平方向)来排列其所有子 Widget,常被用于需要展示一组连续视图元素的场景ListView 构造方法ListView:仅适用于列表中...

Android指示器,轮播与循环轮播(android轮播图代码)

Android UI Libs之CircleIndicator1. 说明CircleIndicator,顾名思义,圆形指示器,只一个可以用来做轮播的第三方库。2. 配置在模块的build.gradle...

Shopee新手指南:Shopee卖家中心用户界面介绍

1.Shopee各站点前台网页链接:2.Shopee各站点后台网页链接3.Shopee APP下载:安卓版下载链接:https://pan.baidu.com/s/1eSp8M1k#list/path...

如何优雅地使用嵌入式事件标志组?

事件标志组嵌入式事件标志组是一种在嵌入式系统中广泛使用的同步机制,主要用于实现多任务间的同步与通信。事件标志组是一组事件标志位的集合,每个位代表一个事件是否发生。它允许任务等待特定的事件发生,当事件发...

Go 语言中的 RWMutex 源码解析、使用场景及应用分析

Go 语言标准库的 sync 包提供了一些非常重要的并发原语来帮助程序开发者处理并发任务。本文将详细解析 sync 包中的 RWMutex,即读写互斥锁(Reader/Writer Mutex),并结...

Go语言进阶:时间轮(golang时间轮)

时间轮概念时间轮(Timing Wheel)是一种高效的定时任务调度数据结构,特别适合处理大量定时任务。它通过一个循环数组(轮盘)和多个槽位(buckets)来组织定时任务,每个槽位代表一个时间间隔。...