继承——基类与派生类

简介: 继承——基类与派生类

继承的基本概念

为什么使用继承

我们在使用类的时候常常会遇到以下情况

class  Buddlesort//冒泡排序
{
    int num[30];
    void sort();//排序函数
    void print();//打印函数
};
class  Quicksort//快速排序
{
    int num[30];
    void sort();//排序函数
    void print();//打印函数
};
class  Hillsort//希尔排序
{
    int num[30];
    void sort();//排序函数
    void print();//打印函数
};

我们可以发现,除了具体排序的实现方法,其他元素基本趋于一致,我们可以利用继承对代码进行一定·的优化,代码如下

class Sort
{
    public:
    int num[30];
    void print();//打印函数
};
class  Buddlesort:public Sort//冒泡排序
{
    void sort();//排序函数
};
class  Quicksort:public Sort//快速排序
{
    void sort();//排序函数
};
class  Hillsort:public Sort//希尔排序
{
    void sort();//排序函数
};

我们首先定义基类Sort,里面储存着几个类所共有的元素

class Sort
{
    public:
    int num[30];
    void print();//打印函数
};

再通过继承的方式将这些由派生类所继承,以Quicksort为例

class  Quicksort:public Sort//快速排序
{
    void sort();//排序函数
};

我们可以发现使用继承可以大大简化部分重复代码的书写

继承的一些常用操作

类派生列表

class  Quicksort:public Sort//快速排序
{
    void sort();//排序函数
};

当我们定义派生类要通过派生类列表来指出它是从哪个(些)基类继承过来的,写法如上

动态绑定

在开始这部分的内容之前,我们假设有一家书店,不可避免的会有原价出售的书籍和打折出售后的书籍,我们可以先假设所有书都是原价书籍,定义出一个原价出售书籍的类,代码如下

class Qutoe//原价书籍
{
public:
  string isbn() const;//返回书籍编号
  virtual double net_price(size_t n);
};

在这个类里面我们定义了两个函数

1.string isbn() const用于返回图书的编号

2.net_price(size_t n)用于返回书籍的实际售价,但是值得关注的是,基类里面该函数在返回类型前加上了virtual,这是将基类里面的该函数定义成了虚函数,虚函数将会在后面详细的介绍,在这里仅对它的功能做简单的介绍:

大家可以想一下,虽然基类和后面可能会有的派生类里面这个函数的功能都会是返回书籍的当前价格,但是在每个派生类中函数的实现方式却又各不相同,我们就可以在基类中的该函数返回类型前加上virtual,将它定义为虚函数,便于我们在派生类里面根据我们自己的需求,将其改成我们需要的样子,举个例子:

class Bulk_qutoe:public Qutoe//打折后的书籍
{
public:
  double net_price(size_t n)
  {
    return 0;
  }
};
class Last_qutoe:public Qutoe
{
public:
  double net_price(size_t n)
  {
    n = 100 * 3;
    return n;
  }
};

虽然类写的简单,但是我们可以发现两个类里面同一个函数实现方法完全不一样,我们可以在不同的派生类对基类的虚函数进行覆盖。

现在我们再将目光放到我们的动态绑定上面,通过动态绑定我们可以通过同一段代码分别处理基类和派生类的对象

double Print(ostream& cout,const Qutoe& q,size_t p)
{
  double res = q.net_price(p);
  return res;
}

这里有一个非常有意思的事情,当我们对函数进行不同参数的输入,如:、

int main()
{
  Qutoe basic;
  Bulk_qutoe bulk;
  double n1, n2;
  Print(cout, basic, n1);
  Print(cout, bulk, n1);
  return 0;
}

当我们对Print函数里面输入不同类型的对象basi、bulk,所调用的net_price的版本就不相同,这种函数的运行版本由实参决定,在运行时选择函数的版本,叫动态绑定。

定义基类和派生类

定义基类
class Quote
{
public:
    Quote() =default;
    Quote(double size_price,const string& number):size_price(size_price),m_number(number) 
    {
    }
    string IseN()
    {
        return m_number;
    }
    virtual double Total_price(double size_price,int n)
    {
        return n*size_price;
    }
    virtual ~Quote() =default;
    private:
    string m_number;
    protected:
    double size_price=0.0;
};

对上面的基类我们进行了扩写,得到了上面的代码,对上面的的代码接下来我们作一些讲解:

1.Quote() =default;这个是将构造函数设为默认拷贝构造函数

2.virtual ~Quote() =default;这里是为了使用virtual关键字来声明析构函数,当我们将析构函数声明为虚函数时,它允许通过基类指针或引用来调用派生类对象的析构函数。而这对于使用继承和多态的情况非常重要。当基类指针指向派生类对象时,如果基类的析构函数不声明为虚函数,那么在使用基类指针删除对象时,只会调用基类的析构函数,而不会调用派生类的析构函数,从而导致派生类对象中的资源没有得到正确释放。这可能会导致内存泄漏或其他未定义的行为,为了确保在使用基类指针或引用删除对象时调用正确的派生类析构函数,我们需要在基类中将析构函数声明为虚函数。这样,在删除对象时,会根据指针或引用所指向的对象的实际类型,调用相应的析构函数,确保正确释放资源。

定义派生类
class Bulk_Qutoe:public Quote
{
public:
    Bulk_Qutoe()=default;
    Bulk_Qutoe(double,const string&,int,double);
    double Total_price(double size_price,int book_number)  const  overrider;
private:
    double discount;
    int book_number;
    string book_name;
};
派生类中的虚函数

