C++基础知识(六:继承)

首先我们应该知道C++的三大特性就是封装、继承和多态。

此篇文章将详细的讲解继承的作用和使用方法。

  • 继承

一个类,继承另一个已有的类,创建的过程

父类(基类)派生出子类(派生类)的过程

继承提高了代码的复用性

【1】继承的格式

class 类名:父类名
{};

【2】继承的权限

class 类名:继承的权限 父类名
{};

如果不写继承方式,默认是私有继承
父类中的权限      public|private|protected  public|private|protected   public|private|protected              
继承方式                 public                    private                   protected
子类中的权限      public|不能访问|protected  private|不能访问|private    protected|不能访问|protected

【3】继承时类中的特殊成员函数

特殊的成员函数不会被继承

构造函数:

  • 需要在子类中显性调用父类的构造函数(初始化列表中)(透传构造)
  • 透传构造
  • 继承构造
  • 委托构造

需要在子类中显性调用父类构造函数的场合:

父类中只有有参构造  ----->子类在创建类对象时,必须手动调用父类的构造函数

#include <iostream>

using namespace std;

class Father
{
public:
    int age;
    char c;
    Father(int a,char c):age(a),c(c){cout << "Father有参" << endl;}
};

class Child:public Father    //----->私有继承
{
    int high;
public:
    void show()
    {
        cout << c << endl;
    }
};

int main()
{
    //Child c1;  //error,因为父类只有有参构造,而子类中没有提供能够调用父类有参构造的构造函数,不能成功创建父类的空间
    //Father f1;
    c1.age;
    cout << sizeof (Father) << endl;
    cout << sizeof (Child) << endl;
    return 0;
}

i)透传构造

在子类构造函数的初始化列表中,显性调用父类的构造函数

ii)继承构造

C++支持

不用在子类中再写一遍父类的构造函数

使用:using Father::Father; ----->在子类中使用父类的构造函数

直接使用继承构造的方式,不能对子类成员初始化

继承构造本质上并不是把父类中的构造函数继承给子类,编译器自动根据父类中构造函数的格式,提供出派生的构造函数(个数和参数都和父类中的构造函数一致),主要还是通过透传构造创建父类的空间

#include <iostream>
using namespace std;

class Father
{
public:
    int age;
    char c;
//    Father(){cout << "Father无参" << endl;}
    Father(int a,char c):age(a),c(c){cout << "Father有参两个参数" << endl;}
    Father(char c):c(c){cout << "Father有参一个参数的" << endl;}
    Father(Father &other):age(other.age),c(other.c)
    {cout << "Father拷贝" << endl;}
};

class Child:public Father    //----->私有继承
{
private:
    int high;
    //父类中的public成员age,通过公有继承,仍然是public
    using Father::age;   //把父类中公有继承下来的age成员,在子类中改成私有权限
public:
    void show()
    {
        cout << c << endl;
    }
    //子类的无参构造,但是显性调用父类的有参构造还给了默认值
    //透传构造
//    Child():Father(12,'a'){cout << "Child无参构造" << endl;}
//    Child(int a,char c,int h):Father(a,c),high(h)
//    {cout << "Child有参构造" << endl;}

    //父类中的所有构造函数,都被继承到了子类中
    using Father::Father;   //更高效一些
};

int main()
{
    Child c1(10);
    Child c2(20,'z');
    Child c3 = c2;
    //Father f1;
    //c1.age;
    cout << sizeof (Father) << endl;
    cout << sizeof (Child) << endl;
    return 0;
}

iii)委托构造

一个类的情况,并不直接通过无参构造实例化对象,而是无参构造委托了有参构造,实例化对象

继承时的情况

    Child():Child(10){cout << "Child无参构造" << endl;}   //Child c1
    Child(int a):Father(12,'a'),high(a)
    {cout << "Child有参构造一个参数" << endl;}

iv)拷贝构造

需要在初始化列表中显性调用父类的拷贝构造,传other对象到父类的拷贝构造中

Father(Father &other):age(other.age),c(other.c){cout << "Father的拷贝构造" << endl;}
Child(Child &other):Father(other),high(other.high){}