派生类经常会根据自身需求来覆盖掉基类里面的虚函数,当虚函数没有选择覆盖掉虚函数,该虚函数将会作为一位普通成员被派生类所继承

派生类对象以及派生类到基类的类型转换

在一个派生类中分为两个部分,一个是派生类里面自己的定义的成员(非静态对象)的子对象,而另一部分则是从其他基类所继承对应的子对象,如图所示:

因为派生类里面含有与基类对应的组成部分,所以我们可以将派生对象当作基类对象来使用,同时我们也可以将基类对象的指针或者引用绑定到派生类的基类部分上,如下所示:

Qutoe item //基类对象
Bulk_Qutoe  bulk//派生类对象
Quote* p = &item//指向基类的指针p
p = &bulk;//p改指向派生类里面从基类里面继承过来的部分
Quote &r=bulk//将r与派生类里面继承的部分绑定在一起

这种转换就是派生类到基类的类型转换,通过它我们可以将派生类对象或派生类对象的引用用在需要基类引用的地方,基类指针也是同样的道理

派生类构造函数

虽然派生类里面含有从基类那边继承过来的成员,但是这部分成员不能使用派生类的构造函数来对该部分成员进行初始化,仍然需要对这一部分成员用基类构造函数进行初始化,以上图的Bulk_Qutoe为例:

class Quote
{
public:
    Quote(const string& name,double p,string No):book(name),price(p),book_ISBN(No)
    {
    }
    virtual double net_price(size_t n,double price)
    {
        return n*price;
    }
    Quote(double p,string No):price(p),book_ISBN(No)
    {}
    virtual ~Quote()=default;
private:
    string book;
protected:
    string book_ISBN;//书的编号
    double price;
};
class Bulk_Quote:protected Quote
{
private:
    size_t min_qry;
    double discount;
    string book_name;
public:
    Bulk_Quote(const string& name,string book_ISBN,double price,size_t qry,double dis):Quote(price,book_ISBN),book_name(name),min_qry(qry),discount(dis)
    {}
    double net_price(size_t n,double price)
    {
        if(n>min_qry)  price*=discount;
        return n*price;
    }
    ~Bulk_Quote()
    {}
};

如上所示,派生类的从基类继承过来的部分仍然是在基类的构造函数内完成的初始化

继承与静态成员

如果基类定义出了一个静态成员,那在整个继承体系中该静态成员只能有该成员的唯一定义,无论派生出多少派生类,每个静态成员只存在唯一的定义,同时静态成员变量遵循通用的访问控制规则。

相关文章
|
开发框架 前端开发 JavaScript
基于Admin.NET框架的前端的一些改进和代码生成处理(2)
基于Admin.NET框架的前端的一些改进和代码生成处理(2)
|
SQL 存储 数据管理
掌握SQL Server Integration Services (SSIS)精髓:从零开始构建自动化数据提取、转换与加载(ETL)流程,实现高效数据迁移与集成——轻松上手SSIS打造企业级数据管理利器
【8月更文挑战第31天】SQL Server Integration Services (SSIS) 是 Microsoft 提供的企业级数据集成平台,用于高效完成数据提取、转换和加载(ETL)任务。本文通过简单示例介绍 SSIS 的基本使用方法,包括创建数据包、配置数据源与目标以及自动化执行流程。首先确保安装了 SQL Server Data Tools (SSDT),然后在 Visual Studio 中创建新的 SSIS 项目,通过添加控制流和数据流组件,实现从 CSV 文件到 SQL Server 数据库的数据迁移。
3703 0
|
JavaScript Serverless API
Serverless 应用引擎操作报错合集之在Serverless 应用引擎中,FC3.0读取response body的时候出现错误提示"Caused by: java.io.IOException: closed"如何解决
Serverless 应用引擎(SAE)是阿里云提供的Serverless PaaS平台,支持Spring Cloud、Dubbo、HSF等主流微服务框架,简化应用的部署、运维和弹性伸缩。在使用SAE过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
360 3
|
Java C语言 C++
从C语言到C++④(第二章_类和对象_上篇)->类->封装->this指针(上)
从C语言到C++④(第二章_类和对象_上篇)->类->封装->this指针
84 0
|
存储 数据管理 对象存储
云存储Clouder认证:存储应用与数据管理—课时10:实验练习与认证考试
云存储Clouder认证:存储应用与数据管理—课时10:实验练习与认证考试
|
供应链 安全 Java
安全同学讲Maven间接依赖场景的仲裁机制
去年的Log4j-core的安全问题,再次把供应链安全推向了高潮。在供应链安全的场景,蚂蚁集团在静态代码扫描平台-STC和资产威胁透视平台-哈勃这2款产品在联合合作下,优势互补,很好的解决了直接依赖和间接依赖的场景。但是由于STC是基于事前,受限于扫描效率存在遗漏的风险面,而哈勃又是基于事后,存在修复时间上的风险。基于此,笔者尝试寻找一种方式可以同时解决2款产品的短板。
安全同学讲Maven间接依赖场景的仲裁机制
|
Java API Scala
【JDK新特性】一篇搞懂Lambda表达式 & 函数式接口
【JDK新特性】一篇搞懂Lambda表达式 & 函数式接口
|
算法
uva 11549 CALCULATOR CONUNDRUM
题目链接 刘汝佳算法竞赛经典入门训练指南p42
59 0
|
Shell 开发工具 git
Hexo系列(五) 撰写文章
Hexo系列(五) 撰写文章
195 0
|
BI 数据安全/隐私保护