【4】继承时构造和析构的时机

继承关系,可以理解为包含关系

子类在继承父类时,会把父类中的成员保留一份,再来创建子类自己的成员

父类先构造,子类后构造

子类先析构,父类后析构

#include <iostream>

using namespace std;
class F
{
    int *p;
public:
    F():p(new int){cout << "F无参构造" << endl;}
    ~F()
    {
        delete p;
        cout << "F析构函数" << endl;
    }
};
class C:public F
{
    int *p;
public:
    C():p(new int){cout << "C无参构造" << endl;}
    ~C()
    {
        delete p;
        cout << "C析构函数" << endl;
    }
};

int main()
{
    C *p1 = new C;
    delete p1;   //空间释放时,会自动调用析构函数,无需手动调用
    p1 = nullptr;
    return 0;
}

【5】父子类中存在同名成员问题

访问时不会发生冲突,默认访问子类的

#include <iostream>
using namespace std;
class F
{
public:
    int *p;
    F():p(new int){cout << "F无参构造" << endl;}
    ~F()
    {
        delete p;
        cout << "F析构函数" << endl;
    }
};
class C:public F
{
public:
    int *p;
    C():p(new int){cout << "C无参构造" << endl;}
    ~C()
    {
        delete p;
        cout << "C析构函数" << endl;
    }
};

int main()
{
    C *p1 = new C;
    *(p1->p) = 90;
    cout << *(p1->p) << endl;   //子类成员和父类成员同名,默认优先访问子类成员
    cout << *(p1->F::p) << endl;  //通过域限定符访问父类的成员
    delete p1;   //空间释放时,会自动调用析构函数,无需手动调用
    p1 = nullptr;
    return 0;
}
  • 多重继承

一个子类,继承自多个基类

【1】格式

class 类名:继承权限 父类名,继承权限 父类名····
{}

【2】当多个父类中包含同名成员

多个父类中包含同名成员,通过域限定符访问指定的父类中成员

#include <iostream>

using namespace std;

class Room
{
public:
    void clean()
    {
        cout << "打扫房间" << endl;
    }
};
class BedRoom
{
public:
    void play()
    {
        cout << "可以玩游戏" << endl;
    }
    void clean()
    {
        cout << "打扫卧室" << endl;
    }
};

//Home类公共继承字Room和BedRoom类
class Home:public Room,public BedRoom
{
};

int main()
{
    Home h1;
    h1.play();
    h1.Room::clean();
    h1.BedRoom::clean();
    return 0;
}
  • 菱形继承(钻石继承)

【1】格式

     A                ----->公共基类
   /   \
  B     C             ------>中间子类
   \   /
     D                ------>汇集子类

汇集子类中,会包含两份公共基类中的内容

【2】菱形继承存在的问题

  1. 会发生二义性的问题(同一个变量或者函数,可以通过两种方法访问)
  2. 如果公共基类,过大,会造成汇集子类中的代码膨胀/冗余
#include <iostream>

using namespace std;
class A
{
public:
    int a;
    //A(int a):a(a){cout << "A" << endl;}
};

class B:public A
{
public:
    int c;
    //B(int a,int c):A(a),c(c){cout << "B" << endl;}
};

class C:public A
{
public:
    //C(int a):A(a){cout << "C" << endl;}
};

class D:public C,public B
{
public:
    //D(int a,int c):B(a,c),C(a),A(a){cout << "D" << endl;}
};

int main()
{
    D d1;
    d1.B::= 90;   //二义性,还可以直接通过中间子类访问,直接访问B中的a成员
    //cout << d1.C::A::a << endl;  //会发生二义性,因为访问A,但是有两条路径都访问到A
    return 0;
}

【3】虚继承(virtual)

虚继承指对公共基类的虚继承。

主要用于解决菱形继承问题,

采用虚继承后,公共基类中的内容,只会在汇集子类中存在一份,在汇集子类中,可以通过任意一条路径访问到公共基类中的成员

#include <iostream>

using namespace std;
class A
{
public:
    int a;
};

class B:virtual public A
{
public:
    int c;
};

class C:virtual public A
{

};

class D:public B,public C
{

};

int main()
{
    D d1;
    d1.B::A::= 90;
    cout << d1.C::A::<< endl;
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Leetcode】2583. 二叉树中的第 K 大层和

文章目录 题目思路代码结果 题目 题目链接 给你一棵二叉树的根节点 root 和一个正整数 k 。 树中的 层和 是指 同一层 上节点值的总和。 返回树中第 k 大的层和&#xff08;不一定不同&#xff09;。如果树少于 k 层&#xff0c;则返回 -1 。 注意&#xff0c;如果两个节点与根…

Houdini_RBD_刚体约束

仍然是看视频的笔记&#xff0c;摸着大佬们过河。有点杂有点乱&#xff0c;如有错误&#xff0c;多多指教。原视频链接&#xff1a;rbd_CONSTRAINT01_哔哩哔哩_bilibili 文章/笔记个人推荐&#xff1a; 1、知乎刘鹏云_RBD 2、感谢R姐的无偿pdf笔记分享——哔哩哔哩Rosarita_Art…

C++入门学习(三十六)函数的声明

程序是自上而下运行的&#xff0c;比如我下面的代码&#xff1a; #include <iostream> #include<string> using namespace std;int main() { int a1; int b2;int sumaddNumbers(a,b); cout<<sum;return 0; }int addNumbers(int a, int b) { int sum …

ONLYOFFICE桌⾯应⽤程序v8.0:功能丰富,⽀持多平台

文章目录 可填写的 PDF 表单RTL支持电子表格中的新增功能其他改进和新增功能与 Moodle 集成用密码保护 PDF 文件快速创建文档本地界面主题总结 继 ONLYOFFICE 文档 v8.0 的发布后&#xff0c;很高兴&#xff0c;因为适用于 Linux、Windows 和 macOS 的 ONLYOFFICE 桌面应用程序…

Android studio 安装以及第一个程序

一、配置 1、下载JDK&#xff08;JDK&#xff1a;Java Development Kit Java开发工具包&#xff09; 打开Java Downloads | Oracle下载地址下载相应的JDK版本即可&#xff0c;需要注意的是请下载JDK11以上的版本&#xff0c;并且是64位版 2、安装JDK 双击打开已经下载好的安装…

复刻大模型 Sora 有多难?一张图带你读懂 Sora 的技术路径

近日&#xff0c;OpenAI 发布了视频生成模型Sora&#xff0c;最大的Sora模型能够生成一分钟的高保真视频。同时OpenAI称&#xff0c;可扩展的视频生成模型&#xff0c;是构建物理世界通用模拟器的一条可能的路径。 Sora 能够生成横屏1920*1080视频&#xff0c;竖屏1080*1920视…

MATLAB练习题:估计离开家之前能拿到报纸的概率

​讲解视频&#xff1a;可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。​ MATLAB教程新手入门篇&#xff08;数学建模清风主讲&#xff0c;适合零基础同学观看&#xff09;_哔哩哔哩_bilibili 清风订了一份报纸&#xff0c;送报人可能在早上6&#xff1a;…

【论文精读】OS-Copilot: Towards Generalist Computer Agents with Self-Improvement

OS-Copilot: Towards Generalist Computer Agents with Self-Improvement 前言ABSTRACT1 INTRODUCTION2 THE OS-COPILOT FRAMEWORK2.1 PLANNER2.2 CONFIGURATOR2.2.1 DECLARATIVE MEMORY2.2.2 PROCEDURAL MEMORY2.2.3 WORKING MEMORY 2.3 ACTOR 3 THE FRIDAY AGENT3.1 A RUNNIN…

JavaScript原型继承与面向对象编程思想

原型继承与面向对象编程思想 在JavaScript中&#xff0c;原型(prototype)、构造函数(constructor)和实例对象(instance)是面向对象编程中的重要概念&#xff0c;并且它们之间存在着紧密的关系。 原型(prototype)&#xff1a;原型是JavaScript中对象之间关联的一种机制。每个Ja…

Clickhouse系列之连接工具连接、数据类型和数据库

基本操作 一、使用连接工具连接二、数据类型1、数字类型IntFloatDecimal 2、字符串类型StringFixedStringUUID 3、时间类型DateTimeDateTime64Date 4、复合类型ArrayEnum 5、特殊类型Nullable 三、数据库 一、使用连接工具连接 上一篇介绍了clickhouse的命令行登录&#xff0c…

mysql 事务详解一

前言 提到事务&#xff0c;大家肯定不陌生。在我们现实生活中也是存在的&#xff0c;比如我们去超市购物&#xff0c;然后去支付。虽然是两个步骤&#xff0c;必须保证同时成功&#xff0c;这个交易才可以完成。 如果这个场景&#xff0c;拿到我们购物系统&#xff0c;就是几…

【kubernetes】kubeadm部署k8s集群(3主3从+keepalived/nginx负载均衡高可用)

目录 一、完成系统初始化 步骤一&#xff1a;常规环境初始化 步骤二&#xff1a;内核版本升级以及内核限制文件参数修改 步骤三&#xff1a;提前准备好负载均衡器和keepalived(接着之前的二进制部署修改的) 二、所有节点部署docker&#xff0c;以及指定版本的kubeadm 步骤…

大厂面试-美团高频考察算法之重排链表

本文学习目标或巩固的知识点 学习如何处理链表重排类题目 巩固反转链表巩固快慢指针巩固合并链表 提前说明&#xff1a;算法题目来自力扣、牛客等等途径 &#x1f7e2;表示简单 &#x1f7e1;表示中等 &#x1f534;表示困难 &#x1f92e;表示恶心 博主真实经历&#xff0c;…

pikachu靶场-File Inclusion

介绍&#xff1a; File Inclusion(文件包含漏洞)概述 文件包含&#xff0c;是一个功能。在各种开发语言中都提供了内置的文件包含函数&#xff0c;其可以使开发人员在一个代码文件中直接包含&#xff08;引入&#xff09;另外一个代码文件。 比如 在PHP中&#xff0c;提供了&…

unity学习(40)——创建(create)角色脚本(panel)——UI

1.点击不同的头像按钮&#xff0c;分别选择职业1和职业2&#xff0c;create脚本中对应的函数。 2.调取inputfield中所输入的角色名&#xff08;限制用户名长度为7字符&#xff09;&#xff0c;但愿逆向的服务器可以查重名&#xff1a; 3.点击头衔&#xff0c;显示选择的职业&a…

二手货wordpress企业网站主题模板

二手车wordpress主题模板 简洁的二手车wordpress主题模板&#xff0c;适合做二手车业务的公司官方网站使用。 https://www.jianzhanpress.com/?p3473 wordpress二手物资回收主题 绿色wordpress二手物资回收主题&#xff0c;用于二手物资回收公司WP建站使用。 https://www.…

算法【查找算法的概念】

查找算法概念 1、查找的基本概念2、评价查找算法3、问题: 查找过程中我们要研究什么? 1、查找的基本概念 查找的概念&#xff1a; 根据给定的某个值&#xff0c;在查找表中确定一个其关键字等于给定值的数据元素或者记录。 查找算法也可以叫搜索算法。查找算法就是从一个有序…

HTMLElement.click()的回调触发踩坑

先看看以下代码 const el document.getElementById("btn") el.addEventListener("click", () > {Promise.resolve().then(() > console.log("microtask 1"));console.log("1"); }); el.addEventListener("click", (…

深度学习基础——U-Net图像分割

图像分割&#xff0c;就是根据图像的某种相似性特征(如亮度、颜色、纹理、面积、形状、位置、局部统计特征或频谱特征等&#xff09;将医学图像划分为若干个互不相交的“连通”区域。 相关特征在同一区域内表现出一致性或相似性&#xff0c;而在不同区域间表现出明显的…

yolov8-seg dnn调用

接上篇一直更换torch、opencv版本都无法解决这个问题&#xff08;seg调用dnn报错&#xff09;。那问题会不会出在yolov8源码本身呢。yolov8的讨论区基本都看过了&#xff0c;我决定尝试在其前身yolov5的讨论区上找找我不信没人遇到这个问题。很快找到下面的讨论第一个帖子&…